bitgo
Version:
BitGo JavaScript SDK
202 lines • 34.1 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
require("should");
const sdk_test_1 = require("@bitgo/sdk-test");
const bitgo_1 = require("../../../../src/bitgo");
const statics_1 = require("@bitgo/statics");
describe('OFC ERC20 Tokens Configuration:', function () {
let bitgo;
before(function () {
bitgo = sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo, { env: 'test' });
bitgo.initializeTestVars();
});
describe('validate addressCoin configuration for all OFC ERC20 tokens', function () {
it('should have addressCoin matching the first part of underlying asset', function () {
// Get all OFC ERC20 tokens (ofcerc20 and tofcerc20 instances)
// These are identified by having an addressCoin property
const ofcCoins = statics_1.coins.filter((coin) => coin.family === 'ofc' && coin.addressCoin);
const misconfigurations = [];
ofcCoins.forEach((ofcCoin) => {
// Get the underlying asset
const asset = ofcCoin.asset;
// Skip if no addressCoin property (not all OFC coins have it)
if (!ofcCoin.addressCoin) {
return;
}
// Skip testnet tokens - they use testnet-specific addressCoins
// (e.g., gteth, hteth, tsol, tavaxc, tpolygon, tarbeth)
if (ofcCoin.network.type === 'testnet') {
return;
}
// Determine expected addressCoin from the asset (mainnet only)
let expectedAddressCoin;
if (asset.includes(':')) {
// For assets like 'baseeth:spec', 'xdc:usdc', 'mon:usdc', etc.
// The addressCoin should be the part before the colon
expectedAddressCoin = asset.split(':')[0];
}
else if (ofcCoin.name.includes(':')) {
// For tokens with ':' in the name like 'ofcbaseeth:spec'
// Extract the chain from the name
const nameParts = ofcCoin.name.replace(/^ofc/, '').split(':');
if (nameParts.length > 1) {
expectedAddressCoin = nameParts[0];
}
else {
expectedAddressCoin = 'eth'; // Default to eth for standard ERC20 tokens
}
}
else {
// For standard tokens without ':' in asset (e.g., 'USDC', 'LINK')
expectedAddressCoin = 'eth';
}
// Check addressCoin matches expected value
if (ofcCoin.addressCoin !== expectedAddressCoin) {
misconfigurations.push(`Token ${ofcCoin.name} with asset ${asset} should have addressCoin='${expectedAddressCoin}' but has '${ofcCoin.addressCoin}'`);
}
});
// Report all misconfigurations at once
if (misconfigurations.length > 0) {
throw new Error(`Found ${misconfigurations.length} addressCoin misconfigurations:\n` + misconfigurations.join('\n'));
}
});
it('should validate specific chain-specific tokens', function () {
// Test specific tokens by chain
const testCases = [
// XDC Network tokens
{ token: 'ofcxdc:usdc', addressCoin: 'xdc', chain: 'XDC' },
{ token: 'ofcxdc:lbt', addressCoin: 'xdc', chain: 'XDC' },
{ token: 'ofcxdc:gama', addressCoin: 'xdc', chain: 'XDC' },
{ token: 'ofcxdc:srx', addressCoin: 'xdc', chain: 'XDC' },
{ token: 'ofcxdc:weth', addressCoin: 'xdc', chain: 'XDC' },
// Base Ethereum tokens
{ token: 'ofcbaseeth:spec', addressCoin: 'baseeth', chain: 'Base' },
{ token: 'ofcbaseeth:soon', addressCoin: 'baseeth', chain: 'Base' },
{ token: 'ofcbaseeth:wave', addressCoin: 'baseeth', chain: 'Base' },
{ token: 'ofcbaseeth:tig', addressCoin: 'baseeth', chain: 'Base' },
{ token: 'ofcbaseeth:virtual', addressCoin: 'baseeth', chain: 'Base' },
{ token: 'ofcbaseeth:zora', addressCoin: 'baseeth', chain: 'Base' },
{ token: 'ofcbaseeth:toshi', addressCoin: 'baseeth', chain: 'Base' },
{ token: 'ofcbaseeth:creator', addressCoin: 'baseeth', chain: 'Base' },
{ token: 'ofcbaseeth:avnt', addressCoin: 'baseeth', chain: 'Base' },
{ token: 'ofcbaseeth:mira', addressCoin: 'baseeth', chain: 'Base' },
{ token: 'ofcbaseeth:towns', addressCoin: 'baseeth', chain: 'Base' },
{ token: 'ofcbaseeth:recall', addressCoin: 'baseeth', chain: 'Base' },
{ token: 'ofcbaseeth:brlv', addressCoin: 'baseeth', chain: 'Base' },
{ token: 'ofcbaseeth:wbrly', addressCoin: 'baseeth', chain: 'Base' },
{ token: 'ofcbaseeth:sapien', addressCoin: 'baseeth', chain: 'Base' },
{ token: 'ofcbaseeth:aixbt', addressCoin: 'baseeth', chain: 'Base' },
{ token: 'ofcbaseeth:brett', addressCoin: 'baseeth', chain: 'Base' },
// MON Network tokens
{ token: 'ofcmon:usdc', addressCoin: 'mon', chain: 'MON' },
{ token: 'ofcmon:wmon', addressCoin: 'mon', chain: 'MON' },
// HYPE Network token
{ token: 'ofchype:hwhype', addressCoin: 'hype', chain: 'HYPE' },
// IP (Story Network) token
{ token: 'ofcip:aria', addressCoin: 'ip', chain: 'Story' },
];
const errors = [];
testCases.forEach(({ token, addressCoin, chain }) => {
const ofcCoin = statics_1.coins.get(token);
if (!ofcCoin) {
errors.push(`${chain} token ${token} not found in statics`);
}
else if (ofcCoin.addressCoin !== addressCoin) {
errors.push(`${chain} token ${token} should have addressCoin='${addressCoin}' but has '${ofcCoin.addressCoin}'`);
}
});
if (errors.length > 0) {
throw new Error(`Found ${errors.length} configuration errors:\n` + errors.join('\n'));
}
});
it('should validate all tokens have addressCoin property', function () {
// Get all OFC ERC20 tokens (ofcerc20 and tofcerc20 instances)
// These should all have an addressCoin property
const ofcErc20Tokens = statics_1.coins.filter((coin) => coin.family === 'ofc' && coin.isToken === true && (coin.name.includes(':') || coin.asset.includes(':')));
const tokensWithoutAddressCoin = [];
ofcErc20Tokens.forEach((ofcCoin) => {
if (!ofcCoin.addressCoin) {
tokensWithoutAddressCoin.push(`${ofcCoin.name} (asset: ${ofcCoin.asset})`);
}
});
// Report tokens without addressCoin (informational only, not a failure)
tokensWithoutAddressCoin.length.should.be.greaterThanOrEqual(0);
});
});
describe('validate required custody features for all OFC ERC20 tokens', function () {
it('should have required custody features for ofcerc20 and tofcerc20 tokens', function () {
const requiredFeatures = [
statics_1.CoinFeature.ACCOUNT_MODEL,
statics_1.CoinFeature.REQUIRES_BIG_NUMBER,
statics_1.CoinFeature.CUSTODY,
statics_1.CoinFeature.CUSTODY_BITGO_TRUST,
];
// Get all OFC ERC20 tokens (ofcerc20 and tofcerc20 instances)
// These are identified by having an addressCoin property
const ofcCoins = statics_1.coins.filter((coin) => coin.family === 'ofc' && coin.addressCoin);
const missingFeatures = [];
ofcCoins.forEach((ofcCoin) => {
requiredFeatures.forEach((feature) => {
if (!ofcCoin.features.includes(feature)) {
missingFeatures.push(`Token ${ofcCoin.name} is missing feature: ${feature}`);
}
});
});
if (missingFeatures.length > 0) {
throw new Error(`Found ${missingFeatures.length} missing features:\n` + missingFeatures.join('\n'));
}
});
});
describe('validate address validation for chain-specific tokens', function () {
it('should validate bg- format addresses for all OFC tokens', function () {
// Get sample OFC tokens from different chains
const testTokens = [
'ofcxdc:usdc',
'ofcbaseeth:spec',
'ofcmon:usdc',
'ofchype:hwhype',
'ofcip:aria',
'ofceth',
'ofcbtc',
];
const errors = [];
testTokens.forEach((tokenName) => {
const ofcCoin = bitgo.coin(tokenName);
if (ofcCoin) {
const validBgAddress = 'bg-5b2b80eafbdf94d5030bb23f9b56ad64';
const invalidBgAddress = 'bg-5b2b80eafbdf94d5030bb23f9b56ad64nnn';
if (!ofcCoin.isValidAddress(validBgAddress)) {
errors.push(`${tokenName} should accept valid bg- address format`);
}
if (ofcCoin.isValidAddress(invalidBgAddress)) {
errors.push(`${tokenName} should reject invalid bg- address format`);
}
}
});
if (errors.length > 0) {
throw new Error(`Found ${errors.length} address validation errors:\n` + errors.join('\n'));
}
});
});
describe('validate all OFC tokens are properly registered', function () {
it('should be able to instantiate all OFC tokens', function () {
const ofcCoins = statics_1.coins.filter((coin) => coin.family === 'ofc');
const errors = [];
ofcCoins.forEach((ofcCoin) => {
try {
const coin = bitgo.coin(ofcCoin.name);
if (!coin) {
errors.push(`Failed to instantiate ${ofcCoin.name}`);
}
}
catch (e) {
errors.push(`Error instantiating ${ofcCoin.name}: ${e.message}`);
}
});
if (errors.length > 0) {
throw new Error(`Found ${errors.length} instantiation errors:\n` + errors.join('\n'));
}
});
});
});
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib2ZjRXJjMjBUb2tlbnMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi90ZXN0L3YyL3VuaXQvY29pbnMvb2ZjRXJjMjBUb2tlbnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQSxrQkFBZ0I7QUFDaEIsOENBQTRDO0FBQzVDLGlEQUE4QztBQUM5Qyw0Q0FBb0Q7QUFFcEQsUUFBUSxDQUFDLGlDQUFpQyxFQUFFO0lBQzFDLElBQUksS0FBSyxDQUFDO0lBRVYsTUFBTSxDQUFDO1FBQ0wsS0FBSyxHQUFHLG9CQUFTLENBQUMsUUFBUSxDQUFDLGFBQUssRUFBRSxFQUFFLEdBQUcsRUFBRSxNQUFNLEVBQUUsQ0FBQyxDQUFDO1FBQ25ELEtBQUssQ0FBQyxrQkFBa0IsRUFBRSxDQUFDO0lBQzdCLENBQUMsQ0FBQyxDQUFDO0lBRUgsUUFBUSxDQUFDLDZEQUE2RCxFQUFFO1FBQ3RFLEVBQUUsQ0FBQyxxRUFBcUUsRUFBRTtZQUN4RSw4REFBOEQ7WUFDOUQseURBQXlEO1lBQ3pELE1BQU0sUUFBUSxHQUFHLGVBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQyxJQUFTLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxNQUFNLEtBQUssS0FBSyxJQUFJLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQztZQUV4RixNQUFNLGlCQUFpQixHQUFhLEVBQUUsQ0FBQztZQUV2QyxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUMsT0FBWSxFQUFFLEVBQUU7Z0JBQ2hDLDJCQUEyQjtnQkFDM0IsTUFBTSxLQUFLLEdBQUcsT0FBTyxDQUFDLEtBQUssQ0FBQztnQkFFNUIsOERBQThEO2dCQUM5RCxJQUFJLENBQUMsT0FBTyxDQUFDLFdBQVcsRUFBRSxDQUFDO29CQUN6QixPQUFPO2dCQUNULENBQUM7Z0JBRUQsK0RBQStEO2dCQUMvRCx3REFBd0Q7Z0JBQ3hELElBQUksT0FBTyxDQUFDLE9BQU8sQ0FBQyxJQUFJLEtBQUssU0FBUyxFQUFFLENBQUM7b0JB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QUFDLENBQUMsT0FBTyxFQUFFLEVBQUU7Z0JBQzNCLElBQUksQ0FBQztvQkFDSCxNQUFNLElBQUksR0FBRyxLQUFLLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztvQkFDdEMsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO3dCQUNWLE1BQU0sQ0FBQyxJQUFJLENBQUMseUJBQXlCLE9BQU8sQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDO29CQUN2RCxDQUFDO2dCQUNILENBQUM7Z0JBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztvQkFDWCxNQUFNLENBQUMsSUFBSSxDQUFDLHVCQUF1QixPQUFPLENBQUMsSUFBSSxLQUFLLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDO2dCQUNuRSxDQUFDO1lBQ0gsQ0FBQyxDQUFDLENBQUM7WUFFSCxJQUFJLE1BQU0sQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFLENBQUM7Z0JBQ3RCLE1BQU0sSUFBSSxLQUFLLENBQUMsU0FBUyxNQUFNLENBQUMsTUFBTSwwQkFBMEIsR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7WUFDeEYsQ0FBQztRQUNILENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAnc2hvdWxkJztcbmltcG9ydCB7IFRlc3RCaXRHbyB9IGZyb20gJ0BiaXRnby9zZGstdGVzdCc7XG5pbXBvcnQgeyBCaXRHbyB9IGZyb20gJy4uLy4uLy4uLy4uL3NyYy9iaXRnbyc7XG5pbXBvcnQgeyBjb2lucywgQ29pbkZlYXR1cmUgfSBmcm9tICdAYml0Z28vc3RhdGljcyc7XG5cbmRlc2NyaWJlKCdPRkMgRVJDMjAgVG9rZW5zIENvbmZpZ3VyYXRpb246JywgZnVuY3Rpb24gKCkge1xuICBsZXQgYml0Z287XG5cbiAgYmVmb3JlKGZ1bmN0aW9uICgpIHtcbiAgICBiaXRnbyA9IFRlc3RCaXRHby5kZWNvcmF0ZShCaXRHbywgeyBlbnY6ICd0ZXN0JyB9KTtcbiAgICBiaXRnby5pbml0aWFsaXplVGVzdFZhcnMoKTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ3ZhbGlkYXRlIGFkZHJlc3NDb2luIGNvbmZpZ3VyYXRpb24gZm9yIGFsbCBPRkMgRVJDMjAgdG9rZW5zJywgZnVuY3Rpb24gKCkge1xuICAgIGl0KCdzaG91bGQgaGF2ZSBhZGRyZXNzQ29pbiBtYXRjaGluZyB0aGUgZmlyc3QgcGFydCBvZiB1bmRlcmx5aW5nIGFzc2V0JywgZnVuY3Rpb24gKCkge1xuICAgICAgLy8gR2V0IGFsbCBPRkMgRVJDMjAgdG9rZW5zIChvZmNlcmMyMCBhbmQgdG9mY2VyYzIwIGluc3RhbmNlcylcbiAgICAgIC8vIFRoZXNlIGFyZSBpZGVudGlmaWVkIGJ5IGhhdmluZyBhbiBhZGRyZXNzQ29pbiBwcm9wZXJ0eVxuICAgICAgY29uc3Qgb2ZjQ29pbnMgPSBjb2lucy5maWx0ZXIoKGNvaW46IGFueSkgPT4gY29pbi5mYW1pbHkgPT09ICdvZmMnICYmIGNvaW4uYWRkcmVzc0NvaW4pO1xuXG4gICAgICBjb25zdCBtaXNjb25maWd1cmF0aW9uczogc3RyaW5nW10gPSBbXTtcblxuICAgICAgb2ZjQ29pbnMuZm9yRWFjaCgob2ZjQ29pbjogYW55KSA9PiB7XG4gICAgICAgIC8vIEdldCB0aGUgdW5kZXJseWluZyBhc3NldFxuICAgICAgICBjb25zdCBhc3NldCA9IG9mY0NvaW4uYXNzZXQ7XG5cbiAgICAgICAgLy8gU2tpcCBpZiBubyBhZGRyZXNzQ29pbiBwcm9wZXJ0eSAobm90IGFsbCBPRkMgY29pbnMgaGF2ZSBpdClcbiAgICAgICAgaWYgKCFvZmNDb2luLmFkZHJlc3NDb2luKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gU2tpcCB0ZXN0bmV0IHRva2VucyAtIHRoZXkgdXNlIHRlc3RuZXQtc3BlY2lmaWMgYWRkcmVzc0NvaW5zXG4gICAgICAgIC8vIChlLmcuLCBndGV0aCwgaHRldGgsIHRzb2wsIHRhdmF4YywgdHBvbHlnb24sIHRhcmJldGgpXG4gICAgICAgIGlmIChvZmNDb2luLm5ldHdvcmsudHlwZSA9PT0gJ3Rlc3RuZXQnKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gRGV0ZXJtaW5lIGV4cGVjdGVkIGFkZHJlc3NDb2luIGZyb20gdGhlIGFzc2V0IChtYWlubmV0IG9ubHkpXG4gICAgICAgIGxldCBleHBlY3RlZEFkZHJlc3NDb2luO1xuXG4gICAgICAgIGlmIChhc3NldC5pbmNsdWRlcygnOicpKSB7XG4gICAgICAgICAgLy8gRm9yIGFzc2V0cyBsaWtlICdiYXNlZXRoOnNwZWMnLCAneGRjOnVzZGMnLCAnbW9uOnVzZGMnLCBldGMuXG4gICAgICAgICAgLy8gVGhlIGFkZHJlc3NDb2luIHNob3VsZCBiZSB0aGUgcGFydCBiZWZvcmUgdGhlIGNvbG9uXG4gICAgICAgICAgZXhwZWN0ZWRBZGRyZXNzQ29pbiA9IGFzc2V0LnNwbGl0KCc6JylbMF07XG4gICAgICAgIH0gZWxzZSBpZiAob2ZjQ29pbi5uYW1lLmluY2x1ZGVzKCc6JykpIHtcbiAgICAgICAgICAvLyBGb3IgdG9rZW5zIHdpdGggJzonIGluIHRoZSBuYW1lIGxpa2UgJ29mY2Jhc2VldGg6c3BlYydcbiAgICAgICAgICAvLyBFeHRyYWN0IHRoZSBjaGFpbiBmcm9tIHRoZSBuYW1lXG4gICAgICAgICAgY29uc3QgbmFtZVBhcnRzID0gb2ZjQ29pbi5uYW1lLnJlcGxhY2UoL15vZmMvLCAnJykuc3BsaXQoJzonKTtcbiAgICAgICAgICBpZiAobmFtZVBhcnRzLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgICAgIGV4cGVjdGVkQWRkcmVzc0NvaW4gPSBuYW1lUGFydHNbMF07XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGV4cGVjdGVkQWRkcmVzc0NvaW4gPSAnZXRoJzsgLy8gRGVmYXVsdCB0byBldGggZm9yIHN0YW5kYXJkIEVSQzIwIHRva2Vuc1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAvLyBGb3Igc3RhbmRhcmQgdG9rZW5zIHdpdGhvdXQgJzonIGluIGFzc2V0IChlLmcuLCAnVVNEQycsICdMSU5LJylcbiAgICAgICAgICBleHBlY3RlZEFkZHJlc3NDb2luID0gJ2V0aCc7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBDaGVjayBhZGRyZXNzQ29pbiBtYXRjaGVzIGV4cGVjdGVkIHZhbHVlXG4gICAgICAgIGlmIChvZmNDb2luLmFkZHJlc3NDb2luICE9PSBleHBlY3RlZEFkZHJlc3NDb2luKSB7XG4gICAgICAgICAgbWlzY29uZmlndXJhdGlvbnMucHVzaChcbiAgICAgICAgICAgIGBUb2tlbiAke29mY0NvaW4ubmFtZX0gd2l0aCBhc3NldCAke2Fzc2V0fSBzaG91bGQgaGF2ZSBhZGRyZXNzQ29pbj0nJHtleHBlY3RlZEFkZHJlc3NDb2lufScgYnV0IGhhcyAnJHtvZmNDb2luLmFkZHJlc3NDb2lufSdgXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG5cbiAgICAgIC8vIFJlcG9ydCBhbGwgbWlzY29uZmlndXJhdGlvbnMgYXQgb25jZVxuICAgICAgaWYgKG1pc2NvbmZpZ3VyYXRpb25zLmxlbmd0aCA+IDApIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgIGBGb3VuZCAke21pc2NvbmZpZ3VyYXRpb25zLmxlbmd0aH0gYWRkcmVzc0NvaW4gbWlzY29uZmlndXJhdGlvbnM6XFxuYCArIG1pc2NvbmZpZ3VyYXRpb25zLmpvaW4oJ1xcbicpXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHZhbGlkYXRlIHNwZWNpZmljIGNoYWluLXNwZWNpZmljIHRva2VucycsIGZ1bmN0aW9uICgpIHtcbiAgICAgIC8vIFRlc3Qgc3BlY2lmaWMgdG9rZW5zIGJ5IGNoYWluXG4gICAgICBjb25zdCB0ZXN0Q2FzZXMgPSBbXG4gICAgICAgIC8vIFhEQyBOZXR3b3JrIHRva2Vuc1xuICAgICAgICB7IHRva2VuOiAnb2ZjeGRjOnVzZGMnLCBhZGRyZXNzQ29pbjogJ3hkYycsIGNoYWluOiAnWERDJyB9LFxuICAgICAgICB7IHRva2VuOiAnb2ZjeGRjOmxidCcsIGFkZHJlc3NDb2luOiAneGRjJywgY2hhaW46ICdYREMnIH0sXG4gICAgICAgIHsgdG9rZW46ICdvZmN4ZGM6Z2FtYScsIGFkZHJlc3NDb2luOiAneGRjJywgY2hhaW46ICdYREMnIH0sXG4gICAgICAgIHsgdG9rZW46ICdvZmN4ZGM6c3J4JywgYWRkcmVzc0NvaW46ICd4ZGMnLCBjaGFpbjogJ1hEQycgfSxcbiAgICAgICAgeyB0b2tlbjogJ29mY3hkYzp3ZXRoJywgYWRkcmVzc0NvaW46ICd4ZGMnLCBjaGFpbjogJ1hEQycgfSxcbiAgICAgICAgLy8gQmFzZSBFdGhlcmV1bSB0b2tlbnNcbiAgICAgICAgeyB0b2tlbjogJ29mY2Jhc2VldGg6c3BlYycsIGFkZHJlc3NDb2luOiAnYmFzZWV0aCcsIGNoYWluOiAnQmFzZScgfSxcbiAgICAgICAgeyB0b2tlbjogJ29mY2Jhc2VldGg6c29vbicsIGFkZHJlc3NDb2luOiAnYmFzZWV0aCcsIGNoYWluOiAnQmFzZScgfSxcbiAgICAgICAgeyB0b2tlbjogJ29mY2Jhc2VldGg6d2F2ZScsIGFkZHJlc3NDb2luOiAnYmFzZWV0aCcsIGNoYWluOiAnQmFzZScgfSxcbiAgICAgICAgeyB0b2tlbjogJ29mY2Jhc2VldGg6dGlnJywgYWRkcmVzc0NvaW46ICdiYXNlZXRoJywgY2hhaW46ICdCYXNlJyB9LFxuICAgICAgICB7IHRva2VuOiAnb2ZjYmFzZWV0aDp2aXJ0dWFsJywgYWRkcmVzc0NvaW46ICdiYXNlZXRoJywgY2hhaW46ICdCYXNlJyB9LFxuICAgICAgICB7IHRva2VuOiAnb2ZjYmFzZWV0aDp6b3JhJywgYWRkcmVzc0NvaW46ICdiYXNlZXRoJywgY2hhaW46ICdCYXNlJyB9LFxuICAgICAgICB7IHRva2VuOiAnb2ZjYmFzZWV0aDp0b3NoaScsIGFkZHJlc3NDb2luOiAnYmFzZWV0aCcsIGNoYWluOiAnQmFzZScgfSxcbiAgICAgICAgeyB0b2tlbjogJ29mY2Jhc2VldGg6Y3JlYXRvcicsIGFkZHJlc3NDb2luOiAnYmFzZWV0aCcsIGNoYWluOiAnQmFzZScgfSxcbiAgICAgICAgeyB0b2tlbjogJ29mY2Jhc2VldGg6YXZudCcsIGFkZHJlc3NDb2luOiAnYmFzZWV0aCcsIGNoYWluOiAnQmFzZScgfSxcbiAgICAgICAgeyB0b2tlbjogJ29mY2Jhc2VldGg6bWlyYScsIGFkZHJlc3NDb2luOiAnYmFzZWV0aCcsIGNoYWluOiAnQmFzZScgfSxcbiAgICAgICAgeyB0b2tlbjogJ29mY2Jhc2VldGg6dG93bnMnLCBhZGRyZXNzQ29pbjogJ2Jhc2VldGgnLCBjaGFpbjogJ0Jhc2UnIH0sXG4gICAgICAgIHsgdG9rZW46ICdvZmNiYXNlZXRoOnJlY2FsbCcsIGFkZHJlc3NDb2luOiAnYmFzZWV0aCcsIGNoYWluOiAnQmFzZScgfSxcbiAgICAgICAgeyB0b2tlbjogJ29mY2Jhc2VldGg6YnJsdicsIGFkZHJlc3NDb2luOiAnYmFzZWV0aCcsIGNoYWluOiAnQmFzZScgfSxcbiAgICAgICAgeyB0b2tlbjogJ29mY2Jhc2VldGg6d2JybHknLCBhZGRyZXNzQ29pbjogJ2Jhc2VldGgnLCBjaGFpbjogJ0Jhc2UnIH0sXG4gICAgICAgIHsgdG9rZW46ICdvZmNiYXNlZXRoOnNhcGllbicsIGFkZHJlc3NDb2luOiAnYmFzZWV0aCcsIGNoYWluOiAnQmFzZScgfSxcbiAgICAgICAgeyB0b2tlbjogJ29mY2Jhc2VldGg6YWl4YnQnLCBhZGRyZXNzQ29pbjogJ2Jhc2VldGgnLCBjaGFpbjogJ0Jhc2UnIH0sXG4gICAgICAgIHsgdG9rZW46ICdvZmNiYXNlZXRoOmJyZXR0JywgYWRkcmVzc0NvaW46ICdiYXNlZXRoJywgY2hhaW46ICdCYXNlJyB9LFxuICAgICAgICAvLyBNT04gTmV0d29yayB0b2tlbnNcbiAgICAgICAgeyB0b2tlbjogJ29mY21vbjp1c2RjJywgYWRkcmVzc0NvaW46ICdtb24nLCBjaGFpbjogJ01PTicgfSxcbiAgICAgICAgeyB0b2tlbjogJ29mY21vbjp3bW9uJywgYWRkcmVzc0NvaW46ICdtb24nLCBjaGFpbjogJ01PTicgfSxcbiAgICAgICAgLy8gSFlQRSBOZXR3b3JrIHRva2VuXG4gICAgICAgIHsgdG9rZW46ICdvZmNoeXBlOmh3aHlwZScsIGFkZHJlc3NDb2luOiAnaHlwZScsIGNoYWluOiAnSFlQRScgfSxcbiAgICAgICAgLy8gSVAgKFN0b3J5IE5ldHdvcmspIHRva2VuXG4gICAgICAgIHsgdG9rZW46ICdvZmNpcDphcmlhJywgYWRkcmVzc0NvaW46ICdpcCcsIGNoYWluOiAnU3RvcnknIH0sXG4gICAgICBdO1xuXG4gICAgICBjb25zdCBlcnJvcnM6IHN0cmluZ1tdID0gW107XG5cbiAgICAgIHRlc3RDYXNlcy5mb3JFYWNoKCh7IHRva2VuLCBhZGRyZXNzQ29pbiwgY2hhaW4gfSkgPT4ge1xuICAgICAgICBjb25zdCBvZmNDb2luOiBhbnkgPSBjb2lucy5nZXQodG9rZW4pO1xuICAgICAgICBpZiAoIW9mY0NvaW4pIHtcbiAgICAgICAgICBlcnJvcnMucHVzaChgJHtjaGFpbn0gdG9rZW4gJHt0b2tlbn0gbm90IGZvdW5kIGluIHN0YXRpY3NgKTtcbiAgICAgICAgfSBlbHNlIGlmIChvZmNDb2luLmFkZHJlc3NDb2luICE9PSBhZGRyZXNzQ29pbikge1xuICAgICAgICAgIGVycm9ycy5wdXNoKFxuICAgICAgICAgICAgYCR7Y2hhaW59IHRva2VuICR7dG9rZW59IHNob3VsZCBoYXZlIGFkZHJlc3NDb2luPScke2FkZHJlc3NDb2lufScgYnV0IGhhcyAnJHtvZmNDb2luLmFkZHJlc3NDb2lufSdgXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG5cbiAgICAgIGlmIChlcnJvcnMubGVuZ3RoID4gMCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEZvdW5kICR7ZXJyb3JzLmxlbmd0aH0gY29uZmlndXJhdGlvbiBlcnJvcnM6XFxuYCArIGVycm9ycy5qb2luKCdcXG4nKSk7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHZhbGlkYXRlIGFsbCB0b2tlbnMgaGF2ZSBhZGRyZXNzQ29pbiBwcm9wZXJ0eScsIGZ1bmN0aW9uICgpIHtcbiAgICAgIC8vIEdldCBhbGwgT0ZDIEVSQzIwIHRva2VucyAob2ZjZXJjMjAgYW5kIHRvZmNlcmMyMCBpbnN0YW5jZXMpXG4gICAgICAvLyBUaGVzZSBzaG91bGQgYWxsIGhhdmUgYW4gYWRkcmVzc0NvaW4gcHJvcGVydHlcbiAgICAgIGNvbnN0IG9mY0VyYzIwVG9rZW5zID0gY29pbnMuZmlsdGVyKFxuICAgICAgICAoY29pbjogYW55KSA9PlxuICAgICAgICAgIGNvaW4uZmFtaWx5ID09PSAnb2ZjJyAmJiBjb2luLmlzVG9rZW4gPT09IHRydWUgJiYgKGNvaW4ubmFtZS5pbmNsdWRlcygnOicpIHx8IGNvaW4uYXNzZXQuaW5jbHVkZXMoJzonKSlcbiAgICAgICk7XG5cbiAgICAgIGNvbnN0IHRva2Vuc1dpdGhvdXRBZGRyZXNzQ29pbjogc3RyaW5nW10gPSBbXTtcblxuICAgICAgb2ZjRXJjMjBUb2tlbnMuZm9yRWFjaCgob2ZjQ29pbjogYW55KSA9PiB7XG4gICAgICAgIGlmICghb2ZjQ29pbi5hZGRyZXNzQ29pbikge1xuICAgICAgICAgIHRva2Vuc1dpdGhvdXRBZGRyZXNzQ29pbi5wdXNoKGAke29mY0NvaW4ubmFtZX0gKGFzc2V0OiAke29mY0NvaW4uYXNzZXR9KWApO1xuICAgICAgICB9XG4gICAgICB9KTtcblxuICAgICAgLy8gUmVwb3J0IHRva2VucyB3aXRob3V0IGFkZHJlc3NDb2luIChpbmZvcm1hdGlvbmFsIG9ubHksIG5vdCBhIGZhaWx1cmUpXG4gICAgICB0b2tlbnNXaXRob3V0QWRkcmVzc0NvaW4ubGVuZ3RoLnNob3VsZC5iZS5ncmVhdGVyVGhhbk9yRXF1YWwoMCk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCd2YWxpZGF0ZSByZXF1aXJlZCBjdXN0b2R5IGZlYXR1cmVzIGZvciBhbGwgT0ZDIEVSQzIwIHRva2VucycsIGZ1bmN0aW9uICgpIHtcbiAgICBpdCgnc2hvdWxkIGhhdmUgcmVxdWlyZWQgY3VzdG9keSBmZWF0dXJlcyBmb3Igb2ZjZXJjMjAgYW5kIHRvZmNlcmMyMCB0b2tlbnMnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCByZXF1aXJlZEZlYXR1cmVzID0gW1xuICAgICAgICBDb2luRmVhdHVyZS5BQ0NPVU5UX01PREVMLFxuICAgICAgICBDb2luRmVhdHVyZS5SRVFVSVJFU19CSUdfTlVNQkVSLFxuICAgICAgICBDb2luRmVhdHVyZS5DVVNUT0RZLFxuICAgICAgICBDb2luRmVhdHVyZS5DVVNUT0RZX0JJVEdPX1RSVVNULFxuICAgICAgXTtcblxuICAgICAgLy8gR2V0IGFsbCBPRkMgRVJDMjAgdG9rZW5zIChvZmNlcmMyMCBhbmQgdG9mY2VyYzIwIGluc3RhbmNlcylcbiAgICAgIC8vIFRoZXNlIGFyZSBpZGVudGlmaWVkIGJ5IGhhdmluZyBhbiBhZGRyZXNzQ29pbiBwcm9wZXJ0eVxuICAgICAgY29uc3Qgb2ZjQ29pbnMgPSBjb2lucy5maWx0ZXIoKGNvaW46IGFueSkgPT4gY29pbi5mYW1pbHkgPT09ICdvZmMnICYmIGNvaW4uYWRkcmVzc0NvaW4pO1xuXG4gICAgICBjb25zdCBtaXNzaW5nRmVhdHVyZXM6IHN0cmluZ1tdID0gW107XG5cbiAgICAgIG9mY0NvaW5zLmZvckVhY2goKG9mY0NvaW4pID0+IHtcbiAgICAgICAgcmVxdWlyZWRGZWF0dXJlcy5mb3JFYWNoKChmZWF0dXJlKSA9PiB7XG4gICAgICAgICAgaWYgKCFvZmNDb2luLmZlYXR1cmVzLmluY2x1ZGVzKGZlYXR1cmUpKSB7XG4gICAgICAgICAgICBtaXNzaW5nRmVhdHVyZXMucHVzaChgVG9rZW4gJHtvZmNDb2luLm5hbWV9IGlzIG1pc3NpbmcgZmVhdHVyZTogJHtmZWF0dXJlfWApO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICB9KTtcblxuICAgICAgaWYgKG1pc3NpbmdGZWF0dXJlcy5sZW5ndGggPiAwKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgRm91bmQgJHttaXNzaW5nRmVhdHVyZXMubGVuZ3RofSBtaXNzaW5nIGZlYXR1cmVzOlxcbmAgKyBtaXNzaW5nRmVhdHVyZXMuam9pbignXFxuJykpO1xuICAgICAgfVxuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgndmFsaWRhdGUgYWRkcmVzcyB2YWxpZGF0aW9uIGZvciBjaGFpbi1zcGVjaWZpYyB0b2tlbnMnLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ3Nob3VsZCB2YWxpZGF0ZSBiZy0gZm9ybWF0IGFkZHJlc3NlcyBmb3IgYWxsIE9GQyB0b2tlbnMnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAvLyBHZXQgc2FtcGxlIE9GQyB0b2tlbnMgZnJvbSBkaWZmZXJlbnQgY2hhaW5zXG4gICAgICBjb25zdCB0ZXN0VG9rZW5zID0gW1xuICAgICAgICAnb2ZjeGRjOnVzZGMnLFxuICAgICAgICAnb2ZjYmFzZWV0aDpzcGVjJyxcbiAgICAgICAgJ29mY21vbjp1c2RjJyxcbiAgICAgICAgJ29mY2h5cGU6aHdoeXBlJyxcbiAgICAgICAgJ29mY2lwOmFyaWEnLFxuICAgICAgICAnb2ZjZXRoJyxcbiAgICAgICAgJ29mY2J0YycsXG4gICAgICBdO1xuXG4gICAgICBjb25zdCBlcnJvcnM6IHN0cmluZ1tdID0gW107XG5cbiAgICAgIHRlc3RUb2tlbnMuZm9yRWFjaCgodG9rZW5OYW1lKSA9PiB7XG4gICAgICAgIGNvbnN0IG9mY0NvaW4gPSBiaXRnby5jb2luKHRva2VuTmFtZSk7XG4gICAgICAgIGlmIChvZmNDb2luKSB7XG4gICAgICAgICAgY29uc3QgdmFsaWRCZ0FkZHJlc3MgPSAnYmctNWIyYjgwZWFmYmRmOTRkNTAzMGJiMjNmOWI1NmFkNjQnO1xuICAgICAgICAgIGNvbnN0IGludmFsaWRCZ0FkZHJlc3MgPSAnYmctNWIyYjgwZWFmYmRmOTRkNTAzMGJiMjNmOWI1NmFkNjRubm4nO1xuXG4gICAgICAgICAgaWYgKCFvZmNDb2luLmlzVmFsaWRBZGRyZXNzKHZhbGlkQmdBZGRyZXNzKSkge1xuICAgICAgICAgICAgZXJyb3JzLnB1c2goYCR7dG9rZW5OYW1lfSBzaG91bGQgYWNjZXB0IHZhbGlkIGJnLSBhZGRyZXNzIGZvcm1hdGApO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmIChvZmNDb2luLmlzVmFsaWRBZGRyZXNzKGludmFsaWRCZ0FkZHJlc3MpKSB7XG4gICAgICAgICAgICBlcnJvcnMucHVzaChgJHt0b2tlbk5hbWV9IHNob3VsZCByZWplY3QgaW52YWxpZCBiZy0gYWRkcmVzcyBmb3JtYXRgKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0pO1xuXG4gICAgICBpZiAoZXJyb3JzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBGb3VuZCAke2Vycm9ycy5sZW5ndGh9IGFkZHJlc3MgdmFsaWRhdGlvbiBlcnJvcnM6XFxuYCArIGVycm9ycy5qb2luKCdcXG4nKSk7XG4gICAgICB9XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCd2YWxpZGF0ZSBhbGwgT0ZDIHRva2VucyBhcmUgcHJvcGVybHkgcmVnaXN0ZXJlZCcsIGZ1bmN0aW9uICgpIHtcbiAgICBpdCgnc2hvdWxkIGJlIGFibGUgdG8gaW5zdGFudGlhdGUgYWxsIE9GQyB0b2tlbnMnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBvZmNDb2lucyA9IGNvaW5zLmZpbHRlcigoY29pbikgPT4gY29pbi5mYW1pbHkgPT09ICdvZmMnKTtcbiAgICAgIGNvbnN0IGVycm9yczogc3RyaW5nW10gPSBbXTtcblxuICAgICAgb2ZjQ29pbnMuZm9yRWFjaCgob2ZjQ29pbikgPT4ge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGNvbnN0IGNvaW4gPSBiaXRnby5jb2luKG9mY0NvaW4ubmFtZSk7XG4gICAgICAgICAgaWYgKCFjb2luKSB7XG4gICAgICAgICAgICBlcnJvcnMucHVzaChgRmFpbGVkIHRvIGluc3RhbnRpYXRlICR7b2ZjQ29pbi5uYW1lfWApO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgIGVycm9ycy5wdXNoKGBFcnJvciBpbnN0YW50aWF0aW5nICR7b2ZjQ29pbi5uYW1lfTogJHtlLm1lc3NhZ2V9YCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuXG4gICAgICBpZiAoZXJyb3JzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBGb3VuZCAke2Vycm9ycy5sZW5ndGh9IGluc3RhbnRpYXRpb24gZXJyb3JzOlxcbmAgKyBlcnJvcnMuam9pbignXFxuJykpO1xuICAgICAgfVxuICAgIH0pO1xuICB9KTtcbn0pO1xuIl19