@neo-one/server-plugin-wallet
Version:
NEO•ONE Server wallet plugin.
255 lines (253 loc) • 37.6 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const client_common_1 = require("@neo-one/client-common");
const client_core_1 = require("@neo-one/client-core");
const client_full_core_1 = require("@neo-one/client-full-core");
const server_plugin_1 = require("@neo-one/server-plugin");
const server_plugin_network_1 = require("@neo-one/server-plugin-network");
const utils_1 = require("@neo-one/utils");
const fs = tslib_1.__importStar(require("fs-extra"));
const path = tslib_1.__importStar(require("path"));
const rxjs_1 = require("rxjs");
const operators_1 = require("rxjs/operators");
const constants_1 = require("./constants");
const errors_1 = require("./errors");
const getRPCURL = (network) => {
if (network === undefined) {
return undefined;
}
if (network.state === 'started') {
const readyNode = network.nodes.find((node) => node.ready);
if (readyNode !== undefined) {
return readyNode.rpcAddress;
}
}
return network.nodes[0].rpcAddress;
};
const updateClient = ({ networkName, network, client, }) => {
let rpcURL = getRPCURL(network);
if (rpcURL === undefined && networkName === server_plugin_network_1.constants.NETWORK_NAME.MAIN) {
rpcURL = constants_1.constants.MAIN_URL;
}
if (rpcURL === undefined) {
throw new errors_1.NetworkRequiredError();
}
client.providers.file.provider.addNetwork({
network: networkName,
rpcURL,
});
return new client_full_core_1.ReadClient(new client_core_1.NEOONEDataProvider({
network: networkName,
rpcURL,
}));
};
const getNetwork$ = ({ networkName, pluginManager, }) => pluginManager
.getResourcesManager({
plugin: server_plugin_network_1.constants.PLUGIN,
resourceType: server_plugin_network_1.constants.NETWORK_RESOURCE_TYPE,
})
.getResource$({
name: networkName,
options: {},
});
const WALLET_PATH = 'wallet.json';
class WalletResource {
static async createNew({ client, pluginManager, resourceType, name, privateKey: privateKeyIn, password, dataPath, }) {
const { name: baseName, names: [networkName], } = server_plugin_1.compoundName.extract(name);
const network = await getNetwork$({ networkName, pluginManager })
.pipe(operators_1.take(1))
.toPromise();
if (network === undefined &&
!(networkName === server_plugin_network_1.constants.NETWORK_NAME.MAIN || networkName === server_plugin_network_1.constants.NETWORK_NAME.TEST)) {
throw new errors_1.NetworkRequiredError();
}
const readClient = updateClient({ networkName, network, client });
const privateKey = privateKeyIn === undefined ? client_common_1.createPrivateKey() : privateKeyIn;
const address = client_common_1.privateKeyToAddress(privateKey);
const walletPath = this.getWalletPath(dataPath);
return new WalletResource({
client,
readClient,
pluginManager,
resourceType,
name,
baseName,
networkName,
address,
dataPath,
walletPath,
clientNetworkType: networkName,
initial: {
privateKey,
password,
},
});
}
static async createExisting({ client, pluginManager, resourceType, name, dataPath, }) {
const { name: baseName, names: [networkName], } = server_plugin_1.compoundName.extract(name);
const network = await getNetwork$({ networkName, pluginManager })
.pipe(operators_1.take(1))
.toPromise();
const readClient = updateClient({ networkName, network, client });
const walletPath = this.getWalletPath(dataPath);
const { address } = await fs.readJSON(walletPath);
return new WalletResource({
client,
readClient,
pluginManager,
resourceType,
name,
baseName,
networkName,
address,
dataPath,
walletPath,
clientNetworkType: networkName,
});
}
static getWalletPath(dataPath) {
return path.resolve(dataPath, WALLET_PATH);
}
constructor({ client, readClient, pluginManager, resourceType, name, baseName, networkName, address, dataPath, walletPath, clientNetworkType, initial, }) {
this.client = client;
this.mutableReadClient = readClient;
this.resourceType = resourceType;
this.name = name;
this.baseName = baseName;
this.networkName = networkName;
this.address = address;
this.dataPath = dataPath;
this.walletPath = walletPath;
this.clientNetworkType = clientNetworkType;
this.mutableInitial = initial;
this.mutableBalance = [];
this.network$ = getNetwork$({ pluginManager, networkName });
this.resource$ = rxjs_1.combineLatest([this.network$, rxjs_1.timer(0, 5000)]).pipe(operators_1.concatMap(async (value) => {
await this.update(value[0]);
return this.toResource();
}), operators_1.shareReplay(1));
}
async create() {
if (this.mutableInitial === undefined) {
throw new Error('Something went wrong.');
}
const { privateKey, password } = this.mutableInitial;
await this.client.providers.file.keystore.addUserAccount({
network: this.clientNetworkType,
name: this.baseName,
privateKey,
password,
});
this.mutableInitial = undefined;
await fs.ensureDir(path.dirname(this.walletPath));
await fs.writeJSON(this.walletPath, { address: this.address });
}
async delete() {
await this.client.providers.file.keystore.deleteUserAccount(this.walletID);
await fs.remove(this.dataPath);
}
get walletID() {
return {
network: this.clientNetworkType,
address: this.address,
};
}
get wallet() {
return this.client.providers.file.keystore.getWallet(this.walletID);
}
get unlocked() {
return this.wallet.type === 'unlocked';
}
async unlock({ password }) {
await this.client.providers.file.keystore.unlockWallet({
id: this.walletID,
password,
});
}
async lock() {
await this.client.providers.file.keystore.lockWallet(this.walletID);
}
get wif() {
if (this.wallet.type === 'locked') {
return undefined;
}
return client_common_1.privateKeyToWIF(this.wallet.privateKey);
}
getDebug() {
const table = [
['Data Path', this.dataPath],
['Wallet Path', this.walletPath],
];
return table.concat(Object.entries(this.toResource()).map(([key, val]) => {
if (val === undefined) {
return [key, 'null'];
}
return [key, typeof val === 'string' ? val : JSON.stringify(val, undefined, 2)];
}));
}
toResource() {
return {
plugin: this.resourceType.plugin.name,
resourceType: this.resourceType.name,
name: this.name,
baseName: this.baseName,
state: this.unlocked ? 'started' : 'stopped',
network: this.networkName,
accountID: {
network: this.networkName,
address: this.address,
},
address: this.address,
unlocked: this.unlocked,
neoBalance: this.mutableNeoBalance === undefined ? 'Unknown' : this.mutableNeoBalance,
gasBalance: this.mutableGasBalance === undefined ? 'Unknown' : this.mutableGasBalance,
wif: this.wif,
nep2: this.wallet.nep2,
publicKey: this.wallet.userAccount.publicKey,
balance: this.mutableBalance,
};
}
async update(network) {
if (network !== undefined && network.nodes.some((node) => node.ready)) {
this.mutableReadClient = updateClient({
networkName: this.networkName,
network,
client: this.client,
});
try {
const account = await this.mutableReadClient.getAccount(this.address);
let neoBalance = '0';
let gasBalance = '0';
this.mutableBalance = await Promise.all(Object.entries(account.balances).map(async ([assetHash, amount]) => {
const asset = await this.mutableReadClient.getAsset(assetHash);
let { name } = asset;
if (asset.hash === client_common_1.common.NEO_ASSET_HASH) {
name = 'NEO';
neoBalance = amount.toString();
}
if (asset.hash === client_common_1.common.GAS_ASSET_HASH) {
name = 'GAS';
gasBalance = amount.toString();
}
return {
assetName: name,
asset: assetHash,
amount: amount.toString(),
};
}));
this.mutableNeoBalance = neoBalance;
this.mutableGasBalance = gasBalance;
}
catch (error) {
this.resourceType.plugin.monitor.withData({ [utils_1.labels.NEO_ADDRESS]: this.address }).logError({
name: 'neo_wallet_resource_update_wallet',
message: `Failed to update wallet ${this.address}`,
error,
});
}
}
}
}
exports.WalletResource = WalletResource;
//# sourceMappingURL=data:application/json;charset=utf8;base64,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LElBQUksQ0FBQyxpQkFBaUIsR0FBRyxVQUFVLENBQUM7Z0JBQ3BDLElBQUksQ0FBQyxpQkFBaUIsR0FBRyxVQUFVLENBQUM7YUFDckM7WUFBQyxPQUFPLEtBQUssRUFBRTtnQkFDZCxJQUFJLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQyxjQUFNLENBQUMsV0FBVyxDQUFDLEVBQUUsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUMsUUFBUSxDQUFDO29CQUN6RixJQUFJLEVBQUUsbUNBQW1DO29CQUN6QyxPQUFPLEVBQUUsMkJBQTJCLElBQUksQ0FBQyxPQUFPLEVBQUU7b0JBQ2xELEtBQUs7aUJBQ04sQ0FBQyxDQUFDO2FBQ0o7U0FDRjtJQUNILENBQUM7Q0FDRjtBQW5TRCx3Q0FtU0MiLCJmaWxlIjoibmVvLW9uZS1zZXJ2ZXItcGx1Z2luLXdhbGxldC9zcmMvV2FsbGV0UmVzb3VyY2UuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBjb21tb24sXG4gIGNyZWF0ZVByaXZhdGVLZXksXG4gIE5ldHdvcmtUeXBlIGFzIENsaWVudE5ldHdvcmtUeXBlLFxuICBwcml2YXRlS2V5VG9BZGRyZXNzLFxuICBwcml2YXRlS2V5VG9XSUYsXG59IGZyb20gJ0BuZW8tb25lL2NsaWVudC1jb21tb24nO1xuaW1wb3J0IHsgTG9jYWxXYWxsZXQsIE5FT09ORURhdGFQcm92aWRlciB9IGZyb20gJ0BuZW8tb25lL2NsaWVudC1jb3JlJztcbmltcG9ydCB7IFJlYWRDbGllbnQgfSBmcm9tICdAbmVvLW9uZS9jbGllbnQtZnVsbC1jb3JlJztcbmltcG9ydCB7IGNvbXBvdW5kTmFtZSwgRGVzY3JpYmVUYWJsZSwgUGx1Z2luTWFuYWdlciB9IGZyb20gJ0BuZW8tb25lL3NlcnZlci1wbHVnaW4nO1xuaW1wb3J0IHsgY29uc3RhbnRzIGFzIG5ldHdvcmtDb25zdGFudHMsIE5ldHdvcmsgfSBmcm9tICdAbmVvLW9uZS9zZXJ2ZXItcGx1Z2luLW5ldHdvcmsnO1xuaW1wb3J0IHsgbGFiZWxzIH0gZnJvbSAnQG5lby1vbmUvdXRpbHMnO1xuaW1wb3J0ICogYXMgZnMgZnJvbSAnZnMtZXh0cmEnO1xuaW1wb3J0ICogYXMgcGF0aCBmcm9tICdwYXRoJztcbmltcG9ydCB7IGNvbWJpbmVMYXRlc3QsIE9ic2VydmFibGUsIHRpbWVyIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBjb25jYXRNYXAsIHNoYXJlUmVwbGF5LCB0YWtlIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHsgY29uc3RhbnRzIH0gZnJvbSAnLi9jb25zdGFudHMnO1xuaW1wb3J0IHsgTmV0d29ya1JlcXVpcmVkRXJyb3IgfSBmcm9tICcuL2Vycm9ycyc7XG5pbXBvcnQgeyBSZWFkV2FsbGV0Q2xpZW50LCBXYWxsZXRDbGllbnQgfSBmcm9tICcuL3R5cGVzJztcbmltcG9ydCB7IENvaW4sIFdhbGxldCwgV2FsbGV0UmVzb3VyY2VUeXBlIH0gZnJvbSAnLi9XYWxsZXRSZXNvdXJjZVR5cGUnO1xuXG5jb25zdCBnZXRSUENVUkwgPSAobmV0d29yaz86IE5ldHdvcmsgfCB1bmRlZmluZWQpOiBzdHJpbmcgfCB1bmRlZmluZWQgPT4ge1xuICBpZiAobmV0d29yayA9PT0gdW5kZWZpbmVkKSB7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxuXG4gIGlmIChuZXR3b3JrLnN0YXRlID09PSAnc3RhcnRlZCcpIHtcbiAgICBjb25zdCByZWFkeU5vZGUgPSBuZXR3b3JrLm5vZGVzLmZpbmQoKG5vZGUpID0+IG5vZGUucmVhZHkpO1xuICAgIGlmIChyZWFkeU5vZGUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgcmV0dXJuIHJlYWR5Tm9kZS5ycGNBZGRyZXNzO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBuZXR3b3JrLm5vZGVzWzBdLnJwY0FkZHJlc3M7XG59O1xuXG5jb25zdCB1cGRhdGVDbGllbnQgPSAoe1xuICBuZXR3b3JrTmFtZSxcbiAgbmV0d29yayxcbiAgY2xpZW50LFxufToge1xuICByZWFkb25seSBuZXR3b3JrTmFtZTogc3RyaW5nO1xuICByZWFkb25seSBuZXR3b3JrPzogTmV0d29yaztcbiAgcmVhZG9ubHkgY2xpZW50OiBXYWxsZXRDbGllbnQ7XG59KTogUmVhZFdhbGxldENsaWVudCA9PiB7XG4gIGxldCBycGNVUkwgPSBnZXRSUENVUkwobmV0d29yayk7XG4gIGlmIChycGNVUkwgPT09IHVuZGVmaW5lZCAmJiBuZXR3b3JrTmFtZSA9PT0gbmV0d29ya0NvbnN0YW50cy5ORVRXT1JLX05BTUUuTUFJTikge1xuICAgIHJwY1VSTCA9IGNvbnN0YW50cy5NQUlOX1VSTDtcbiAgfVxuXG4gIGlmIChycGNVUkwgPT09IHVuZGVmaW5lZCkge1xuICAgIHRocm93IG5ldyBOZXR3b3JrUmVxdWlyZWRFcnJvcigpO1xuICB9XG5cbiAgY2xpZW50LnByb3ZpZGVycy5maWxlLnByb3ZpZGVyLmFkZE5ldHdvcmsoe1xuICAgIG5ldHdvcms6IG5ldHdvcmtOYW1lLFxuICAgIHJwY1VSTCxcbiAgfSk7XG5cbiAgcmV0dXJuIG5ldyBSZWFkQ2xpZW50KFxuICAgIG5ldyBORU9PTkVEYXRhUHJvdmlkZXIoe1xuICAgICAgbmV0d29yazogbmV0d29ya05hbWUsXG4gICAgICBycGNVUkwsXG4gICAgfSksXG4gICk7XG59O1xuXG5jb25zdCBnZXROZXR3b3JrJCA9ICh7XG4gIG5ldHdvcmtOYW1lLFxuICBwbHVnaW5NYW5hZ2VyLFxufToge1xuICByZWFkb25seSBuZXR3b3JrTmFtZTogc3RyaW5nO1xuICByZWFkb25seSBwbHVnaW5NYW5hZ2VyOiBQbHVnaW5NYW5hZ2VyO1xufSk6IE9ic2VydmFibGU8TmV0d29yayB8IHVuZGVmaW5lZD4gPT5cbiAgcGx1Z2luTWFuYWdlclxuICAgIC5nZXRSZXNvdXJjZXNNYW5hZ2VyKHtcbiAgICAgIHBsdWdpbjogbmV0d29ya0NvbnN0YW50cy5QTFVHSU4sXG4gICAgICByZXNvdXJjZVR5cGU6IG5ldHdvcmtDb25zdGFudHMuTkVUV09SS19SRVNPVVJDRV9UWVBFLFxuICAgIH0pXG4gICAgLmdldFJlc291cmNlJCh7XG4gICAgICBuYW1lOiBuZXR3b3JrTmFtZSxcbiAgICAgIG9wdGlvbnM6IHt9LFxuICAgIH0pIGFzIE9ic2VydmFibGU8TmV0d29yayB8IHVuZGVmaW5lZD47XG5cbmludGVyZmFjZSBJbml0aWFsT3B0aW9ucyB7XG4gIHJlYWRvbmx5IHByaXZhdGVLZXk6IHN0cmluZztcbiAgcmVhZG9ubHkgcGFzc3dvcmQ/OiBzdHJpbmc7XG59XG5cbmludGVyZmFjZSBXYWxsZXRSZXNvdXJjZU9wdGlvbnMge1xuICByZWFkb25seSBjbGllbnQ6IFdhbGxldENsaWVudDtcbiAgcmVhZG9ubHkgcmVhZENsaWVudDogUmVhZFdhbGxldENsaWVudDtcbiAgcmVhZG9ubHkgcGx1Z2luTWFuYWdlcjogUGx1Z2luTWFuYWdlcjtcbiAgcmVhZG9ubHkgcmVzb3VyY2VUeXBlOiBXYWxsZXRSZXNvdXJjZVR5cGU7XG4gIHJlYWRvbmx5IG5hbWU6IHN0cmluZztcbiAgcmVhZG9ubHkgYmFzZU5hbWU6IHN0cmluZztcbiAgcmVhZG9ubHkgbmV0d29ya05hbWU6IHN0cmluZztcbiAgcmVhZG9ubHkgYWRkcmVzczogc3RyaW5nO1xuICByZWFkb25seSBkYXRhUGF0aDogc3RyaW5nO1xuICByZWFkb25seSB3YWxsZXRQYXRoOiBzdHJpbmc7XG4gIHJlYWRvbmx5IGNsaWVudE5ldHdvcmtUeXBlOiBDbGllbnROZXR3b3JrVHlwZTtcbiAgcmVhZG9ubHkgaW5pdGlhbD86IEluaXRpYWxPcHRpb25zO1xufVxuXG5pbnRlcmZhY2UgTmV3V2FsbGV0UmVzb3VyY2VPcHRpb25zIHtcbiAgcmVhZG9ubHkgY2xpZW50OiBXYWxsZXRDbGllbnQ7XG4gIHJlYWRvbmx5IHBsdWdpbk1hbmFnZXI6IFBsdWdpbk1hbmFnZXI7XG4gIHJlYWRvbmx5IHJlc291cmNlVHlwZTogV2FsbGV0UmVzb3VyY2VUeXBlO1xuICByZWFkb25seSBuYW1lOiBzdHJpbmc7XG4gIHJlYWRvbmx5IHByaXZhdGVLZXk/OiBzdHJpbmc7XG4gIHJlYWRvbmx5IHBhc3N3b3JkPzogc3RyaW5nO1xuICByZWFkb25seSBkYXRhUGF0aDogc3RyaW5nO1xufVxuXG5pbnRlcmZhY2UgRXhpc3RpbmdXYWxsZXRSZXNvdXJjZU9wdGlvbnMge1xuICByZWFkb25seSBjbGllbnQ6IFdhbGxldENsaWVudDtcbiAgcmVhZG9ubHkgcGx1Z2luTWFuYWdlcjogUGx1Z2luTWFuYWdlcjtcbiAgcmVhZG9ubHkgcmVzb3VyY2VUeXBlOiBXYWxsZXRSZXNvdXJjZVR5cGU7XG4gIHJlYWRvbmx5IG5hbWU6IHN0cmluZztcbiAgcmVhZG9ubHkgZGF0YVBhdGg6IHN0cmluZztcbn1cblxuY29uc3QgV0FMTEVUX1BBVEggPSAnd2FsbGV0Lmpzb24nO1xuXG5leHBvcnQgY2xhc3MgV2FsbGV0UmVzb3VyY2Uge1xuICBwdWJsaWMgc3RhdGljIGFzeW5jIGNyZWF0ZU5ldyh7XG4gICAgY2xpZW50LFxuICAgIHBsdWdpbk1hbmFnZXIsXG4gICAgcmVzb3VyY2VUeXBlLFxuICAgIG5hbWUsXG4gICAgcHJpdmF0ZUtleTogcHJpdmF0ZUtleUluLFxuICAgIHBhc3N3b3JkLFxuICAgIGRhdGFQYXRoLFxuICB9OiBOZXdXYWxsZXRSZXNvdXJjZU9wdGlvbnMpOiBQcm9taXNlPFdhbGxldFJlc291cmNlPiB7XG4gICAgY29uc3Qge1xuICAgICAgbmFtZTogYmFzZU5hbWUsXG4gICAgICBuYW1lczogW25ldHdvcmtOYW1lXSxcbiAgICB9ID0gY29tcG91bmROYW1lLmV4dHJhY3QobmFtZSk7XG5cbiAgICBjb25zdCBuZXR3b3JrID0gYXdhaXQgZ2V0TmV0d29yayQoeyBuZXR3b3JrTmFtZSwgcGx1Z2luTWFuYWdlciB9KVxuICAgICAgLnBpcGUodGFrZSgxKSlcbiAgICAgIC50b1Byb21pc2UoKTtcbiAgICBpZiAoXG4gICAgICBuZXR3b3JrID09PSB1bmRlZmluZWQgJiZcbiAgICAgICEobmV0d29ya05hbWUgPT09IG5ldHdvcmtDb25zdGFudHMuTkVUV09SS19OQU1FLk1BSU4gfHwgbmV0d29ya05hbWUgPT09IG5ldHdvcmtDb25zdGFudHMuTkVUV09SS19OQU1FLlRFU1QpXG4gICAgKSB7XG4gICAgICB0aHJvdyBuZXcgTmV0d29ya1JlcXVpcmVkRXJyb3IoKTtcbiAgICB9XG5cbiAgICBjb25zdCByZWFkQ2xpZW50ID0gdXBkYXRlQ2xpZW50KHsgbmV0d29ya05hbWUsIG5ldHdvcmssIGNsaWVudCB9KTtcbiAgICBjb25zdCBwcml2YXRlS2V5ID0gcHJpdmF0ZUtleUluID09PSB1bmRlZmluZWQgPyBjcmVhdGVQcml2YXRlS2V5KCkgOiBwcml2YXRlS2V5SW47XG4gICAgY29uc3QgYWRkcmVzcyA9IHByaXZhdGVLZXlUb0FkZHJlc3MocHJpdmF0ZUtleSk7XG5cbiAgICBjb25zdCB3YWxsZXRQYXRoID0gdGhpcy5nZXRXYWxsZXRQYXRoKGRhdGFQYXRoKTtcblxuICAgIHJldHVybiBuZXcgV2FsbGV0UmVzb3VyY2Uoe1xuICAgICAgY2xpZW50LFxuICAgICAgcmVhZENsaWVudCxcbiAgICAgIHBsdWdpbk1hbmFnZXIsXG4gICAgICByZXNvdXJjZVR5cGUsXG4gICAgICBuYW1lLFxuICAgICAgYmFzZU5hbWUsXG4gICAgICBuZXR3b3JrTmFtZSxcbiAgICAgIGFkZHJlc3MsXG4gICAgICBkYXRhUGF0aCxcbiAgICAgIHdhbGxldFBhdGgsXG4gICAgICBjbGllbnROZXR3b3JrVHlwZTogbmV0d29ya05hbWUsXG4gICAgICBpbml0aWFsOiB7XG4gICAgICAgIHByaXZhdGVLZXksXG4gICAgICAgIHBhc3N3b3JkLFxuICAgICAgfSxcbiAgICB9KTtcbiAgfVxuXG4gIHB1YmxpYyBzdGF0aWMgYXN5bmMgY3JlYXRlRXhpc3Rpbmcoe1xuICAgIGNsaWVudCxcbiAgICBwbHVnaW5NYW5hZ2VyLFxuICAgIHJlc291cmNlVHlwZSxcbiAgICBuYW1lLFxuICAgIGRhdGFQYXRoLFxuICB9OiBFeGlzdGluZ1dhbGxldFJlc291cmNlT3B0aW9ucyk6IFByb21pc2U8V2FsbGV0UmVzb3VyY2U+IHtcbiAgICBjb25zdCB7XG4gICAgICBuYW1lOiBiYXNlTmFtZSxcbiAgICAgIG5hbWVzOiBbbmV0d29ya05hbWVdLFxuICAgIH0gPSBjb21wb3VuZE5hbWUuZXh0cmFjdChuYW1lKTtcblxuICAgIGNvbnN0IG5ldHdvcmsgPSBhd2FpdCBnZXROZXR3b3JrJCh7IG5ldHdvcmtOYW1lLCBwbHVnaW5NYW5hZ2VyIH0pXG4gICAgICAucGlwZSh0YWtlKDEpKVxuICAgICAgLnRvUHJvbWlzZSgpO1xuICAgIGNvbnN0IHJlYWRDbGllbnQgPSB1cGRhdGVDbGllbnQoeyBuZXR3b3JrTmFtZSwgbmV0d29yaywgY2xpZW50IH0pO1xuXG4gICAgY29uc3Qgd2FsbGV0UGF0aCA9IHRoaXMuZ2V0V2FsbGV0UGF0aChkYXRhUGF0aCk7XG4gICAgY29uc3QgeyBhZGRyZXNzIH0gPSBhd2FpdCBmcy5yZWFkSlNPTih3YWxsZXRQYXRoKTtcblxuICAgIHJldHVybiBuZXcgV2FsbGV0UmVzb3VyY2Uoe1xuICAgICAgY2xpZW50LFxuICAgICAgcmVhZENsaWVudCxcbiAgICAgIHBsdWdpbk1hbmFnZXIsXG4gICAgICByZXNvdXJjZVR5cGUsXG4gICAgICBuYW1lLFxuICAgICAgYmFzZU5hbWUsXG4gICAgICBuZXR3b3JrTmFtZSxcbiAgICAgIGFkZHJlc3MsXG4gICAgICBkYXRhUGF0aCxcbiAgICAgIHdhbGxldFBhdGgsXG4gICAgICBjbGllbnROZXR3b3JrVHlwZTogbmV0d29ya05hbWUsXG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIHN0YXRpYyBnZXRXYWxsZXRQYXRoKGRhdGFQYXRoOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIHJldHVybiBwYXRoLnJlc29sdmUoZGF0YVBhdGgsIFdBTExFVF9QQVRIKTtcbiAgfVxuXG4gIHB1YmxpYyByZWFkb25seSByZXNvdXJjZSQ6IE9ic2VydmFibGU8V2FsbGV0PjtcbiAgcHJpdmF0ZSByZWFkb25seSBjbGllbnQ6IFdhbGxldENsaWVudDtcbiAgcHJpdmF0ZSBtdXRhYmxlUmVhZENsaWVudDogUmVhZFdhbGxldENsaWVudDtcbiAgcHJpdmF0ZSByZWFkb25seSByZXNvdXJjZVR5cGU6IFdhbGxldFJlc291cmNlVHlwZTtcbiAgcHJpdmF0ZSByZWFkb25seSBuYW1lOiBzdHJpbmc7XG4gIHByaXZhdGUgcmVhZG9ubHkgYmFzZU5hbWU6IHN0cmluZztcbiAgcHJpdmF0ZSByZWFkb25seSBuZXR3b3JrTmFtZTogc3RyaW5nO1xuICBwcml2YXRlIHJlYWRvbmx5IGFkZHJlc3M6IHN0cmluZztcbiAgcHJpdmF0ZSByZWFkb25seSBkYXRhUGF0aDogc3RyaW5nO1xuICBwcml2YXRlIHJlYWRvbmx5IHdhbGxldFBhdGg6IHN0cmluZztcbiAgcHJpdmF0ZSByZWFkb25seSBjbGllbnROZXR3b3JrVHlwZTogQ2xpZW50TmV0d29ya1R5cGU7XG4gIHByaXZhdGUgbXV0YWJsZUluaXRpYWw6IEluaXRpYWxPcHRpb25zIHwgdW5kZWZpbmVkO1xuICBwcml2YXRlIG11dGFibGVOZW9CYWxhbmNlOiBzdHJpbmcgfCB1bmRlZmluZWQ7XG4gIHByaXZhdGUgbXV0YWJsZUdhc0JhbGFuY2U6IHN0cmluZyB8IHVuZGVmaW5lZDtcbiAgcHJpdmF0ZSBtdXRhYmxlQmFsYW5jZTogcmVhZG9ubHkgQ29pbltdO1xuICBwcml2YXRlIHJlYWRvbmx5IG5ldHdvcmskOiBPYnNlcnZhYmxlPE5ldHdvcmsgfCB1bmRlZmluZWQ+O1xuXG4gIHB1YmxpYyBjb25zdHJ1Y3Rvcih7XG4gICAgY2xpZW50LFxuICAgIHJlYWRDbGllbnQsXG4gICAgcGx1Z2luTWFuYWdlcixcbiAgICByZXNvdXJjZVR5cGUsXG4gICAgbmFtZSxcbiAgICBiYXNlTmFtZSxcbiAgICBuZXR3b3JrTmFtZSxcbiAgICBhZGRyZXNzLFxuICAgIGRhdGFQYXRoLFxuICAgIHdhbGxldFBhdGgsXG4gICAgY2xpZW50TmV0d29ya1R5cGUsXG4gICAgaW5pdGlhbCxcbiAgfTogV2FsbGV0UmVzb3VyY2VPcHRpb25zKSB7XG4gICAgdGhpcy5jbGllbnQgPSBjbGllbnQ7XG4gICAgdGhpcy5tdXRhYmxlUmVhZENsaWVudCA9IHJlYWRDbGllbnQ7XG4gICAgdGhpcy5yZXNvdXJjZVR5cGUgPSByZXNvdXJjZVR5cGU7XG4gICAgdGhpcy5uYW1lID0gbmFtZTtcbiAgICB0aGlzLmJhc2VOYW1lID0gYmFzZU5hbWU7XG4gICAgdGhpcy5uZXR3b3JrTmFtZSA9IG5ldHdvcmtOYW1lO1xuICAgIHRoaXMuYWRkcmVzcyA9IGFkZHJlc3M7XG4gICAgdGhpcy5kYXRhUGF0aCA9IGRhdGFQYXRoO1xuICAgIHRoaXMud2FsbGV0UGF0aCA9IHdhbGxldFBhdGg7XG4gICAgdGhpcy5jbGllbnROZXR3b3JrVHlwZSA9IGNsaWVudE5ldHdvcmtUeXBlO1xuICAgIHRoaXMubXV0YWJsZUluaXRpYWwgPSBpbml0aWFsO1xuXG4gICAgdGhpcy5tdXRhYmxlQmFsYW5jZSA9IFtdO1xuXG4gICAgdGhpcy5uZXR3b3JrJCA9IGdldE5ldHdvcmskKHsgcGx1Z2luTWFuYWdlciwgbmV0d29ya05hbWUgfSk7XG4gICAgdGhpcy5yZXNvdXJjZSQgPSBjb21iaW5lTGF0ZXN0KFt0aGlzLm5ldHdvcmskLCB0aW1lcigwLCA1MDAwKV0pLnBpcGUoXG4gICAgICBjb25jYXRNYXAoYXN5bmMgKHZhbHVlKSA9PiB7XG4gICAgICAgIGF3YWl0IHRoaXMudXBkYXRlKHZhbHVlWzBdKTtcblxuICAgICAgICByZXR1cm4gdGhpcy50b1Jlc291cmNlKCk7XG4gICAgICB9KSxcbiAgICAgIHNoYXJlUmVwbGF5KDEpLFxuICAgICk7XG4gIH1cblxuICBwdWJsaWMgYXN5bmMgY3JlYXRlKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICh0aGlzLm11dGFibGVJbml0aWFsID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignU29tZXRoaW5nIHdlbnQgd3JvbmcuJyk7XG4gICAgfVxuICAgIGNvbnN0IHsgcHJpdmF0ZUtleSwgcGFzc3dvcmQgfSA9IHRoaXMubXV0YWJsZUluaXRpYWw7XG4gICAgYXdhaXQgdGhpcy5jbGllbnQucHJvdmlkZXJzLmZpbGUua2V5c3RvcmUuYWRkVXNlckFjY291bnQoe1xuICAgICAgbmV0d29yazogdGhpcy5jbGllbnROZXR3b3JrVHlwZSxcbiAgICAgIG5hbWU6IHRoaXMuYmFzZU5hbWUsXG4gICAgICBwcml2YXRlS2V5LFxuICAgICAgcGFzc3dvcmQsXG4gICAgfSk7XG5cbiAgICB0aGlzLm11dGFibGVJbml0aWFsID0gdW5kZWZpbmVkO1xuICAgIGF3YWl0IGZzLmVuc3VyZURpcihwYXRoLmRpcm5hbWUodGhpcy53YWxsZXRQYXRoKSk7XG4gICAgYXdhaXQgZnMud3JpdGVKU09OKHRoaXMud2FsbGV0UGF0aCwgeyBhZGRyZXNzOiB0aGlzLmFkZHJlc3MgfSk7XG4gIH1cblxuICBwdWJsaWMgYXN5bmMgZGVsZXRlKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGF3YWl0IHRoaXMuY2xpZW50LnByb3ZpZGVycy5maWxlLmtleXN0b3JlLmRlbGV0ZVVzZXJBY2NvdW50KHRoaXMud2FsbGV0SUQpO1xuICAgIGF3YWl0IGZzLnJlbW92ZSh0aGlzLmRhdGFQYXRoKTtcbiAgfVxuXG4gIHB1YmxpYyBnZXQgd2FsbGV0SUQoKToge1xuICAgIHJlYWRvbmx5IG5ldHdvcms6IENsaWVudE5ldHdvcmtUeXBlO1xuICAgIHJlYWRvbmx5IGFkZHJlc3M6IHN0cmluZztcbiAgfSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIG5ldHdvcms6IHRoaXMuY2xpZW50TmV0d29ya1R5cGUsXG4gICAgICBhZGRyZXNzOiB0aGlzLmFkZHJlc3MsXG4gICAgfTtcbiAgfVxuXG4gIHB1YmxpYyBnZXQgd2FsbGV0KCk6IExvY2FsV2FsbGV0IHtcbiAgICByZXR1cm4gdGhpcy5jbGllbnQucHJvdmlkZXJzLmZpbGUua2V5c3RvcmUuZ2V0V2FsbGV0KHRoaXMud2FsbGV0SUQpO1xuICB9XG5cbiAgcHVibGljIGdldCB1bmxvY2tlZCgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy53YWxsZXQudHlwZSA9PT0gJ3VubG9ja2VkJztcbiAgfVxuXG4gIHB1YmxpYyBhc3luYyB1bmxvY2soeyBwYXNzd29yZCB9OiB7IHJlYWRvbmx5IHBhc3N3b3JkOiBzdHJpbmcgfSk6IFByb21pc2U8dm9pZD4ge1xuICAgIGF3YWl0IHRoaXMuY2xpZW50LnByb3ZpZGVycy5maWxlLmtleXN0b3JlLnVubG9ja1dhbGxldCh7XG4gICAgICBpZDogdGhpcy53YWxsZXRJRCxcbiAgICAgIHBhc3N3b3JkLFxuICAgIH0pO1xuICB9XG5cbiAgcHVibGljIGFzeW5jIGxvY2soKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgYXdhaXQgdGhpcy5jbGllbnQucHJvdmlkZXJzLmZpbGUua2V5c3RvcmUubG9ja1dhbGxldCh0aGlzLndhbGxldElEKTtcbiAgfVxuXG4gIHB1YmxpYyBnZXQgd2lmKCk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gICAgaWYgKHRoaXMud2FsbGV0LnR5cGUgPT09ICdsb2NrZWQnKSB7XG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIHJldHVybiBwcml2YXRlS2V5VG9XSUYodGhpcy53YWxsZXQucHJpdmF0ZUtleSk7XG4gIH1cblxuICBwdWJsaWMgZ2V0RGVidWcoKTogRGVzY3JpYmVUYWJsZSB7XG4gICAgY29uc3QgdGFibGU6IFJlYWRvbmx5QXJyYXk8cmVhZG9ubHkgW3N0cmluZywgc3RyaW5nXT4gPSBbXG4gICAgICBbJ0RhdGEgUGF0aCcsIHRoaXMuZGF0YVBhdGhdIGFzIGNvbnN0LFxuICAgICAgWydXYWxsZXQgUGF0aCcsIHRoaXMud2FsbGV0UGF0aF0gYXMgY29uc3QsXG4gICAgXTtcblxuICAgIHJldHVybiB0YWJsZS5jb25jYXQoXG4gICAgICBPYmplY3QuZW50cmllcyh0aGlzLnRvUmVzb3VyY2UoKSkubWFwPHJlYWRvbmx5IFtzdHJpbmcsIHN0cmluZ10+KChba2V5LCB2YWxdKSA9PiB7XG4gICAgICAgIGlmICh2YWwgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIHJldHVybiBba2V5LCAnbnVsbCddIGFzIGNvbnN0O1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIFtrZXksIHR5cGVvZiB2YWwgPT09ICdzdHJpbmcnID8gdmFsIDogSlNPTi5zdHJpbmdpZnkodmFsLCB1bmRlZmluZWQsIDIpXSBhcyBjb25zdDtcbiAgICAgIH0pLFxuICAgICk7XG4gIH1cblxuICBwcml2YXRlIHRvUmVzb3VyY2UoKTogV2FsbGV0IHtcbiAgICByZXR1cm4ge1xuICAgICAgcGx1Z2luOiB0aGlzLnJlc291cmNlVHlwZS5wbHVnaW4ubmFtZSxcbiAgICAgIHJlc291cmNlVHlwZTogdGhpcy5yZXNvdXJjZVR5cGUubmFtZSxcbiAgICAgIG5hbWU6IHRoaXMubmFtZSxcbiAgICAgIGJhc2VOYW1lOiB0aGlzLmJhc2VOYW1lLFxuICAgICAgc3RhdGU6IHRoaXMudW5sb2NrZWQgPyAnc3RhcnRlZCcgOiAnc3RvcHBlZCcsXG4gICAgICBuZXR3b3JrOiB0aGlzLm5ldHdvcmtOYW1lLFxuICAgICAgYWNjb3VudElEOiB7XG4gICAgICAgIG5ldHdvcms6IHRoaXMubmV0d29ya05hbWUsXG4gICAgICAgIGFkZHJlc3M6IHRoaXMuYWRkcmVzcyxcbiAgICAgIH0sXG4gICAgICBhZGRyZXNzOiB0aGlzLmFkZHJlc3MsXG4gICAgICB1bmxvY2tlZDogdGhpcy51bmxvY2tlZCxcbiAgICAgIG5lb0JhbGFuY2U6IHRoaXMubXV0YWJsZU5lb0JhbGFuY2UgPT09IHVuZGVmaW5lZCA/ICdVbmtub3duJyA6IHRoaXMubXV0YWJsZU5lb0JhbGFuY2UsXG4gICAgICBnYXNCYWxhbmNlOiB0aGlzLm11dGFibGVHYXNCYWxhbmNlID09PSB1bmRlZmluZWQgPyAnVW5rbm93bicgOiB0aGlzLm11dGFibGVHYXNCYWxhbmNlLFxuICAgICAgd2lmOiB0aGlzLndpZixcbiAgICAgIG5lcDI6IHRoaXMud2FsbGV0Lm5lcDIsXG4gICAgICBwdWJsaWNLZXk6IHRoaXMud2FsbGV0LnVzZXJBY2NvdW50LnB1YmxpY0tleSxcbiAgICAgIGJhbGFuY2U6IHRoaXMubXV0YWJsZUJhbGFuY2UsXG4gICAgfTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgdXBkYXRlKG5ldHdvcms/OiBOZXR3b3JrKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKG5ldHdvcmsgIT09IHVuZGVmaW5lZCAmJiBuZXR3b3JrLm5vZGVzLnNvbWUoKG5vZGUpID0+IG5vZGUucmVhZHkpKSB7XG4gICAgICB0aGlzLm11dGFibGVSZWFkQ2xpZW50ID0gdXBkYXRlQ2xpZW50KHtcbiAgICAgICAgbmV0d29ya05hbWU6IHRoaXMubmV0d29ya05hbWUsXG4gICAgICAgIG5ldHdvcmssXG4gICAgICAgIGNsaWVudDogdGhpcy5jbGllbnQsXG4gICAgICB9KTtcblxuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgYWNjb3VudCA9IGF3YWl0IHRoaXMubXV0YWJsZVJlYWRDbGllbnQuZ2V0QWNjb3VudCh0aGlzLmFkZHJlc3MpO1xuXG4gICAgICAgIGxldCBuZW9CYWxhbmNlID0gJzAnO1xuICAgICAgICBsZXQgZ2FzQmFsYW5jZSA9ICcwJztcbiAgICAgICAgdGhpcy5tdXRhYmxlQmFsYW5jZSA9IGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgICAgIE9iamVjdC5lbnRyaWVzKGFjY291bnQuYmFsYW5jZXMpLm1hcDxQcm9taXNlPHsgYXNzZXROYW1lOiBzdHJpbmc7IGFzc2V0OiBzdHJpbmc7IGFtb3VudDogc3RyaW5nIH0+PihcbiAgICAgICAgICAgIGFzeW5jIChbYXNzZXRIYXNoLCBhbW91bnRdKTogUHJvbWlzZTx7IGFzc2V0TmFtZTogc3RyaW5nOyBhc3NldDogc3RyaW5nOyBhbW91bnQ6IHN0cmluZyB9PiA9PiB7XG4gICAgICAgICAgICAgIGNvbnN0IGFzc2V0ID0gYXdhaXQgdGhpcy5tdXRhYmxlUmVhZENsaWVudC5nZXRBc3NldChhc3NldEhhc2gpO1xuICAgICAgICAgICAgICBsZXQgeyBuYW1lIH0gPSBhc3NldDtcbiAgICAgICAgICAgICAgaWYgKGFzc2V0Lmhhc2ggPT09IGNvbW1vbi5ORU9fQVNTRVRfSEFTSCkge1xuICAgICAgICAgICAgICAgIG5hbWUgPSAnTkVPJztcbiAgICAgICAgICAgICAgICBuZW9CYWxhbmNlID0gYW1vdW50LnRvU3RyaW5nKCk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgaWYgKGFzc2V0Lmhhc2ggPT09IGNvbW1vbi5HQVNfQVNTRVRfSEFTSCkge1xuICAgICAgICAgICAgICAgIG5hbWUgPSAnR0FTJztcbiAgICAgICAgICAgICAgICBnYXNCYWxhbmNlID0gYW1vdW50LnRvU3RyaW5nKCk7XG4gICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIGFzc2V0TmFtZTogbmFtZSxcbiAgICAgICAgICAgICAgICBhc3NldDogYXNzZXRIYXNoLFxuICAgICAgICAgICAgICAgIGFtb3VudDogYW1vdW50LnRvU3RyaW5nKCksXG4gICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICksXG4gICAgICAgICk7XG5cbiAgICAgICAgdGhpcy5tdXRhYmxlTmVvQmFsYW5jZSA9IG5lb0JhbGFuY2U7XG4gICAgICAgIHRoaXMubXV0YWJsZUdhc0JhbGFuY2UgPSBnYXNCYWxhbmNlO1xuICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgdGhpcy5yZXNvdXJjZVR5cGUucGx1Z2luLm1vbml0b3Iud2l0aERhdGEoeyBbbGFiZWxzLk5FT19BRERSRVNTXTogdGhpcy5hZGRyZXNzIH0pLmxvZ0Vycm9yKHtcbiAgICAgICAgICBuYW1lOiAnbmVvX3dhbGxldF9yZXNvdXJjZV91cGRhdGVfd2FsbGV0JyxcbiAgICAgICAgICBtZXNzYWdlOiBgRmFpbGVkIHRvIHVwZGF0ZSB3YWxsZXQgJHt0aGlzLmFkZHJlc3N9YCxcbiAgICAgICAgICBlcnJvcixcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfVxuICB9XG59XG4iXX0=