@bitgo-beta/sdk-coin-flrp 1.0.1-beta.36 → 1.0.1-beta.361

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. package/dist/src/flrp.d.ts +10 -17
  2. package/dist/src/flrp.d.ts.map +1 -1
  3. package/dist/src/flrp.js +51 -77
  4. package/dist/src/index.d.ts +0 -1
  5. package/dist/src/index.d.ts.map +1 -1
  6. package/dist/src/index.js +1 -2
  7. package/dist/src/lib/ExportInCTxBuilder.d.ts +51 -0
  8. package/dist/src/lib/ExportInCTxBuilder.d.ts.map +1 -0
  9. package/dist/src/lib/ExportInCTxBuilder.js +190 -0
  10. package/dist/src/lib/ExportInPTxBuilder.d.ts +47 -0
  11. package/dist/src/lib/ExportInPTxBuilder.d.ts.map +1 -0
  12. package/dist/src/lib/ExportInPTxBuilder.js +277 -0
  13. package/dist/src/lib/ImportInCTxBuilder.d.ts +48 -0
  14. package/dist/src/lib/ImportInCTxBuilder.d.ts.map +1 -0
  15. package/dist/src/lib/ImportInCTxBuilder.js +268 -0
  16. package/dist/src/lib/ImportInPTxBuilder.d.ts +33 -0
  17. package/dist/src/lib/ImportInPTxBuilder.d.ts.map +1 -0
  18. package/dist/src/lib/ImportInPTxBuilder.js +192 -0
  19. package/dist/src/lib/atomicInCTransactionBuilder.d.ts +18 -16
  20. package/dist/src/lib/atomicInCTransactionBuilder.d.ts.map +1 -1
  21. package/dist/src/lib/atomicInCTransactionBuilder.js +38 -36
  22. package/dist/src/lib/atomicTransactionBuilder.d.ts +57 -71
  23. package/dist/src/lib/atomicTransactionBuilder.d.ts.map +1 -1
  24. package/dist/src/lib/atomicTransactionBuilder.js +246 -209
  25. package/dist/src/lib/iface.d.ts +38 -61
  26. package/dist/src/lib/iface.d.ts.map +1 -1
  27. package/dist/src/lib/iface.js +13 -14
  28. package/dist/src/lib/index.d.ts +5 -0
  29. package/dist/src/lib/index.d.ts.map +1 -1
  30. package/dist/src/lib/index.js +12 -2
  31. package/dist/src/lib/keyPair.d.ts +5 -5
  32. package/dist/src/lib/keyPair.d.ts.map +1 -1
  33. package/dist/src/lib/keyPair.js +17 -9
  34. package/dist/src/lib/permissionlessValidatorTxBuilder.d.ts +43 -0
  35. package/dist/src/lib/permissionlessValidatorTxBuilder.d.ts.map +1 -0
  36. package/dist/src/lib/permissionlessValidatorTxBuilder.js +132 -0
  37. package/dist/src/lib/transaction.d.ts +25 -65
  38. package/dist/src/lib/transaction.d.ts.map +1 -1
  39. package/dist/src/lib/transaction.js +341 -199
  40. package/dist/src/lib/transactionBuilder.d.ts +107 -0
  41. package/dist/src/lib/transactionBuilder.d.ts.map +1 -0
  42. package/dist/src/lib/transactionBuilder.js +210 -0
  43. package/dist/src/lib/transactionBuilderFactory.d.ts +50 -30
  44. package/dist/src/lib/transactionBuilderFactory.d.ts.map +1 -1
  45. package/dist/src/lib/transactionBuilderFactory.js +129 -72
  46. package/dist/src/lib/utils.d.ts +78 -147
  47. package/dist/src/lib/utils.d.ts.map +1 -1
  48. package/dist/src/lib/utils.js +238 -324
  49. package/dist/test/resources/account.d.ts +51 -0
  50. package/dist/test/resources/account.d.ts.map +1 -0
  51. package/dist/test/resources/account.js +54 -0
  52. package/dist/test/resources/transactionData/exportInC.d.ts +20 -0
  53. package/dist/test/resources/transactionData/exportInC.d.ts.map +1 -0
  54. package/dist/test/resources/transactionData/exportInC.js +39 -0
  55. package/dist/test/resources/transactionData/exportInP.d.ts +69 -0
  56. package/dist/test/resources/transactionData/exportInP.d.ts.map +1 -0
  57. package/dist/test/resources/transactionData/exportInP.js +140 -0
  58. package/dist/test/resources/transactionData/importInC.d.ts +27 -0
  59. package/dist/test/resources/transactionData/importInC.d.ts.map +1 -0
  60. package/dist/test/resources/transactionData/importInC.js +44 -0
  61. package/dist/test/resources/transactionData/importInP.d.ts +35 -0
  62. package/dist/test/resources/transactionData/importInP.d.ts.map +1 -0
  63. package/dist/test/resources/transactionData/importInP.js +58 -0
  64. package/dist/test/unit/flrp.js +446 -68
  65. package/dist/test/unit/lib/exportInCTxBuilder.d.ts +2 -0
  66. package/dist/test/unit/lib/exportInCTxBuilder.d.ts.map +1 -0
  67. package/dist/test/unit/lib/exportInCTxBuilder.js +192 -0
  68. package/dist/test/unit/lib/exportInPTxBuilder.d.ts +2 -0
  69. package/dist/test/unit/lib/exportInPTxBuilder.d.ts.map +1 -0
  70. package/dist/test/unit/lib/exportInPTxBuilder.js +325 -0
  71. package/dist/test/unit/lib/importInCTxBuilder.d.ts +2 -0
  72. package/dist/test/unit/lib/importInCTxBuilder.d.ts.map +1 -0
  73. package/dist/test/unit/lib/importInCTxBuilder.js +400 -0
  74. package/dist/test/unit/lib/importInPTxBuilder.d.ts +2 -0
  75. package/dist/test/unit/lib/importInPTxBuilder.d.ts.map +1 -0
  76. package/dist/test/unit/lib/importInPTxBuilder.js +307 -0
  77. package/dist/test/unit/lib/keyPair.d.ts +2 -0
  78. package/dist/test/unit/lib/keyPair.d.ts.map +1 -0
  79. package/dist/test/unit/lib/keyPair.js +158 -0
  80. package/dist/test/unit/lib/signFlowTestSuit.d.ts +20 -0
  81. package/dist/test/unit/lib/signFlowTestSuit.d.ts.map +1 -0
  82. package/dist/test/unit/lib/signFlowTestSuit.js +83 -0
  83. package/dist/test/unit/lib/transactionBuilderFactory.d.ts +2 -0
  84. package/dist/test/unit/lib/transactionBuilderFactory.d.ts.map +1 -0
  85. package/dist/test/unit/lib/transactionBuilderFactory.js +60 -0
  86. package/dist/test/unit/lib/utils.js +539 -207
  87. package/dist/tsconfig.tsbuildinfo +1 -1
  88. package/package.json +18 -10
  89. package/.eslintignore +0 -5
  90. package/.eslintrc.json +0 -7
  91. package/.mocharc.yml +0 -8
  92. package/CHANGELOG.md +0 -0
  93. package/dist/src/iface.d.ts +0 -25
  94. package/dist/src/iface.d.ts.map +0 -1
  95. package/dist/src/iface.js +0 -3
  96. package/dist/src/lib/constants.d.ts +0 -11
  97. package/dist/src/lib/constants.d.ts.map +0 -1
  98. package/dist/src/lib/constants.js +0 -17
  99. package/dist/src/lib/errors.d.ts +0 -8
  100. package/dist/src/lib/errors.d.ts.map +0 -1
  101. package/dist/src/lib/errors.js +0 -19
  102. package/dist/src/lib/exportInCTxBuilder.d.ts +0 -77
  103. package/dist/src/lib/exportInCTxBuilder.d.ts.map +0 -1
  104. package/dist/src/lib/exportInCTxBuilder.js +0 -170
  105. package/dist/src/lib/exportInPTxBuilder.d.ts +0 -30
  106. package/dist/src/lib/exportInPTxBuilder.d.ts.map +0 -1
  107. package/dist/src/lib/exportInPTxBuilder.js +0 -56
  108. package/dist/test/unit/lib/atomicTransactionBuilder.d.ts +0 -2
  109. package/dist/test/unit/lib/atomicTransactionBuilder.d.ts.map +0 -1
  110. package/dist/test/unit/lib/atomicTransactionBuilder.js +0 -222
  111. package/dist/test/unit/lib/exportTxBuilder.d.ts +0 -2
  112. package/dist/test/unit/lib/exportTxBuilder.d.ts.map +0 -1
  113. package/dist/test/unit/lib/exportTxBuilder.js +0 -45
  114. package/dist/test/unit/lib/transaction.d.ts +0 -2
  115. package/dist/test/unit/lib/transaction.d.ts.map +0 -1
  116. package/dist/test/unit/lib/transaction.js +0 -460
  117. package/dist/test/unit/smoke.d.ts +0 -2
  118. package/dist/test/unit/smoke.d.ts.map +0 -1
  119. package/dist/test/unit/smoke.js +0 -23
@@ -34,253 +34,585 @@ var __importStar = (this && this.__importStar) || (function () {
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  const statics_1 = require("@bitgo-beta/statics");
37
- const sdk_core_1 = require("@bitgo-beta/sdk-core");
38
37
  const assert = __importStar(require("assert"));
39
38
  const utils_1 = require("../../../src/lib/utils");
39
+ const account_1 = require("../../resources/account");
40
+ const secp256k1_1 = require("@bitgo-beta/secp256k1");
41
+ const exportInC_1 = require("../../resources/transactionData/exportInC");
42
+ const importInP_1 = require("../../resources/transactionData/importInP");
43
+ const exportInP_1 = require("../../resources/transactionData/exportInP");
44
+ const importInC_1 = require("../../resources/transactionData/importInC");
45
+ const lib_1 = require("../../../src/lib");
46
+ const flarejs_1 = require("@flarenetwork/flarejs");
40
47
  describe('Utils', function () {
41
48
  let utils;
49
+ const network = statics_1.coins.get('flrp').network;
42
50
  beforeEach(function () {
43
51
  utils = new utils_1.Utils();
44
52
  });
45
53
  describe('includeIn', function () {
46
- it('should return true when all wallet addresses are in output addresses', function () {
47
- const walletAddresses = ['addr1', 'addr2'];
48
- const outputAddresses = ['addr1', 'addr2', 'addr3'];
49
- assert.strictEqual(utils.includeIn(walletAddresses, outputAddresses), true);
54
+ it('should return true when all wallet addresses are in UTXO output addresses', function () {
55
+ const walletAddresses = [exportInC_1.EXPORT_IN_C.pAddresses[0], exportInC_1.EXPORT_IN_C.pAddresses[1]];
56
+ const utxoOutputAddresses = [...exportInC_1.EXPORT_IN_C.pAddresses];
57
+ assert.strictEqual(utils.includeIn(walletAddresses, utxoOutputAddresses), true);
50
58
  });
51
- it('should return false when not all wallet addresses are in output addresses', function () {
52
- const walletAddresses = ['addr1', 'addr2'];
53
- const outputAddresses = ['addr1', 'addr3'];
54
- assert.strictEqual(utils.includeIn(walletAddresses, outputAddresses), false);
59
+ it('should return false when some wallet addresses are not in UTXO output addresses', function () {
60
+ const walletAddresses = [exportInC_1.EXPORT_IN_C.pAddresses[0], account_1.ACCOUNT_3.address];
61
+ const utxoOutputAddresses = [exportInC_1.EXPORT_IN_C.pAddresses[0], exportInC_1.EXPORT_IN_C.pAddresses[1]];
62
+ assert.strictEqual(utils.includeIn(walletAddresses, utxoOutputAddresses), false);
55
63
  });
56
64
  it('should return true for empty wallet addresses', function () {
57
65
  const walletAddresses = [];
58
- const outputAddresses = ['addr1', 'addr2'];
59
- assert.strictEqual(utils.includeIn(walletAddresses, outputAddresses), true);
60
- });
61
- it('should return false when wallet address not found in empty output addresses', function () {
62
- const walletAddresses = ['addr1'];
63
- const outputAddresses = [];
64
- assert.strictEqual(utils.includeIn(walletAddresses, outputAddresses), false);
66
+ const utxoOutputAddresses = [exportInC_1.EXPORT_IN_C.pAddresses[0]];
67
+ assert.strictEqual(utils.includeIn(walletAddresses, utxoOutputAddresses), true);
65
68
  });
66
69
  });
67
70
  describe('isValidAddress', function () {
68
- it('should validate single valid Flare addresses', function () {
69
- // Flare addresses start with 'flare:' or 'C-flare:'
70
- const validAddresses = [
71
- 'flare1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq6f4avh',
72
- 'C-flare1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq6f4avh',
73
- ];
74
- validAddresses.forEach((addr) => {
75
- // Note: The current implementation uses regex validation
76
- // This test will be updated once proper Flare address validation is implemented
77
- const result = utils.isValidAddress(addr);
78
- // Currently returns false due to placeholder implementation
79
- assert.strictEqual(typeof result, 'boolean');
80
- });
71
+ it('should return true for valid mainnet P-chain address', function () {
72
+ assert.strictEqual(utils.isValidAddress(account_1.SEED_ACCOUNT.addressMainnet), true);
81
73
  });
82
- it('should validate array of addresses', function () {
83
- const addresses = [
84
- 'flare1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq6f4avh',
85
- 'flare1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa6f4avh',
86
- ];
87
- const result = utils.isValidAddress(addresses);
88
- assert.strictEqual(typeof result, 'boolean');
89
- });
90
- it('should validate addresses separated by ~', function () {
91
- const addressString = 'flare1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq6f4avh~flare1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa6f4avh';
92
- const result = utils.isValidAddress(addressString);
93
- assert.strictEqual(typeof result, 'boolean');
94
- });
95
- it('should reject obviously invalid addresses', function () {
96
- const invalidAddresses = [
97
- '',
98
- 'invalid',
99
- '123',
100
- 'bitcoin1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq',
101
- 'eth:0x1234567890123456789012345678901234567890',
102
- ];
103
- invalidAddresses.forEach((addr) => {
104
- const result = utils.isValidAddress(addr);
105
- // Current implementation may not catch all invalid addresses
106
- assert.strictEqual(typeof result, 'boolean');
107
- });
74
+ it('should return true for valid testnet P-chain address', function () {
75
+ assert.strictEqual(utils.isValidAddress(account_1.SEED_ACCOUNT.addressTestnet), true);
76
+ });
77
+ it('should return true for valid NodeID address', function () {
78
+ assert.strictEqual(utils.isValidAddress('NodeID-abc123xyz'), true);
79
+ });
80
+ it('should return true for array of valid addresses', function () {
81
+ assert.strictEqual(utils.isValidAddress(exportInC_1.EXPORT_IN_C.pAddresses), true);
82
+ });
83
+ it('should return true for tilde-separated addresses', function () {
84
+ const combined = exportInC_1.EXPORT_IN_C.pAddresses.join('~');
85
+ assert.strictEqual(utils.isValidAddress(combined), true);
86
+ });
87
+ it('should return false for invalid address format', function () {
88
+ assert.strictEqual(utils.isValidAddress('invalid'), false);
89
+ });
90
+ it('should return false for address without prefix', function () {
91
+ assert.strictEqual(utils.isValidAddress('flare1abc123'), false);
92
+ });
93
+ });
94
+ describe('isValidBlockId', function () {
95
+ it('should return true for valid 32-byte hex block ID', function () {
96
+ assert.strictEqual(utils.isValidBlockId(account_1.SEED_ACCOUNT.privateKey), true); // 64 hex chars = 32 bytes
97
+ });
98
+ it('should return false for invalid length block ID', function () {
99
+ assert.strictEqual(utils.isValidBlockId(account_1.INVALID_SHORT_KEYPAIR_KEY), false);
100
+ });
101
+ it('should return false for empty block ID', function () {
102
+ assert.strictEqual(utils.isValidBlockId(''), false);
108
103
  });
109
104
  });
110
- describe('isValidAddressRegex', function () {
111
- it('should test address format with regex', function () {
112
- const testAddress = 'flare1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq6f4avh';
113
- const result = utils['isValidAddressRegex'](testAddress);
114
- assert.strictEqual(typeof result, 'boolean');
105
+ describe('isValidPublicKey', function () {
106
+ it('should return true for valid compressed public key starting with 03', function () {
107
+ assert.strictEqual(utils.isValidPublicKey(account_1.SEED_ACCOUNT.publicKey), true);
115
108
  });
116
- it('should reject empty strings', function () {
117
- const result = utils['isValidAddressRegex']('');
118
- assert.strictEqual(result, false);
109
+ it('should return true for valid compressed public key starting with 02', function () {
110
+ assert.strictEqual(utils.isValidPublicKey(account_1.ACCOUNT_1.publicKey), true);
111
+ });
112
+ it('should return true for another valid compressed public key', function () {
113
+ assert.strictEqual(utils.isValidPublicKey(account_1.ACCOUNT_2.publicKey), true);
114
+ });
115
+ it('should return true for valid xpub', function () {
116
+ assert.strictEqual(utils.isValidPublicKey(account_1.SEED_ACCOUNT.xPublicKey), true);
117
+ });
118
+ it('should return true for ACCOUNT_1 xpub', function () {
119
+ assert.strictEqual(utils.isValidPublicKey(account_1.ACCOUNT_1.xPublicKey), true);
120
+ });
121
+ it('should return false for invalid short public key', function () {
122
+ assert.strictEqual(utils.isValidPublicKey(account_1.INVALID_SHORT_KEYPAIR_KEY), false);
123
+ });
124
+ it('should return false for compressed key with wrong prefix', function () {
125
+ const invalidKey = '05' + account_1.SEED_ACCOUNT.privateKey;
126
+ assert.strictEqual(utils.isValidPublicKey(invalidKey), false);
127
+ });
128
+ it('should return false for non-hex public key', function () {
129
+ const invalidKey = 'zz' + account_1.SEED_ACCOUNT.privateKey;
130
+ assert.strictEqual(utils.isValidPublicKey(invalidKey), false);
119
131
  });
120
132
  });
121
- describe('isValidTransactionId', function () {
122
- it('should throw NotImplementedError', function () {
123
- assert.throws(() => utils.isValidTransactionId('txid123'), sdk_core_1.NotImplementedError, 'isValidTransactionId not implemented');
133
+ describe('isValidPrivateKey', function () {
134
+ it('should return true for valid 64-char hex private key', function () {
135
+ assert.strictEqual(utils.isValidPrivateKey(account_1.SEED_ACCOUNT.privateKey), true);
136
+ });
137
+ it('should return true for ACCOUNT_1 private key', function () {
138
+ assert.strictEqual(utils.isValidPrivateKey(account_1.ACCOUNT_1.privateKey), true);
139
+ });
140
+ it('should return true for ACCOUNT_2 private key', function () {
141
+ assert.strictEqual(utils.isValidPrivateKey(account_1.ACCOUNT_2.privateKey), true);
142
+ });
143
+ it('should return true for valid xprv', function () {
144
+ assert.strictEqual(utils.isValidPrivateKey(account_1.SEED_ACCOUNT.xPrivateKey), true);
145
+ });
146
+ it('should return true for 66-char private key ending with 01', function () {
147
+ const extendedKey = account_1.SEED_ACCOUNT.privateKey + '01';
148
+ assert.strictEqual(utils.isValidPrivateKey(extendedKey), true);
149
+ });
150
+ it('should return false for 66-char private key not ending with 01', function () {
151
+ assert.strictEqual(utils.isValidPrivateKey(account_1.INVALID_LONG_KEYPAIR_PRV), false);
152
+ });
153
+ it('should return false for invalid short private key', function () {
154
+ assert.strictEqual(utils.isValidPrivateKey(account_1.INVALID_SHORT_KEYPAIR_KEY), false);
155
+ });
156
+ it('should return false for non-hex private key', function () {
157
+ const invalidKey = 'zz' + account_1.SEED_ACCOUNT.privateKey.slice(2);
158
+ assert.strictEqual(utils.isValidPrivateKey(invalidKey), false);
124
159
  });
125
160
  });
126
- describe('isValidSignature', function () {
127
- it('should throw NotImplementedError', function () {
128
- assert.throws(() => utils.isValidSignature('signature123'), sdk_core_1.NotImplementedError, 'isValidSignature not implemented');
161
+ describe('allHexChars', function () {
162
+ it('should return true for valid private key hex', function () {
163
+ assert.strictEqual(utils.allHexChars(account_1.SEED_ACCOUNT.privateKey), true);
164
+ });
165
+ it('should return true for valid public key hex', function () {
166
+ assert.strictEqual(utils.allHexChars(account_1.SEED_ACCOUNT.publicKey), true);
167
+ });
168
+ it('should return true for hex string with 0x prefix', function () {
169
+ assert.strictEqual(utils.allHexChars(exportInC_1.EXPORT_IN_C.cHexAddress), true);
170
+ });
171
+ it('should return true for valid signature hex', function () {
172
+ assert.strictEqual(utils.allHexChars(account_1.SEED_ACCOUNT.signature), true);
173
+ });
174
+ it('should return false for non-hex characters', function () {
175
+ assert.strictEqual(utils.allHexChars('ghijkl'), false);
176
+ });
177
+ it('should return false for empty string', function () {
178
+ assert.strictEqual(utils.allHexChars(''), false);
129
179
  });
130
180
  });
131
- describe('createSignature', function () {
132
- it('should create signature using secp256k1', function () {
133
- const network = statics_1.coins.get('flrp').network;
134
- const message = Buffer.from('hello world', 'utf8');
135
- const privateKey = Buffer.from('0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef', 'hex');
181
+ describe('createSignature and verifySignature', function () {
182
+ it('should create a valid 65-byte signature', function () {
183
+ const message = Buffer.from(account_1.SEED_ACCOUNT.message, 'utf8');
184
+ const privateKey = Buffer.from(account_1.SEED_ACCOUNT.privateKey, 'hex');
136
185
  const signature = utils.createSignature(network, message, privateKey);
137
186
  assert.ok(signature instanceof Buffer);
138
- assert.ok(signature.length > 0);
139
- });
140
- it('should create different signatures for different messages', function () {
141
- const network = statics_1.coins.get('flrp').network;
142
- const message1 = Buffer.from('message 1', 'utf8');
143
- const message2 = Buffer.from('message 2', 'utf8');
144
- const privateKey = Buffer.from('0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef', 'hex');
145
- const sig1 = utils.createSignature(network, message1, privateKey);
146
- const sig2 = utils.createSignature(network, message2, privateKey);
147
- assert.notDeepStrictEqual(sig1, sig2);
148
- });
149
- it('should throw error for invalid private key', function () {
150
- const network = statics_1.coins.get('flrp').network;
151
- const message = Buffer.from('hello world', 'utf8');
152
- const invalidPrivateKey = Buffer.from('invalid', 'utf8');
153
- assert.throws(() => utils.createSignature(network, message, invalidPrivateKey), /Failed to create signature/);
187
+ assert.strictEqual(signature.length, 65);
154
188
  });
155
- });
156
- describe('verifySignature', function () {
157
- it('should verify valid signature', function () {
158
- const network = statics_1.coins.get('flrp').network;
159
- const message = Buffer.from('hello world', 'utf8');
160
- const privateKey = Buffer.from('0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef', 'hex');
161
- // Create signature
189
+ it('should verify a valid signature', function () {
190
+ const message = Buffer.from(account_1.SEED_ACCOUNT.message, 'utf8');
191
+ const privateKey = Buffer.from(account_1.SEED_ACCOUNT.privateKey, 'hex');
192
+ const publicKey = Buffer.from(account_1.SEED_ACCOUNT.publicKey, 'hex');
162
193
  const signature = utils.createSignature(network, message, privateKey);
163
- // Get public key (this would normally come from the private key)
164
- // For testing, we'll use a mock public key approach
165
- const publicKey = Buffer.from('02' + '0'.repeat(62), 'hex'); // Compressed public key format
166
- // Note: This test may fail if the public key doesn't match the private key
167
- // In a real implementation, you'd derive the public key from the private key
168
- // The method returns false when verification fails instead of throwing
169
- const isValid = utils.verifySignature(network, message, signature, publicKey);
170
- assert.strictEqual(typeof isValid, 'boolean');
171
- // With mock public key, this should return false
172
- assert.strictEqual(isValid, false);
194
+ const sigOnly = signature.slice(0, 64);
195
+ const messageHash = utils.sha256(message);
196
+ const isValid = utils.verifySignature(messageHash, sigOnly, publicKey);
197
+ assert.strictEqual(isValid, true);
173
198
  });
174
199
  it('should return false for invalid signature', function () {
175
- const network = statics_1.coins.get('flrp').network;
176
- const message = Buffer.from('hello world', 'utf8');
177
- const invalidSignature = Buffer.from('invalid signature', 'utf8');
178
- const publicKey = Buffer.from('02' + '0'.repeat(62), 'hex');
179
- // This should return false due to invalid signature format
180
- // The method catches errors internally and returns false
181
- const result = utils.verifySignature(network, message, invalidSignature, publicKey);
182
- assert.strictEqual(result, false);
200
+ const message = Buffer.from(account_1.SEED_ACCOUNT.message, 'utf8');
201
+ const publicKey = Buffer.from(account_1.SEED_ACCOUNT.publicKey, 'hex');
202
+ const invalidSignature = Buffer.alloc(64);
203
+ const messageHash = utils.sha256(message);
204
+ const isValid = utils.verifySignature(messageHash, invalidSignature, publicKey);
205
+ assert.strictEqual(isValid, false);
206
+ });
207
+ it('should create signature with ACCOUNT_1 keys', function () {
208
+ const message = Buffer.from(account_1.SEED_ACCOUNT.message, 'utf8');
209
+ const privateKey = Buffer.from(account_1.ACCOUNT_1.privateKey, 'hex');
210
+ const signature = utils.createSignature(network, message, privateKey);
211
+ assert.ok(signature instanceof Buffer);
212
+ assert.strictEqual(signature.length, 65);
213
+ });
214
+ });
215
+ describe('createNewSig', function () {
216
+ it('should create a signature from valid signature hex string', function () {
217
+ const sig = utils.createNewSig(account_1.SEED_ACCOUNT.signature);
218
+ assert.ok(sig);
219
+ });
220
+ it('should create a signature from export signature hex', function () {
221
+ const sigHex = utils.removeHexPrefix(exportInC_1.EXPORT_IN_C.signature[0]);
222
+ const sig = utils.createNewSig(sigHex);
223
+ assert.ok(sig);
224
+ });
225
+ it('should pad short hex strings', function () {
226
+ const sigHex = account_1.INVALID_SHORT_KEYPAIR_KEY;
227
+ const sig = utils.createNewSig(sigHex);
228
+ assert.ok(sig);
229
+ });
230
+ });
231
+ describe('createEmptySigWithAddress and getAddressFromEmptySig', function () {
232
+ it('should create empty signature with embedded C-chain address', function () {
233
+ const addressHex = utils.removeHexPrefix(exportInC_1.EXPORT_IN_C.cHexAddress);
234
+ const sig = utils.createEmptySigWithAddress(addressHex);
235
+ assert.ok(sig);
236
+ });
237
+ it('should extract embedded address from empty signature', function () {
238
+ const addressHex = utils.removeHexPrefix(exportInC_1.EXPORT_IN_C.cHexAddress).toLowerCase();
239
+ const sig = utils.createEmptySigWithAddress(addressHex);
240
+ // Get signature bytes and convert to hex
241
+ const sigBytes = sig.toBytes();
242
+ const sigHex = Buffer.from(sigBytes).toString('hex');
243
+ const extractedAddress = utils.getAddressFromEmptySig(sigHex);
244
+ assert.strictEqual(extractedAddress, addressHex);
245
+ });
246
+ it('should handle 0x prefixed address', function () {
247
+ const sig = utils.createEmptySigWithAddress(exportInC_1.EXPORT_IN_C.cHexAddress);
248
+ assert.ok(sig);
249
+ });
250
+ it('should return empty string for short signature', function () {
251
+ const shortSig = account_1.SEED_ACCOUNT.privateKey; // 64 chars, less than 130
252
+ assert.strictEqual(utils.getAddressFromEmptySig(shortSig), '');
253
+ });
254
+ });
255
+ describe('sha256', function () {
256
+ it('should compute SHA256 hash of message', function () {
257
+ const data = Buffer.from(account_1.SEED_ACCOUNT.message, 'utf8');
258
+ const hash = utils.sha256(data);
259
+ assert.ok(hash instanceof Buffer);
260
+ assert.strictEqual(hash.length, 32);
261
+ });
262
+ it('should produce consistent hash for same input', function () {
263
+ const data = Buffer.from(account_1.SEED_ACCOUNT.message, 'utf8');
264
+ const hash1 = utils.sha256(data);
265
+ const hash2 = utils.sha256(data);
266
+ assert.deepStrictEqual(hash1, hash2);
267
+ });
268
+ it('should produce different hash for different input', function () {
269
+ const data1 = Buffer.from(account_1.SEED_ACCOUNT.message, 'utf8');
270
+ const data2 = Buffer.from(account_1.SEED_ACCOUNT.privateKey, 'utf8');
271
+ const hash1 = utils.sha256(data1);
272
+ const hash2 = utils.sha256(data2);
273
+ assert.notDeepStrictEqual(hash1, hash2);
274
+ });
275
+ });
276
+ describe('validateRawTransaction', function () {
277
+ it('should not throw for valid unsigned hex transaction', function () {
278
+ const rawTx = utils.removeHexPrefix(exportInC_1.EXPORT_IN_C.unsignedHex);
279
+ assert.doesNotThrow(() => utils.validateRawTransaction(rawTx));
280
+ });
281
+ it('should not throw for valid signed hex transaction', function () {
282
+ const rawTx = utils.removeHexPrefix(exportInC_1.EXPORT_IN_C.signedHex);
283
+ assert.doesNotThrow(() => utils.validateRawTransaction(rawTx));
284
+ });
285
+ it('should not throw for import transaction hex', function () {
286
+ const rawTx = utils.removeHexPrefix(importInP_1.IMPORT_IN_P.unsignedHex);
287
+ assert.doesNotThrow(() => utils.validateRawTransaction(rawTx));
288
+ });
289
+ it('should throw for empty transaction', function () {
290
+ assert.throws(() => utils.validateRawTransaction(''), /Raw transaction is empty/);
291
+ });
292
+ it('should throw for non-hex transaction', function () {
293
+ assert.throws(() => utils.validateRawTransaction('xyz123'), /Raw transaction is not hex string/);
294
+ });
295
+ });
296
+ describe('removeHexPrefix', function () {
297
+ it('should remove 0x prefix from C-chain address', function () {
298
+ assert.strictEqual(utils.removeHexPrefix(exportInC_1.EXPORT_IN_C.cHexAddress), exportInC_1.EXPORT_IN_C.cHexAddress.slice(2));
299
+ });
300
+ it('should remove 0x prefix from unsigned hex', function () {
301
+ assert.strictEqual(utils.removeHexPrefix(exportInC_1.EXPORT_IN_C.unsignedHex), exportInC_1.EXPORT_IN_C.unsignedHex.slice(2));
302
+ });
303
+ it('should return string unchanged if no prefix', function () {
304
+ assert.strictEqual(utils.removeHexPrefix(account_1.SEED_ACCOUNT.privateKey), account_1.SEED_ACCOUNT.privateKey);
305
+ });
306
+ it('should handle empty string', function () {
307
+ assert.strictEqual(utils.removeHexPrefix(''), '');
183
308
  });
184
309
  });
185
- describe('address parsing utilities', function () {
186
- it('should handle address separator constants', function () {
187
- const { ADDRESS_SEPARATOR } = require('../../../src/lib/iface');
188
- assert.strictEqual(ADDRESS_SEPARATOR, '~');
310
+ describe('outputidxNumberToBuffer and outputidxBufferToNumber', function () {
311
+ it('should convert output index to buffer and back', function () {
312
+ const outputIdx = importInP_1.IMPORT_IN_P.outputs[0].outputidx;
313
+ const buffer = utils.outputidxNumberToBuffer(outputIdx);
314
+ const result = utils.outputidxBufferToNumber(buffer);
315
+ assert.strictEqual(result, outputIdx);
316
+ });
317
+ it('should handle nonce value', function () {
318
+ const nonceStr = exportInC_1.EXPORT_IN_C.nonce.toString();
319
+ const buffer = utils.outputidxNumberToBuffer(nonceStr);
320
+ const result = utils.outputidxBufferToNumber(buffer);
321
+ assert.strictEqual(result, nonceStr);
322
+ });
323
+ it('should produce 4-byte buffer', function () {
324
+ const buffer = utils.outputidxNumberToBuffer('255');
325
+ assert.strictEqual(buffer.length, 4);
326
+ });
327
+ });
328
+ describe('addressToString', function () {
329
+ it('should convert address buffer to mainnet bech32 string', function () {
330
+ const address = account_1.SEED_ACCOUNT.addressMainnet;
331
+ const addressBuffer = utils.parseAddress(address);
332
+ const result = utils.addressToString('flare', 'P', addressBuffer);
333
+ assert.ok(result.startsWith('P-'));
334
+ assert.ok(result.includes('flare'));
335
+ });
336
+ it('should convert address buffer to testnet bech32 string', function () {
337
+ const address = account_1.SEED_ACCOUNT.addressTestnet;
338
+ const addressBuffer = utils.parseAddress(address);
339
+ const result = utils.addressToString('costwo', 'P', addressBuffer);
340
+ assert.ok(result.startsWith('P-'));
341
+ assert.ok(result.includes('costwo'));
342
+ });
343
+ });
344
+ describe('cb58Encode and cb58Decode', function () {
345
+ it('should encode and decode target chain ID correctly', function () {
346
+ const encoded = exportInC_1.EXPORT_IN_C.targetChainId;
347
+ const decoded = utils.cb58Decode(encoded);
348
+ const reEncoded = utils.cb58Encode(decoded);
349
+ assert.strictEqual(reEncoded, encoded);
350
+ });
351
+ it('should encode and decode source chain ID correctly', function () {
352
+ const encoded = importInP_1.IMPORT_IN_P.sourceChainId;
353
+ const decoded = utils.cb58Decode(encoded);
354
+ const reEncoded = utils.cb58Encode(decoded);
355
+ assert.strictEqual(reEncoded, encoded);
356
+ });
357
+ it('should throw for invalid checksum', function () {
358
+ assert.throws(() => utils.cb58Decode('1111111111111'), /Invalid checksum/);
359
+ });
360
+ });
361
+ describe('parseAddress and stringToAddress', function () {
362
+ it('should parse hex address with 0x prefix', function () {
363
+ const buffer = utils.parseAddress(exportInC_1.EXPORT_IN_C.cHexAddress);
364
+ assert.ok(buffer instanceof Buffer);
365
+ assert.strictEqual(buffer.length, 20);
366
+ });
367
+ it('should parse raw hex address from outputs', function () {
368
+ const address = importInP_1.IMPORT_IN_P.outputs[0].addresses[0];
369
+ const buffer = utils.parseAddress(address);
370
+ assert.ok(buffer instanceof Buffer);
371
+ assert.strictEqual(buffer.length, 20);
189
372
  });
190
- it('should handle input separator constants', function () {
191
- const { INPUT_SEPARATOR } = require('../../../src/lib/iface');
192
- assert.strictEqual(INPUT_SEPARATOR, ':');
373
+ it('should parse mainnet bech32 address', function () {
374
+ const buffer = utils.parseAddress(account_1.SEED_ACCOUNT.addressMainnet);
375
+ assert.ok(buffer instanceof Buffer);
376
+ assert.strictEqual(buffer.length, 20);
377
+ });
378
+ it('should parse testnet bech32 address', function () {
379
+ const buffer = utils.parseAddress(account_1.SEED_ACCOUNT.addressTestnet);
380
+ assert.ok(buffer instanceof Buffer);
381
+ assert.strictEqual(buffer.length, 20);
382
+ });
383
+ it('should parse P-chain addresses from export data', function () {
384
+ exportInC_1.EXPORT_IN_C.pAddresses.forEach((address) => {
385
+ const buffer = utils.parseAddress(address);
386
+ assert.ok(buffer instanceof Buffer);
387
+ assert.strictEqual(buffer.length, 20);
388
+ });
389
+ });
390
+ it('should throw for address without dash separator', function () {
391
+ assert.throws(() => utils.parseAddress('flare1abc'), /Valid address should include -/);
392
+ });
393
+ it('should throw for invalid HRP', function () {
394
+ assert.throws(() => utils.parseAddress('P-invalid1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq5evzmy'), /Invalid HRP/);
193
395
  });
194
396
  });
195
- describe('error handling', function () {
196
- it('should properly extend base utils', function () {
197
- // Test that utils class exists and has expected methods
198
- assert.ok('isValidAddress' in utils);
199
- assert.ok('includeIn' in utils);
200
- assert.ok('createSignature' in utils);
201
- assert.ok('verifySignature' in utils);
202
- });
203
- it('should handle parsing errors gracefully', function () {
204
- // Test that utils can handle malformed input without crashing
205
- // Note: These may throw errors, which is acceptable behavior
206
- try {
207
- utils.isValidAddress(null);
208
- utils.isValidAddress(undefined);
209
- }
210
- catch (error) {
211
- // Expected behavior - utils should handle or throw meaningful errors
212
- assert.ok(error instanceof Error);
213
- }
397
+ describe('flareIdString', function () {
398
+ it('should create Id from private key hex string', function () {
399
+ const id = utils.flareIdString(account_1.SEED_ACCOUNT.privateKey);
400
+ assert.ok(id);
401
+ });
402
+ it('should create Id from asset ID hex', function () {
403
+ // Asset ID is typically 32 bytes (64 hex chars)
404
+ const assetIdHex = account_1.SEED_ACCOUNT.privateKey; // Using as a 32-byte hex
405
+ const id = utils.flareIdString(assetIdHex);
406
+ assert.ok(id);
214
407
  });
215
408
  });
216
- describe('constants validation', function () {
217
- it('should have correct constant values', function () {
218
- const constants = require('../../../src/lib/constants');
219
- assert.strictEqual(typeof constants.DECODED_BLOCK_ID_LENGTH, 'number');
220
- assert.strictEqual(typeof constants.SHORT_PUB_KEY_LENGTH, 'number');
221
- assert.strictEqual(typeof constants.COMPRESSED_PUBLIC_KEY_LENGTH, 'number');
222
- assert.strictEqual(typeof constants.UNCOMPRESSED_PUBLIC_KEY_LENGTH, 'number');
223
- assert.strictEqual(typeof constants.RAW_PRIVATE_KEY_LENGTH, 'number');
224
- assert.strictEqual(typeof constants.SUFFIXED_PRIVATE_KEY_LENGTH, 'number');
225
- assert.strictEqual(typeof constants.PRIVATE_KEY_COMPRESSED_SUFFIX, 'string');
226
- assert.strictEqual(typeof constants.OUTPUT_INDEX_HEX_LENGTH, 'number');
227
- assert.ok(constants.ADDRESS_REGEX instanceof RegExp);
228
- assert.ok(constants.HEX_REGEX instanceof RegExp);
409
+ describe('recoverySignature', function () {
410
+ it('should recover public key from valid signature', function () {
411
+ const message = Buffer.from(account_1.SEED_ACCOUNT.message, 'utf8');
412
+ const privateKey = Buffer.from(account_1.SEED_ACCOUNT.privateKey, 'hex');
413
+ // Create signature using the same private key (createSignature hashes the message internally)
414
+ const signature = utils.createSignature(network, message, privateKey);
415
+ // Recover public key - pass the hashed message since recoverySignature expects pre-hashed
416
+ const messageHash = utils.sha256(message);
417
+ const recoveredPubKey = utils.recoverySignature(messageHash, signature);
418
+ assert.ok(recoveredPubKey instanceof Buffer);
419
+ assert.strictEqual(recoveredPubKey.length, 33); // Should be compressed public key (33 bytes)
420
+ });
421
+ it('should recover same public key for same message and signature', function () {
422
+ const message = Buffer.from(account_1.SEED_ACCOUNT.message, 'utf8');
423
+ const privateKey = Buffer.from(account_1.SEED_ACCOUNT.privateKey, 'hex');
424
+ const signature = utils.createSignature(network, message, privateKey);
425
+ const messageHash = utils.sha256(message);
426
+ const pubKey1 = utils.recoverySignature(messageHash, signature);
427
+ const pubKey2 = utils.recoverySignature(messageHash, signature);
428
+ assert.deepStrictEqual(pubKey1, pubKey2);
429
+ });
430
+ it('should recover public key that matches original key', function () {
431
+ const message = Buffer.from(account_1.SEED_ACCOUNT.message, 'utf8');
432
+ const privateKey = Buffer.from(account_1.SEED_ACCOUNT.privateKey, 'hex');
433
+ // Get original public key
434
+ const originalPubKey = Buffer.from(secp256k1_1.ecc.pointFromScalar(privateKey, true));
435
+ // Create signature and recover public key
436
+ const signature = utils.createSignature(network, message, privateKey);
437
+ const messageHash = utils.sha256(message);
438
+ const recoveredPubKey = utils.recoverySignature(messageHash, signature);
439
+ // Convert both to hex strings for comparison
440
+ assert.strictEqual(recoveredPubKey.toString('hex'), originalPubKey.toString('hex'));
441
+ });
442
+ it('should recover public key using ACCOUNT_1 keys', function () {
443
+ const message = Buffer.from(account_1.SEED_ACCOUNT.message, 'utf8');
444
+ const privateKey = Buffer.from(account_1.ACCOUNT_1.privateKey, 'hex');
445
+ const originalPubKey = Buffer.from(secp256k1_1.ecc.pointFromScalar(privateKey, true));
446
+ const signature = utils.createSignature(network, message, privateKey);
447
+ const messageHash = utils.sha256(message);
448
+ const recoveredPubKey = utils.recoverySignature(messageHash, signature);
449
+ assert.strictEqual(recoveredPubKey.toString('hex'), originalPubKey.toString('hex'));
450
+ });
451
+ it('should throw error for invalid signature length', function () {
452
+ const messageHash = utils.sha256(Buffer.from(account_1.SEED_ACCOUNT.message, 'utf8'));
453
+ const invalidSignature = Buffer.from(account_1.INVALID_SHORT_KEYPAIR_KEY, 'hex');
454
+ assert.throws(() => utils.recoverySignature(messageHash, invalidSignature), /Failed to recover signature/);
455
+ });
456
+ it('should throw error for signature with invalid recovery parameter', function () {
457
+ const messageHash = utils.sha256(Buffer.from(account_1.SEED_ACCOUNT.message, 'utf8'));
458
+ const signature = Buffer.alloc(65); // Valid length but all zeros - invalid signature
459
+ assert.throws(() => utils.recoverySignature(messageHash, signature), /Failed to recover signature/);
460
+ });
461
+ it('should recover signature and verify sender address from signed C-chain Export tx', async function () {
462
+ // Transaction from actual build response - C-chain Export tx
463
+ const tx = '0x0000000000010000007278db5c30bed04c05ce209179812850bbb3fe6d46d7eef3744d814c0da55524790000000000000000000000000000000000000000000000000000000000000000000000012a96025ad506b9fbb9023fbdc1665c7f7d7c923f000000000605236658734f94af871c3d131b56131b6fb7a0291eacadd261e69dfb42a9cdf6f7fddd00000000000000000000000158734f94af871c3d131b56131b6fb7a0291eacadd261e69dfb42a9cdf6f7fddd000000070000000006052340000000000000000000000002000000037fa8c7e0c8ad9f09f9179b42b77e94a487c3df758d4ba538f772333ca7bf3668a2fe36648438c79d9b6b77b56effb860eaa430e0e30c4e392f59cd08000000010000000900000001750076e67d9720283a71c6e7a9a88ff662608fefdd3f316f1211957ca1873eee3ee4a74b468bda66176a3e5d3ab54d43a8c0be12348f251a3093c16d9db00cd001c31e9c15';
464
+ const expectedSenderAddress = '0x2a96025ad506b9fbb9023fbdc1665c7f7d7c923f';
465
+ const factory = new lib_1.TransactionBuilderFactory(statics_1.coins.get('tflrp'));
466
+ const txn = (await factory.from(tx).build());
467
+ const signablePayload = txn.signablePayload;
468
+ const signatures = txn.signature;
469
+ const sig = Buffer.from(utils.removeHexPrefix(signatures[0]), 'hex');
470
+ // Recover public key from signature (signablePayload is already SHA256 hashed)
471
+ const recoveredPubKey = utils.recoverySignature(signablePayload, sig);
472
+ // Get the sender address from the transaction inputs
473
+ const txInputs = txn.inputs;
474
+ const senderAddressFromTx = txInputs[0].address.toLowerCase();
475
+ // Verify sender address matches expected
476
+ assert.strictEqual(senderAddressFromTx, expectedSenderAddress.toLowerCase(), 'Transaction sender address does not match expected');
477
+ // Derive address from recovered public key
478
+ const derivedEvmAddress = '0x' + Buffer.from(new flarejs_1.Address(flarejs_1.secp256k1.publicKeyToEthAddress(recoveredPubKey)).toBytes()).toString('hex');
479
+ // Verify the recovered public key matches the sender
480
+ assert.strictEqual(derivedEvmAddress.toLowerCase(), senderAddressFromTx, 'Recovered public key does not match sender address');
481
+ // Also verify signature validity
482
+ const sigOnly = sig.slice(0, 64);
483
+ const isValid = utils.verifySignature(signablePayload, sigOnly, recoveredPubKey);
484
+ assert.strictEqual(isValid, true, 'Signature verification failed');
229
485
  });
230
486
  });
231
- describe('Memo Utilities', function () {
232
- it('should convert string to bytes', function () {
233
- const text = 'Hello Flare';
234
- const bytes = utils.stringToBytes(text);
235
- assert.ok(bytes instanceof Uint8Array);
236
- assert.strictEqual(utils.bytesToString(bytes), text);
237
- });
238
- it('should handle UTF-8 strings', function () {
239
- const text = 'Hello 世界 🌍';
240
- const bytes = utils.stringToBytes(text);
241
- assert.strictEqual(utils.bytesToString(bytes), text);
242
- });
243
- it('should create memo bytes from string', function () {
244
- const text = 'Memo text';
245
- const bytes = utils.createMemoBytes(text);
246
- assert.ok(bytes instanceof Uint8Array);
247
- assert.strictEqual(utils.parseMemoBytes(bytes), text);
248
- });
249
- it('should create memo bytes from JSON object', function () {
250
- const obj = { type: 'payment', amount: 1000 };
251
- const bytes = utils.createMemoBytes(obj);
252
- const parsed = utils.parseMemoBytes(bytes);
253
- assert.strictEqual(parsed, JSON.stringify(obj));
254
- });
255
- it('should handle Uint8Array input', function () {
256
- const originalBytes = new Uint8Array([1, 2, 3, 4]);
257
- const bytes = utils.createMemoBytes(originalBytes);
258
- assert.deepStrictEqual(bytes, originalBytes);
259
- });
260
- it('should throw error for invalid memo type', function () {
261
- assert.throws(() => {
262
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
263
- utils.createMemoBytes(123);
264
- }, /Invalid memo format/);
265
- });
266
- it('should parse empty memo', function () {
267
- const emptyBytes = new Uint8Array([]);
268
- const parsed = utils.parseMemoBytes(emptyBytes);
269
- assert.strictEqual(parsed, '');
270
- });
271
- it('should validate memo size', function () {
272
- const smallMemo = new Uint8Array([1, 2, 3]);
273
- const largeMemo = new Uint8Array(5000);
274
- assert.strictEqual(utils.validateMemoSize(smallMemo), true);
275
- assert.strictEqual(utils.validateMemoSize(largeMemo), false);
276
- assert.strictEqual(utils.validateMemoSize(largeMemo, 6000), true);
277
- });
278
- it('should handle special characters in memo', function () {
279
- const specialText = 'Special: \n\t\r\0';
280
- const bytes = utils.createMemoBytes(specialText);
281
- const parsed = utils.parseMemoBytes(bytes);
282
- assert.strictEqual(parsed, specialText);
487
+ describe('isTransactionOf', function () {
488
+ const factory = new lib_1.TransactionBuilderFactory(statics_1.coins.get('tflrp'));
489
+ const utilsInstance = new utils_1.Utils();
490
+ const testnetNetwork = statics_1.coins.get('tflrp').network;
491
+ const pChainBlockchainIdHex = Buffer.from(utilsInstance.cb58Decode(testnetNetwork.blockchainID)).toString('hex');
492
+ const cChainBlockchainIdHex = Buffer.from(utilsInstance.cb58Decode(testnetNetwork.cChainBlockchainID)).toString('hex');
493
+ it('should return true for Import in P transaction with matching P-chain blockchain ID', async function () {
494
+ const txBuilder = factory
495
+ .getImportInPBuilder()
496
+ .threshold(importInP_1.IMPORT_IN_P.threshold)
497
+ .locktime(importInP_1.IMPORT_IN_P.locktime)
498
+ .fromPubKey(importInP_1.IMPORT_IN_P.pAddresses)
499
+ .externalChainId(importInP_1.IMPORT_IN_P.sourceChainId)
500
+ .fee(importInP_1.IMPORT_IN_P.fee)
501
+ .utxos(importInP_1.IMPORT_IN_P.outputs);
502
+ const tx = (await txBuilder.build());
503
+ const flareTransaction = tx.getFlareTransaction();
504
+ assert.strictEqual(utilsInstance.isTransactionOf(flareTransaction, pChainBlockchainIdHex), true);
505
+ });
506
+ it('should return false for Import in P transaction with non-matching C-chain blockchain ID', async function () {
507
+ const txBuilder = factory
508
+ .getImportInPBuilder()
509
+ .threshold(importInP_1.IMPORT_IN_P.threshold)
510
+ .locktime(importInP_1.IMPORT_IN_P.locktime)
511
+ .fromPubKey(importInP_1.IMPORT_IN_P.pAddresses)
512
+ .externalChainId(importInP_1.IMPORT_IN_P.sourceChainId)
513
+ .fee(importInP_1.IMPORT_IN_P.fee)
514
+ .utxos(importInP_1.IMPORT_IN_P.outputs);
515
+ const tx = (await txBuilder.build());
516
+ const flareTransaction = tx.getFlareTransaction();
517
+ assert.strictEqual(utilsInstance.isTransactionOf(flareTransaction, cChainBlockchainIdHex), false);
518
+ });
519
+ it('should return true for Export in P transaction with matching P-chain blockchain ID', async function () {
520
+ const txBuilder = factory
521
+ .getExportInPBuilder()
522
+ .threshold(exportInP_1.EXPORT_IN_P.threshold)
523
+ .locktime(exportInP_1.EXPORT_IN_P.locktime)
524
+ .fromPubKey(exportInP_1.EXPORT_IN_P.pAddresses)
525
+ .externalChainId(exportInP_1.EXPORT_IN_P.sourceChainId)
526
+ .fee(exportInP_1.EXPORT_IN_P.fee)
527
+ .amount(exportInP_1.EXPORT_IN_P.amount)
528
+ .utxos(exportInP_1.EXPORT_IN_P.outputs);
529
+ const tx = (await txBuilder.build());
530
+ const flareTransaction = tx.getFlareTransaction();
531
+ assert.strictEqual(utilsInstance.isTransactionOf(flareTransaction, pChainBlockchainIdHex), true);
532
+ });
533
+ it('should return false for Export in P transaction with non-matching C-chain blockchain ID', async function () {
534
+ const txBuilder = factory
535
+ .getExportInPBuilder()
536
+ .threshold(exportInP_1.EXPORT_IN_P.threshold)
537
+ .locktime(exportInP_1.EXPORT_IN_P.locktime)
538
+ .fromPubKey(exportInP_1.EXPORT_IN_P.pAddresses)
539
+ .externalChainId(exportInP_1.EXPORT_IN_P.sourceChainId)
540
+ .fee(exportInP_1.EXPORT_IN_P.fee)
541
+ .amount(exportInP_1.EXPORT_IN_P.amount)
542
+ .utxos(exportInP_1.EXPORT_IN_P.outputs);
543
+ const tx = (await txBuilder.build());
544
+ const flareTransaction = tx.getFlareTransaction();
545
+ assert.strictEqual(utilsInstance.isTransactionOf(flareTransaction, cChainBlockchainIdHex), false);
546
+ });
547
+ it('should return true for Import in C transaction with matching C-chain blockchain ID', async function () {
548
+ const txBuilder = factory
549
+ .getImportInCBuilder()
550
+ .threshold(importInC_1.IMPORT_IN_C.threshold)
551
+ .locktime(importInC_1.IMPORT_IN_C.locktime)
552
+ .fromPubKey(importInC_1.IMPORT_IN_C.pAddresses)
553
+ .externalChainId(importInC_1.IMPORT_IN_C.sourceChainId)
554
+ .feeRate(importInC_1.IMPORT_IN_C.fee)
555
+ .to(importInC_1.IMPORT_IN_C.to)
556
+ .utxos(importInC_1.IMPORT_IN_C.outputs);
557
+ const tx = (await txBuilder.build());
558
+ const flareTransaction = tx.getFlareTransaction();
559
+ assert.strictEqual(utilsInstance.isTransactionOf(flareTransaction, cChainBlockchainIdHex), true);
560
+ });
561
+ it('should return false for Import in C transaction with non-matching P-chain blockchain ID', async function () {
562
+ const txBuilder = factory
563
+ .getImportInCBuilder()
564
+ .threshold(importInC_1.IMPORT_IN_C.threshold)
565
+ .locktime(importInC_1.IMPORT_IN_C.locktime)
566
+ .fromPubKey(importInC_1.IMPORT_IN_C.pAddresses)
567
+ .externalChainId(importInC_1.IMPORT_IN_C.sourceChainId)
568
+ .feeRate(importInC_1.IMPORT_IN_C.fee)
569
+ .to(importInC_1.IMPORT_IN_C.to)
570
+ .utxos(importInC_1.IMPORT_IN_C.outputs);
571
+ const tx = (await txBuilder.build());
572
+ const flareTransaction = tx.getFlareTransaction();
573
+ assert.strictEqual(utilsInstance.isTransactionOf(flareTransaction, pChainBlockchainIdHex), false);
574
+ });
575
+ it('should return true for Export in C transaction with matching C-chain blockchain ID', async function () {
576
+ const txBuilder = factory
577
+ .getExportInCBuilder()
578
+ .fromPubKey(exportInC_1.EXPORT_IN_C.cHexAddress)
579
+ .nonce(exportInC_1.EXPORT_IN_C.nonce)
580
+ .amount(exportInC_1.EXPORT_IN_C.amount)
581
+ .threshold(exportInC_1.EXPORT_IN_C.threshold)
582
+ .locktime(exportInC_1.EXPORT_IN_C.locktime)
583
+ .to(exportInC_1.EXPORT_IN_C.pAddresses)
584
+ .feeRate(exportInC_1.EXPORT_IN_C.fee);
585
+ const tx = (await txBuilder.build());
586
+ const flareTransaction = tx.getFlareTransaction();
587
+ assert.strictEqual(utilsInstance.isTransactionOf(flareTransaction, cChainBlockchainIdHex), true);
588
+ });
589
+ it('should return false for Export in C transaction with non-matching P-chain blockchain ID', async function () {
590
+ const txBuilder = factory
591
+ .getExportInCBuilder()
592
+ .fromPubKey(exportInC_1.EXPORT_IN_C.cHexAddress)
593
+ .nonce(exportInC_1.EXPORT_IN_C.nonce)
594
+ .amount(exportInC_1.EXPORT_IN_C.amount)
595
+ .threshold(exportInC_1.EXPORT_IN_C.threshold)
596
+ .locktime(exportInC_1.EXPORT_IN_C.locktime)
597
+ .to(exportInC_1.EXPORT_IN_C.pAddresses)
598
+ .feeRate(exportInC_1.EXPORT_IN_C.fee);
599
+ const tx = (await txBuilder.build());
600
+ const flareTransaction = tx.getFlareTransaction();
601
+ assert.strictEqual(utilsInstance.isTransactionOf(flareTransaction, pChainBlockchainIdHex), false);
602
+ });
603
+ it('should return false for invalid blockchain ID', async function () {
604
+ const txBuilder = factory
605
+ .getImportInPBuilder()
606
+ .threshold(importInP_1.IMPORT_IN_P.threshold)
607
+ .locktime(importInP_1.IMPORT_IN_P.locktime)
608
+ .fromPubKey(importInP_1.IMPORT_IN_P.pAddresses)
609
+ .externalChainId(importInP_1.IMPORT_IN_P.sourceChainId)
610
+ .fee(importInP_1.IMPORT_IN_P.fee)
611
+ .utxos(importInP_1.IMPORT_IN_P.outputs);
612
+ const tx = (await txBuilder.build());
613
+ const flareTransaction = tx.getFlareTransaction();
614
+ assert.strictEqual(utilsInstance.isTransactionOf(flareTransaction, 'invalidblockchainid'), false);
283
615
  });
284
616
  });
285
617
  });
286
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi90ZXN0L3VuaXQvbGliL3V0aWxzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsaURBQTBEO0FBQzFELG1EQUEyRDtBQUMzRCwrQ0FBaUM7QUFDakMsa0RBQStDO0FBRS9DLFFBQVEsQ0FBQyxPQUFPLEVBQUU7SUFDaEIsSUFBSSxLQUFZLENBQUM7SUFFakIsVUFBVSxDQUFDO1FBQ1QsS0FBSyxHQUFHLElBQUksYUFBSyxFQUFFLENBQUM7SUFDdEIsQ0FBQyxDQUFDLENBQUM7SUFFSCxRQUFRLENBQUMsV0FBVyxFQUFFO1FBQ3BCLEVBQUUsQ0FBQyxzRUFBc0UsRUFBRTtZQUN6RSxNQUFNLGVBQWUsR0FBRyxDQUFDLE9BQU8sRUFBRSxPQUFPLENBQUMsQ0FBQztZQUMzQyxNQUFNLGVBQWUsR0FBRyxDQUFDLE9BQU8sRUFBRSxPQUFPLEVBQUUsT0FBTyxDQUFDLENBQUM7WUFFcEQsTUFBTSxDQUFDLFdBQVcsQ0FBQyxLQUFLLENBQUMsU0FBUyxDQUFDLGVBQWUsRUFBRSxlQUFlLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQztRQUM5RSxDQUFDLENBQUMsQ0FBQztRQUVILEVBQUUsQ0FBQywyRUFBMkUsRUFBRTtZQUM5RSxNQUFNLGVBQWUsR0FBRyxDQUFDLE9BQU8sRUFBRSxPQUFPLENBQUMsQ0FBQztZQUMzQyxNQUFNLGVBQWUsR0FBRyxDQUFDLE9BQU8sRUFBRSxPQUFPLENBQUMsQ0FBQztZQUUzQyxNQUFNLENBQUMsV0FBVyxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUMsZUFBZSxFQUFFLGVBQWUsQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDO1FBQy9FLENBQUMsQ0FBQyxDQUFDO1FBRUgsRUFBRSxDQUFDLCtDQUErQyxFQUFFO1lBQ2xELE1BQU0sZUFBZSxHQUFhLEVBQUUsQ0FBQztZQUNyQyxNQUFN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QyxDQUFDO1lBQ2pELE1BQU0sTUFBTSxHQUFHLEtBQUssQ0FBQyxjQUFjLENBQUMsS0FBSyxDQUFDLENBQUM7WUFFM0MsTUFBTSxDQUFDLFdBQVcsQ0FBQyxNQUFNLEVBQUUsV0FBVyxDQUFDLENBQUM7UUFDMUMsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztBQUNMLENBQUMsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgY29pbnMsIEZsYXJlTmV0d29yayB9IGZyb20gJ0BiaXRnby1iZXRhL3N0YXRpY3MnO1xuaW1wb3J0IHsgTm90SW1wbGVtZW50ZWRFcnJvciB9IGZyb20gJ0BiaXRnby1iZXRhL3Nkay1jb3JlJztcbmltcG9ydCAqIGFzIGFzc2VydCBmcm9tICdhc3NlcnQnO1xuaW1wb3J0IHsgVXRpbHMgfSBmcm9tICcuLi8uLi8uLi9zcmMvbGliL3V0aWxzJztcblxuZGVzY3JpYmUoJ1V0aWxzJywgZnVuY3Rpb24gKCkge1xuICBsZXQgdXRpbHM6IFV0aWxzO1xuXG4gIGJlZm9yZUVhY2goZnVuY3Rpb24gKCkge1xuICAgIHV0aWxzID0gbmV3IFV0aWxzKCk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdpbmNsdWRlSW4nLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ3Nob3VsZCByZXR1cm4gdHJ1ZSB3aGVuIGFsbCB3YWxsZXQgYWRkcmVzc2VzIGFyZSBpbiBvdXRwdXQgYWRkcmVzc2VzJywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgd2FsbGV0QWRkcmVzc2VzID0gWydhZGRyMScsICdhZGRyMiddO1xuICAgICAgY29uc3Qgb3V0cHV0QWRkcmVzc2VzID0gWydhZGRyMScsICdhZGRyMicsICdhZGRyMyddO1xuXG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwodXRpbHMuaW5jbHVkZUluKHdhbGxldEFkZHJlc3Nlcywgb3V0cHV0QWRkcmVzc2VzKSwgdHJ1ZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJldHVybiBmYWxzZSB3aGVuIG5vdCBhbGwgd2FsbGV0IGFkZHJlc3NlcyBhcmUgaW4gb3V0cHV0IGFkZHJlc3NlcycsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHdhbGxldEFkZHJlc3NlcyA9IFsnYWRkcjEnLCAnYWRkcjInXTtcbiAgICAgIGNvbnN0IG91dHB1dEFkZHJlc3NlcyA9IFsnYWRkcjEnLCAnYWRkcjMnXTtcblxuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHV0aWxzLmluY2x1ZGVJbih3YWxsZXRBZGRyZXNzZXMsIG91dHB1dEFkZHJlc3NlcyksIGZhbHNlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmV0dXJuIHRydWUgZm9yIGVtcHR5IHdhbGxldCBhZGRyZXNzZXMnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB3YWxsZXRBZGRyZXNzZXM6IHN0cmluZ1tdID0gW107XG4gICAgICBjb25zdCBvdXRwdXRBZGRyZXNzZXMgPSBbJ2FkZHIxJywgJ2FkZHIyJ107XG5cbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCh1dGlscy5pbmNsdWRlSW4od2FsbGV0QWRkcmVzc2VzLCBvdXRwdXRBZGRyZXNzZXMpLCB0cnVlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmV0dXJuIGZhbHNlIHdoZW4gd2FsbGV0IGFkZHJlc3Mgbm90IGZvdW5kIGluIGVtcHR5IG91dHB1dCBhZGRyZXNzZXMnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB3YWxsZXRBZGRyZXNzZXMgPSBbJ2FkZHIxJ107XG4gICAgICBjb25zdCBvdXRwdXRBZGRyZXNzZXM6IHN0cmluZ1tdID0gW107XG5cbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCh1dGlscy5pbmNsdWRlSW4od2FsbGV0QWRkcmVzc2VzLCBvdXRwdXRBZGRyZXNzZXMpLCBmYWxzZSk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdpc1ZhbGlkQWRkcmVzcycsIGZ1bmN0aW9uICgpIHtcbiAgICBpdCgnc2hvdWxkIHZhbGlkYXRlIHNpbmdsZSB2YWxpZCBGbGFyZSBhZGRyZXNzZXMnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAvLyBGbGFyZSBhZGRyZXNzZXMgc3RhcnQgd2l0aCAnZmxhcmU6JyBvciAnQy1mbGFyZTonXG4gICAgICBjb25zdCB2YWxpZEFkZHJlc3NlcyA9IFtcbiAgICAgICAgJ2ZsYXJlMXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXE2ZjRhdmgnLFxuICAgICAgICAnQy1mbGFyZTFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxNmY0YXZoJyxcbiAgICAgIF07XG5cbiAgICAgIHZhbGlkQWRkcmVzc2VzLmZvckVhY2goKGFkZHIpID0+IHtcbiAgICAgICAgLy8gTm90ZTogVGhlIGN1cnJlbnQgaW1wbGVtZW50YXRpb24gdXNlcyByZWdleCB2YWxpZGF0aW9uXG4gICAgICAgIC8vIFRoaXMgdGVzdCB3aWxsIGJlIHVwZGF0ZWQgb25jZSBwcm9wZXIgRmxhcmUgYWRkcmVzcyB2YWxpZGF0aW9uIGlzIGltcGxlbWVudGVkXG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IHV0aWxzLmlzVmFsaWRBZGRyZXNzKGFkZHIpO1xuICAgICAgICAvLyBDdXJyZW50bHkgcmV0dXJucyBmYWxzZSBkdWUgdG8gcGxhY2Vob2xkZXIgaW1wbGVtZW50YXRpb25cbiAgICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHR5cGVvZiByZXN1bHQsICdib29sZWFuJyk7XG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdmFsaWRhdGUgYXJyYXkgb2YgYWRkcmVzc2VzJywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgYWRkcmVzc2VzID0gW1xuICAgICAgICAnZmxhcmUxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcTZmNGF2aCcsXG4gICAgICAgICdmbGFyZTFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYTZmNGF2aCcsXG4gICAgICBdO1xuXG4gICAgICBjb25zdCByZXN1bHQgPSB1dGlscy5pc1ZhbGlkQWRkcmVzcyhhZGRyZXNzZXMpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHR5cGVvZiByZXN1bHQsICdib29sZWFuJyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHZhbGlkYXRlIGFkZHJlc3NlcyBzZXBhcmF0ZWQgYnkgficsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGFkZHJlc3NTdHJpbmcgPVxuICAgICAgICAnZmxhcmUxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcTZmNGF2aH5mbGFyZTFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYTZmNGF2aCc7XG5cbiAgICAgIGNvbnN0IHJlc3VsdCA9IHV0aWxzLmlzVmFsaWRBZGRyZXNzKGFkZHJlc3NTdHJpbmcpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHR5cGVvZiByZXN1bHQsICdib29sZWFuJyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJlamVjdCBvYnZpb3VzbHkgaW52YWxpZCBhZGRyZXNzZXMnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBpbnZhbGlkQWRkcmVzc2VzID0gW1xuICAgICAgICAnJyxcbiAgICAgICAgJ2ludmFsaWQnLFxuICAgICAgICAnMTIzJyxcbiAgICAgICAgJ2JpdGNvaW4xcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcScsXG4gICAgICAgICdldGg6MHgxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwJyxcbiAgICAgIF07XG5cbiAgICAgIGludmFsaWRBZGRyZXNzZXMuZm9yRWFjaCgoYWRkcikgPT4ge1xuICAgICAgICBjb25zdCByZXN1bHQgPSB1dGlscy5pc1ZhbGlkQWRkcmVzcyhhZGRyKTtcbiAgICAgICAgLy8gQ3VycmVudCBpbXBsZW1lbnRhdGlvbiBtYXkgbm90IGNhdGNoIGFsbCBpbnZhbGlkIGFkZHJlc3Nlc1xuICAgICAgICBhc3NlcnQuc3RyaWN0RXF1YWwodHlwZW9mIHJlc3VsdCwgJ2Jvb2xlYW4nKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnaXNWYWxpZEFkZHJlc3NSZWdleCcsIGZ1bmN0aW9uICgpIHtcbiAgICBpdCgnc2hvdWxkIHRlc3QgYWRkcmVzcyBmb3JtYXQgd2l0aCByZWdleCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHRlc3RBZGRyZXNzID0gJ2ZsYXJlMXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXE2ZjRhdmgnO1xuICAgICAgY29uc3QgcmVzdWx0ID0gdXRpbHNbJ2lzVmFsaWRBZGRyZXNzUmVnZXgnXSh0ZXN0QWRkcmVzcyk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwodHlwZW9mIHJlc3VsdCwgJ2Jvb2xlYW4nKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmVqZWN0IGVtcHR5IHN0cmluZ3MnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCByZXN1bHQgPSB1dGlsc1snaXNWYWxpZEFkZHJlc3NSZWdleCddKCcnKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChyZXN1bHQsIGZhbHNlKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ2lzVmFsaWRUcmFuc2FjdGlvbklkJywgZnVuY3Rpb24gKCkge1xuICAgIGl0KCdzaG91bGQgdGhyb3cgTm90SW1wbGVtZW50ZWRFcnJvcicsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGFzc2VydC50aHJvd3MoXG4gICAgICAgICgpID0+IHV0aWxzLmlzVmFsaWRUcmFuc2FjdGlvbklkKCd0eGlkMTIzJyksXG4gICAgICAgIE5vdEltcGxlbWVudGVkRXJyb3IsXG4gICAgICAgICdpc1ZhbGlkVHJhbnNhY3Rpb25JZCBub3QgaW1wbGVtZW50ZWQnXG4gICAgICApO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnaXNWYWxpZFNpZ25hdHVyZScsIGZ1bmN0aW9uICgpIHtcbiAgICBpdCgnc2hvdWxkIHRocm93IE5vdEltcGxlbWVudGVkRXJyb3InLCBmdW5jdGlvbiAoKSB7XG4gICAgICBhc3NlcnQudGhyb3dzKFxuICAgICAgICAoKSA9PiB1dGlscy5pc1ZhbGlkU2lnbmF0dXJlKCdzaWduYXR1cmUxMjMnKSxcbiAgICAgICAgTm90SW1wbGVtZW50ZWRFcnJvcixcbiAgICAgICAgJ2lzVmFsaWRTaWduYXR1cmUgbm90IGltcGxlbWVudGVkJ1xuICAgICAgKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ2NyZWF0ZVNpZ25hdHVyZScsIGZ1bmN0aW9uICgpIHtcbiAgICBpdCgnc2hvdWxkIGNyZWF0ZSBzaWduYXR1cmUgdXNpbmcgc2VjcDI1NmsxJywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgbmV0d29yayA9IGNvaW5zLmdldCgnZmxycCcpLm5ldHdvcmsgYXMgRmxhcmVOZXR3b3JrO1xuICAgICAgY29uc3QgbWVzc2FnZSA9IEJ1ZmZlci5mcm9tKCdoZWxsbyB3b3JsZCcsICd1dGY4Jyk7XG4gICAgICBjb25zdCBwcml2YXRlS2V5ID0gQnVmZmVyLmZyb20oJzAxMjM0NTY3ODlhYmNkZWYwMTIzNDU2Nzg5YWJjZGVmMDEyMzQ1Njc4OWFiY2RlZjAxMjM0NTY3ODlhYmNkZWYnLCAnaGV4Jyk7XG5cbiAgICAgIGNvbnN0IHNpZ25hdHVyZSA9IHV0aWxzLmNyZWF0ZVNpZ25hdHVyZShuZXR3b3JrLCBtZXNzYWdlLCBwcml2YXRlS2V5KTtcblxuICAgICAgYXNzZXJ0Lm9rKHNpZ25hdHVyZSBpbnN0YW5jZW9mIEJ1ZmZlcik7XG4gICAgICBhc3NlcnQub2soc2lnbmF0dXJlLmxlbmd0aCA+IDApO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBjcmVhdGUgZGlmZmVyZW50IHNpZ25hdHVyZXMgZm9yIGRpZmZlcmVudCBtZXNzYWdlcycsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IG5ldHdvcmsgPSBjb2lucy5nZXQoJ2ZscnAnKS5uZXR3b3JrIGFzIEZsYXJlTmV0d29yaztcbiAgICAgIGNvbnN0IG1lc3NhZ2UxID0gQnVmZmVyLmZyb20oJ21lc3NhZ2UgMScsICd1dGY4Jyk7XG4gICAgICBjb25zdCBtZXNzYWdlMiA9IEJ1ZmZlci5mcm9tKCdtZXNzYWdlIDInLCAndXRmOCcpO1xuICAgICAgY29uc3QgcHJpdmF0ZUtleSA9IEJ1ZmZlci5mcm9tKCcwMTIzNDU2Nzg5YWJjZGVmMDEyMzQ1Njc4OWFiY2RlZjAxMjM0NTY3ODlhYmNkZWYwMTIzNDU2Nzg5YWJjZGVmJywgJ2hleCcpO1xuXG4gICAgICBjb25zdCBzaWcxID0gdXRpbHMuY3JlYXRlU2lnbmF0dXJlKG5ldHdvcmssIG1lc3NhZ2UxLCBwcml2YXRlS2V5KTtcbiAgICAgIGNvbnN0IHNpZzIgPSB1dGlscy5jcmVhdGVTaWduYXR1cmUobmV0d29yaywgbWVzc2FnZTIsIHByaXZhdGVLZXkpO1xuXG4gICAgICBhc3NlcnQubm90RGVlcFN0cmljdEVxdWFsKHNpZzEsIHNpZzIpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0aHJvdyBlcnJvciBmb3IgaW52YWxpZCBwcml2YXRlIGtleScsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IG5ldHdvcmsgPSBjb2lucy5nZXQoJ2ZscnAnKS5uZXR3b3JrIGFzIEZsYXJlTmV0d29yaztcbiAgICAgIGNvbnN0IG1lc3NhZ2UgPSBCdWZmZXIuZnJvbSgnaGVsbG8gd29ybGQnLCAndXRmOCcpO1xuICAgICAgY29uc3QgaW52YWxpZFByaXZhdGVLZXkgPSBCdWZmZXIuZnJvbSgnaW52YWxpZCcsICd1dGY4Jyk7XG5cbiAgICAgIGFzc2VydC50aHJvd3MoKCkgPT4gdXRpbHMuY3JlYXRlU2lnbmF0dXJlKG5ldHdvcmssIG1lc3NhZ2UsIGludmFsaWRQcml2YXRlS2V5KSwgL0ZhaWxlZCB0byBjcmVhdGUgc2lnbmF0dXJlLyk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCd2ZXJpZnlTaWduYXR1cmUnLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ3Nob3VsZCB2ZXJpZnkgdmFsaWQgc2lnbmF0dXJlJywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgbmV0d29yayA9IGNvaW5zLmdldCgnZmxycCcpLm5ldHdvcmsgYXMgRmxhcmVOZXR3b3JrO1xuICAgICAgY29uc3QgbWVzc2FnZSA9IEJ1ZmZlci5mcm9tKCdoZWxsbyB3b3JsZCcsICd1dGY4Jyk7XG4gICAgICBjb25zdCBwcml2YXRlS2V5ID0gQnVmZmVyLmZyb20oJzAxMjM0NTY3ODlhYmNkZWYwMTIzNDU2Nzg5YWJjZGVmMDEyMzQ1Njc4OWFiY2RlZjAxMjM0NTY3ODlhYmNkZWYnLCAnaGV4Jyk7XG5cbiAgICAgIC8vIENyZWF0ZSBzaWduYXR1cmVcbiAgICAgIGNvbnN0IHNpZ25hdHVyZSA9IHV0aWxzLmNyZWF0ZVNpZ25hdHVyZShuZXR3b3JrLCBtZXNzYWdlLCBwcml2YXRlS2V5KTtcblxuICAgICAgLy8gR2V0IHB1YmxpYyBrZXkgKHRoaXMgd291bGQgbm9ybWFsbHkgY29tZSBmcm9tIHRoZSBwcml2YXRlIGtleSlcbiAgICAgIC8vIEZvciB0ZXN0aW5nLCB3ZSdsbCB1c2UgYSBtb2NrIHB1YmxpYyBrZXkgYXBwcm9hY2hcbiAgICAgIGNvbnN0IHB1YmxpY0tleSA9IEJ1ZmZlci5mcm9tKCcwMicgKyAnMCcucmVwZWF0KDYyKSwgJ2hleCcpOyAvLyBDb21wcmVzc2VkIHB1YmxpYyBrZXkgZm9ybWF0XG5cbiAgICAgIC8vIE5vdGU6IFRoaXMgdGVzdCBtYXkgZmFpbCBpZiB0aGUgcHVibGljIGtleSBkb2Vzbid0IG1hdGNoIHRoZSBwcml2YXRlIGtleVxuICAgICAgLy8gSW4gYSByZWFsIGltcGxlbWVudGF0aW9uLCB5b3UnZCBkZXJpdmUgdGhlIHB1YmxpYyBrZXkgZnJvbSB0aGUgcHJpdmF0ZSBrZXlcbiAgICAgIC8vIFRoZSBtZXRob2QgcmV0dXJucyBmYWxzZSB3aGVuIHZlcmlmaWNhdGlvbiBmYWlscyBpbnN0ZWFkIG9mIHRocm93aW5nXG4gICAgICBjb25zdCBpc1ZhbGlkID0gdXRpbHMudmVyaWZ5U2lnbmF0dXJlKG5ldHdvcmssIG1lc3NhZ2UsIHNpZ25hdHVyZSwgcHVibGljS2V5KTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCh0eXBlb2YgaXNWYWxpZCwgJ2Jvb2xlYW4nKTtcbiAgICAgIC8vIFdpdGggbW9jayBwdWJsaWMga2V5LCB0aGlzIHNob3VsZCByZXR1cm4gZmFsc2VcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChpc1ZhbGlkLCBmYWxzZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJldHVybiBmYWxzZSBmb3IgaW52YWxpZCBzaWduYXR1cmUnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBuZXR3b3JrID0gY29pbnMuZ2V0KCdmbHJwJykubmV0d29yayBhcyBGbGFyZU5ldHdvcms7XG4gICAgICBjb25zdCBtZXNzYWdlID0gQnVmZmVyLmZyb20oJ2hlbGxvIHdvcmxkJywgJ3V0ZjgnKTtcbiAgICAgIGNvbnN0IGludmFsaWRTaWduYXR1cmUgPSBCdWZmZXIuZnJvbSgnaW52YWxpZCBzaWduYXR1cmUnLCAndXRmOCcpO1xuICAgICAgY29uc3QgcHVibGljS2V5ID0gQnVmZmVyLmZyb20oJzAyJyArICcwJy5yZXBlYXQoNjIpLCAnaGV4Jyk7XG5cbiAgICAgIC8vIFRoaXMgc2hvdWxkIHJldHVybiBmYWxzZSBkdWUgdG8gaW52YWxpZCBzaWduYXR1cmUgZm9ybWF0XG4gICAgICAvLyBUaGUgbWV0aG9kIGNhdGNoZXMgZXJyb3JzIGludGVybmFsbHkgYW5kIHJldHVybnMgZmFsc2VcbiAgICAgIGNvbnN0IHJlc3VsdCA9IHV0aWxzLnZlcmlmeVNpZ25hdHVyZShuZXR3b3JrLCBtZXNzYWdlLCBpbnZhbGlkU2lnbmF0dXJlLCBwdWJsaWNLZXkpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHJlc3VsdCwgZmFsc2UpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnYWRkcmVzcyBwYXJzaW5nIHV0aWxpdGllcycsIGZ1bmN0aW9uICgpIHtcbiAgICBpdCgnc2hvdWxkIGhhbmRsZSBhZGRyZXNzIHNlcGFyYXRvciBjb25zdGFudHMnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB7IEFERFJFU1NfU0VQQVJBVE9SIH0gPSByZXF1aXJlKCcuLi8uLi8uLi9zcmMvbGliL2lmYWNlJyk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoQUREUkVTU19TRVBBUkFUT1IsICd+Jyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGhhbmRsZSBpbnB1dCBzZXBhcmF0b3IgY29uc3RhbnRzJywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgeyBJTlBVVF9TRVBBUkFUT1IgfSA9IHJlcXVpcmUoJy4uLy4uLy4uL3NyYy9saWIvaWZhY2UnKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChJTlBVVF9TRVBBUkFUT1IsICc6Jyk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdlcnJvciBoYW5kbGluZycsIGZ1bmN0aW9uICgpIHtcbiAgICBpdCgnc2hvdWxkIHByb3Blcmx5IGV4dGVuZCBiYXNlIHV0aWxzJywgZnVuY3Rpb24gKCkge1xuICAgICAgLy8gVGVzdCB0aGF0IHV0aWxzIGNsYXNzIGV4aXN0cyBhbmQgaGFzIGV4cGVjdGVkIG1ldGhvZHNcbiAgICAgIGFzc2VydC5vaygnaXNWYWxpZEFkZHJlc3MnIGluIHV0aWxzKTtcbiAgICAgIGFzc2VydC5vaygnaW5jbHVkZUluJyBpbiB1dGlscyk7XG4gICAgICBhc3NlcnQub2soJ2NyZWF0ZVNpZ25hdHVyZScgaW4gdXRpbHMpO1xuICAgICAgYXNzZXJ0Lm9rKCd2ZXJpZnlTaWduYXR1cmUnIGluIHV0aWxzKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgaGFuZGxlIHBhcnNpbmcgZXJyb3JzIGdyYWNlZnVsbHknLCBmdW5jdGlvbiAoKSB7XG4gICAgICAvLyBUZXN0IHRoYXQgdXRpbHMgY2FuIGhhbmRsZSBtYWxmb3JtZWQgaW5wdXQgd2l0aG91dCBjcmFzaGluZ1xuICAgICAgLy8gTm90ZTogVGhlc2UgbWF5IHRocm93IGVycm9ycywgd2hpY2ggaXMgYWNjZXB0YWJsZSBiZWhhdmlvclxuICAgICAgdHJ5IHtcbiAgICAgICAgdXRpbHMuaXNWYWxpZEFkZHJlc3MobnVsbCBhcyB1bmtub3duIGFzIHN0cmluZyk7XG4gICAgICAgIHV0aWxzLmlzVmFsaWRBZGRyZXNzKHVuZGVmaW5lZCBhcyB1bmtub3duIGFzIHN0cmluZyk7XG4gICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAvLyBFeHBlY3RlZCBiZWhhdmlvciAtIHV0aWxzIHNob3VsZCBoYW5kbGUgb3IgdGhyb3cgbWVhbmluZ2Z1bCBlcnJvcnNcbiAgICAgICAgYXNzZXJ0Lm9rKGVycm9yIGluc3RhbmNlb2YgRXJyb3IpO1xuICAgICAgfVxuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnY29uc3RhbnRzIHZhbGlkYXRpb24nLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ3Nob3VsZCBoYXZlIGNvcnJlY3QgY29uc3RhbnQgdmFsdWVzJywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgY29uc3RhbnRzID0gcmVxdWlyZSgnLi4vLi4vLi4vc3JjL2xpYi9jb25zdGFudHMnKTtcblxuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHR5cGVvZiBjb25zdGFudHMuREVDT0RFRF9CTE9DS19JRF9MRU5HVEgsICdudW1iZXInKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCh0eXBlb2YgY29uc3RhbnRzLlNIT1JUX1BVQl9LRVlfTEVOR1RILCAnbnVtYmVyJyk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwodHlwZW9mIGNvbnN0YW50cy5DT01QUkVTU0VEX1BVQkxJQ19LRVlfTEVOR1RILCAnbnVtYmVyJyk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwodHlwZW9mIGNvbnN0YW50cy5VTkNPTVBSRVNTRURfUFVCTElDX0tFWV9MRU5HVEgsICdudW1iZXInKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCh0eXBlb2YgY29uc3RhbnRzLlJBV19QUklWQVRFX0tFWV9MRU5HVEgsICdudW1iZXInKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCh0eXBlb2YgY29uc3RhbnRzLlNVRkZJWEVEX1BSSVZBVEVfS0VZX0xFTkdUSCwgJ251bWJlcicpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHR5cGVvZiBjb25zdGFudHMuUFJJVkFURV9LRVlfQ09NUFJFU1NFRF9TVUZGSVgsICdzdHJpbmcnKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCh0eXBlb2YgY29uc3RhbnRzLk9VVFBVVF9JTkRFWF9IRVhfTEVOR1RILCAnbnVtYmVyJyk7XG4gICAgICBhc3NlcnQub2soY29uc3RhbnRzLkFERFJFU1NfUkVHRVggaW5zdGFuY2VvZiBSZWdFeHApO1xuICAgICAgYXNzZXJ0Lm9rKGNvbnN0YW50cy5IRVhfUkVHRVggaW5zdGFuY2VvZiBSZWdFeHApO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnTWVtbyBVdGlsaXRpZXMnLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ3Nob3VsZCBjb252ZXJ0IHN0cmluZyB0byBieXRlcycsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHRleHQgPSAnSGVsbG8gRmxhcmUnO1xuICAgICAgY29uc3QgYnl0ZXMgPSB1dGlscy5zdHJpbmdUb0J5dGVzKHRleHQpO1xuXG4gICAgICBhc3NlcnQub2soYnl0ZXMgaW5zdGFuY2VvZiBVaW50OEFycmF5KTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCh1dGlscy5ieXRlc1RvU3RyaW5nKGJ5dGVzKSwgdGV4dCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGhhbmRsZSBVVEYtOCBzdHJpbmdzJywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgdGV4dCA9ICdIZWxsbyDkuJbnlYwg8J+MjSc7XG4gICAgICBjb25zdCBieXRlcyA9IHV0aWxzLnN0cmluZ1RvQnl0ZXModGV4dCk7XG5cbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCh1dGlscy5ieXRlc1RvU3RyaW5nKGJ5dGVzKSwgdGV4dCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGNyZWF0ZSBtZW1vIGJ5dGVzIGZyb20gc3RyaW5nJywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgdGV4dCA9ICdNZW1vIHRleHQnO1xuICAgICAgY29uc3QgYnl0ZXMgPSB1dGlscy5jcmVhdGVNZW1vQnl0ZXModGV4dCk7XG5cbiAgICAgIGFzc2VydC5vayhieXRlcyBpbnN0YW5jZW9mIFVpbnQ4QXJyYXkpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHV0aWxzLnBhcnNlTWVtb0J5dGVzKGJ5dGVzKSwgdGV4dCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGNyZWF0ZSBtZW1vIGJ5dGVzIGZyb20gSlNPTiBvYmplY3QnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBvYmogPSB7IHR5cGU6ICdwYXltZW50JywgYW1vdW50OiAxMDAwIH07XG4gICAgICBjb25zdCBieXRlcyA9IHV0aWxzLmNyZWF0ZU1lbW9CeXRlcyhvYmopO1xuICAgICAgY29uc3QgcGFyc2VkID0gdXRpbHMucGFyc2VNZW1vQnl0ZXMoYnl0ZXMpO1xuXG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwocGFyc2VkLCBKU09OLnN0cmluZ2lmeShvYmopKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgaGFuZGxlIFVpbnQ4QXJyYXkgaW5wdXQnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBvcmlnaW5hbEJ5dGVzID0gbmV3IFVpbnQ4QXJyYXkoWzEsIDIsIDMsIDRdKTtcbiAgICAgIGNvbnN0IGJ5dGVzID0gdXRpbHMuY3JlYXRlTWVtb0J5dGVzKG9yaWdpbmFsQnl0ZXMpO1xuXG4gICAgICBhc3NlcnQuZGVlcFN0cmljdEVxdWFsKGJ5dGVzLCBvcmlnaW5hbEJ5dGVzKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdGhyb3cgZXJyb3IgZm9yIGludmFsaWQgbWVtbyB0eXBlJywgZnVuY3Rpb24gKCkge1xuICAgICAgYXNzZXJ0LnRocm93cygoKSA9PiB7XG4gICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZXhwbGljaXQtYW55XG4gICAgICAgIHV0aWxzLmNyZWF0ZU1lbW9CeXRlcygxMjMgYXMgYW55KTtcbiAgICAgIH0sIC9JbnZhbGlkIG1lbW8gZm9ybWF0Lyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHBhcnNlIGVtcHR5IG1lbW8nLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBlbXB0eUJ5dGVzID0gbmV3IFVpbnQ4QXJyYXkoW10pO1xuICAgICAgY29uc3QgcGFyc2VkID0gdXRpbHMucGFyc2VNZW1vQnl0ZXMoZW1wdHlCeXRlcyk7XG5cbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChwYXJzZWQsICcnKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdmFsaWRhdGUgbWVtbyBzaXplJywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgc21hbGxNZW1vID0gbmV3IFVpbnQ4QXJyYXkoWzEsIDIsIDNdKTtcbiAgICAgIGNvbnN0IGxhcmdlTWVtbyA9IG5ldyBVaW50OEFycmF5KDUwMDApO1xuXG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwodXRpbHMudmFsaWRhdGVNZW1vU2l6ZShzbWFsbE1lbW8pLCB0cnVlKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCh1dGlscy52YWxpZGF0ZU1lbW9TaXplKGxhcmdlTWVtbyksIGZhbHNlKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCh1dGlscy52YWxpZGF0ZU1lbW9TaXplKGxhcmdlTWVtbywgNjAwMCksIHRydWUpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBoYW5kbGUgc3BlY2lhbCBjaGFyYWN0ZXJzIGluIG1lbW8nLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBzcGVjaWFsVGV4dCA9ICdTcGVjaWFsOiBcXG5cXHRcXHJcXDAnO1xuICAgICAgY29uc3QgYnl0ZXMgPSB1dGlscy5jcmVhdGVNZW1vQnl0ZXMoc3BlY2lhbFRleHQpO1xuICAgICAgY29uc3QgcGFyc2VkID0gdXRpbHMucGFyc2VNZW1vQnl0ZXMoYnl0ZXMpO1xuXG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwocGFyc2VkLCBzcGVjaWFsVGV4dCk7XG4gICAgfSk7XG4gIH0pO1xufSk7XG4iXX0=
618
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi90ZXN0L3VuaXQvbGliL3V0aWxzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsaURBQTBEO0FBQzFELCtDQUFpQztBQUNqQyxrREFBK0M7QUFDL0MscURBT2lDO0FBQ2pDLHFEQUE0QztBQUM1Qyx5RUFBd0U7QUFDeEUseUVBQXdFO0FBQ3hFLHlFQUF3RTtBQUN4RSx5RUFBd0U7QUFDeEUsMENBQTBFO0FBQzFFLG1EQUEyRDtBQUUzRCxRQUFRLENBQUMsT0FBTyxFQUFFO0lBQ2hCLElBQUksS0FBWSxDQUFDO0lBQ2pCLE1BQU0sT0FBTyxHQUFHLGVBQUssQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUMsT0FBdUIsQ0FBQztJQUUxRCxVQUFVLENBQUM7UUFDVCxLQUFLLEdBQUcsSUFBSSxhQUFLLEVBQUUsQ0FBQztJQUN0QixDQUFDLENBQUMsQ0FBQztJQUVILFFBQVEsQ0FBQyxXQUFXLEVBQUU7UUFDcEIsRUFBRSxDQUFDLDJFQUEyRSxFQUFFO1lBQzlFLE1BQU0sZUFBZSxHQUFHLENBQUMsdUJBQVcsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLEVBQUUsdUJBQVcsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUMvRSxNQUFNLG1CQUFtQixHQUFHLENBQUMsR0FBRyx1QkFBVyxDQUFDLFVBQVUsQ0FBQyxDQUFDO1lBQ3hELE1BQU0sQ0FBQyxXQUFXLENBQUMsS0FBSyxDQUFDLFNBQVMsQ0FBQyxlQUFlLEVBQUUsbUJBQW1CLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQztRQUNsRixDQUFDLENBQUMsQ0FBQztRQUVILEVBQUUsQ0FBQyxpRkFBaUYsRUFBRTtZQUNwRixNQUFNLGVBQWUsR0FBRyxDQUFDLHVCQUFXLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxFQUFFLG1CQUFT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QUFHLEVBQUUsQ0FBQyxtQkFBbUIsRUFBRSxDQUFDO1lBRWxELE1BQU0sQ0FBQyxXQUFXLENBQUMsYUFBYSxDQUFDLGVBQWUsQ0FBQyxnQkFBZ0IsRUFBRSxxQkFBcUIsQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDO1FBQ3BHLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGNvaW5zLCBGbGFyZU5ldHdvcmsgfSBmcm9tICdAYml0Z28tYmV0YS9zdGF0aWNzJztcbmltcG9ydCAqIGFzIGFzc2VydCBmcm9tICdhc3NlcnQnO1xuaW1wb3J0IHsgVXRpbHMgfSBmcm9tICcuLi8uLi8uLi9zcmMvbGliL3V0aWxzJztcbmltcG9ydCB7XG4gIFNFRURfQUNDT1VOVCxcbiAgQUNDT1VOVF8xLFxuICBBQ0NPVU5UXzIsXG4gIEFDQ09VTlRfMyxcbiAgSU5WQUxJRF9TSE9SVF9LRVlQQUlSX0tFWSxcbiAgSU5WQUxJRF9MT05HX0tFWVBBSVJfUFJWLFxufSBmcm9tICcuLi8uLi9yZXNvdXJjZXMvYWNjb3VudCc7XG5pbXBvcnQgeyBlY2MgfSBmcm9tICdAYml0Z28tYmV0YS9zZWNwMjU2azEnO1xuaW1wb3J0IHsgRVhQT1JUX0lOX0MgfSBmcm9tICcuLi8uLi9yZXNvdXJjZXMvdHJhbnNhY3Rpb25EYXRhL2V4cG9ydEluQyc7XG5pbXBvcnQgeyBJTVBPUlRfSU5fUCB9IGZyb20gJy4uLy4uL3Jlc291cmNlcy90cmFuc2FjdGlvbkRhdGEvaW1wb3J0SW5QJztcbmltcG9ydCB7IEVYUE9SVF9JTl9QIH0gZnJvbSAnLi4vLi4vcmVzb3VyY2VzL3RyYW5zYWN0aW9uRGF0YS9leHBvcnRJblAnO1xuaW1wb3J0IHsgSU1QT1JUX0lOX0MgfSBmcm9tICcuLi8uLi9yZXNvdXJjZXMvdHJhbnNhY3Rpb25EYXRhL2ltcG9ydEluQyc7XG5pbXBvcnQgeyBUcmFuc2FjdGlvbkJ1aWxkZXJGYWN0b3J5LCBUcmFuc2FjdGlvbiB9IGZyb20gJy4uLy4uLy4uL3NyYy9saWInO1xuaW1wb3J0IHsgc2VjcDI1NmsxLCBBZGRyZXNzIH0gZnJvbSAnQGZsYXJlbmV0d29yay9mbGFyZWpzJztcblxuZGVzY3JpYmUoJ1V0aWxzJywgZnVuY3Rpb24gKCkge1xuICBsZXQgdXRpbHM6IFV0aWxzO1xuICBjb25zdCBuZXR3b3JrID0gY29pbnMuZ2V0KCdmbHJwJykubmV0d29yayBhcyBGbGFyZU5ldHdvcms7XG5cbiAgYmVmb3JlRWFjaChmdW5jdGlvbiAoKSB7XG4gICAgdXRpbHMgPSBuZXcgVXRpbHMoKTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ2luY2x1ZGVJbicsIGZ1bmN0aW9uICgpIHtcbiAgICBpdCgnc2hvdWxkIHJldHVybiB0cnVlIHdoZW4gYWxsIHdhbGxldCBhZGRyZXNzZXMgYXJlIGluIFVUWE8gb3V0cHV0IGFkZHJlc3NlcycsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHdhbGxldEFkZHJlc3NlcyA9IFtFWFBPUlRfSU5fQy5wQWRkcmVzc2VzWzBdLCBFWFBPUlRfSU5fQy5wQWRkcmVzc2VzWzFdXTtcbiAgICAgIGNvbnN0IHV0eG9PdXRwdXRBZGRyZXNzZXMgPSBbLi4uRVhQT1JUX0lOX0MucEFkZHJlc3Nlc107XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwodXRpbHMuaW5jbHVkZUluKHdhbGxldEFkZHJlc3NlcywgdXR4b091dHB1dEFkZHJlc3NlcyksIHRydWUpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCByZXR1cm4gZmFsc2Ugd2hlbiBzb21lIHdhbGxldCBhZGRyZXNzZXMgYXJlIG5vdCBpbiBVVFhPIG91dHB1dCBhZGRyZXNzZXMnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB3YWxsZXRBZGRyZXNzZXMgPSBbRVhQT1JUX0lOX0MucEFkZHJlc3Nlc1swXSwgQUNDT1VOVF8zLmFkZHJlc3NdO1xuICAgICAgY29uc3QgdXR4b091dHB1dEFkZHJlc3NlcyA9IFtFWFBPUlRfSU5fQy5wQWRkcmVzc2VzWzBdLCBFWFBPUlRfSU5fQy5wQWRkcmVzc2VzWzFdXTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCh1dGlscy5pbmNsdWRlSW4od2FsbGV0QWRkcmVzc2VzLCB1dHhvT3V0cHV0QWRkcmVzc2VzKSwgZmFsc2UpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCByZXR1cm4gdHJ1ZSBmb3IgZW1wdHkgd2FsbGV0IGFkZHJlc3NlcycsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHdhbGxldEFkZHJlc3Nlczogc3RyaW5nW10gPSBbXTtcbiAgICAgIGNvbnN0IHV0eG9PdXRwdXRBZGRyZXNzZXMgPSBbRVhQT1JUX0lOX0MucEFkZHJlc3Nlc1swXV07XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwodXRpbHMuaW5jbHVkZUluKHdhbGxldEFkZHJlc3NlcywgdXR4b091dHB1dEFkZHJlc3NlcyksIHRydWUpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnaXNWYWxpZEFkZHJlc3MnLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ3Nob3VsZCByZXR1cm4gdHJ1ZSBmb3IgdmFsaWQgbWFpbm5ldCBQLWNoYWluIGFkZHJlc3MnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwodXRpbHMuaXNWYWxpZEFkZHJlc3MoU0VFRF9BQ0NPVU5ULmFkZHJlc3NNYWlubmV0KSwgdHJ1ZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJldHVybiB0cnVlIGZvciB2YWxpZCB0ZXN0bmV0IFAtY2hhaW4gYWRkcmVzcycsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCh1dGlscy5pc1ZhbGlkQWRkcmVzcyhTRUVEX0FDQ09VTlQuYWRkcmVzc1Rlc3RuZXQpLCB0cnVlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmV0dXJuIHRydWUgZm9yIHZhbGlkIE5vZGVJRCBhZGRyZXNzJywgZnVuY3Rpb24gKCkge1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHV0aWxzLmlzVmFsaWRBZGRyZXNzKCdOb2RlSUQtYWJjMTIzeHl6JyksIHRydWUpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCByZXR1cm4gdHJ1ZSBmb3IgYXJyYXkgb2YgdmFsaWQgYWRkcmVzc2VzJywgZnVuY3Rpb24gKCkge1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHV0aWxzLmlzVmFsaWRBZGRyZXNzKEVYUE9SVF9JTl9DLnBBZGRyZXNzZXMpLCB0cnVlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmV0dXJuIHRydWUgZm9yIHRpbGRlLXNlcGFyYXRlZCBhZGRyZXNzZXMnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBjb21iaW5lZCA9IEVYUE9SVF9JTl9DLnBBZGRyZXNzZXMuam9pbignficpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHV0aWxzLmlzVmFsaWRBZGRyZXNzKGNvbWJpbmVkKSwgdHJ1ZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJldHVybiBmYWxzZSBmb3IgaW52YWxpZCBhZGRyZXNzIGZvcm1hdCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCh1dGlscy5pc1ZhbGlkQWRkcmVzcygnaW52YWxpZCcpLCBmYWxzZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJldHVybiBmYWxzZSBmb3IgYWRkcmVzcyB3aXRob3V0IHByZWZpeCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCh1dGlscy5pc1ZhbGlkQWRkcmVzcygnZmxhcmUxYWJjMTIzJyksIGZhbHNlKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ2lzVmFsaWRCbG9ja0lkJywgZnVuY3Rpb24gKCkge1xuICAgIGl0KCdzaG91bGQgcmV0dXJuIHRydWUgZm9yIHZhbGlkIDMyLWJ5dGUgaGV4IGJsb2NrIElEJywgZnVuY3Rpb24gKCkge1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHV0aWxzLmlzVmFsaWRCbG9ja0lkKFNFRURfQUNDT1VOVC5wcml2YXRlS2V5KSwgdHJ1ZSk7IC8vIDY0IGhleCBjaGFycyA9IDMyIGJ5dGVzXG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJldHVybiBmYWxzZSBmb3IgaW52YWxpZCBsZW5ndGggYmxvY2sgSUQnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwodXRpbHMuaXNWYWxpZEJsb2NrSWQoSU5WQUxJRF9TSE9SVF9LRVlQQUlSX0tFWSksIGZhbHNlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmV0dXJuIGZhbHNlIGZvciBlbXB0eSBibG9jayBJRCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCh1dGlscy5pc1ZhbGlkQmxvY2tJZCgnJyksIGZhbHNlKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ2lzVmFsaWRQdWJsaWNLZXknLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ3Nob3VsZCByZXR1cm4gdHJ1ZSBmb3IgdmFsaWQgY29tcHJlc3NlZCBwdWJsaWMga2V5IHN0YXJ0aW5nIHdpdGggMDMnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwodXRpbHMuaXNWYWxpZFB1YmxpY0tleShTRUVEX0FDQ09VTlQucHVibGljS2V5KSwgdHJ1ZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJldHVybiB0cnVlIGZvciB2YWxpZCBjb21wcmVzc2VkIHB1YmxpYyBrZXkgc3RhcnRpbmcgd2l0aCAwMicsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCh1dGlscy5pc1ZhbGlkUHVibGljS2V5KEFDQ09VTlRfMS5wdWJsaWNLZXkpLCB0cnVlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmV0dXJuIHRydWUgZm9yIGFub3RoZXIgdmFsaWQgY29tcHJlc3NlZCBwdWJsaWMga2V5JywgZnVuY3Rpb24gKCkge1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHV0aWxzLmlzVmFsaWRQdWJsaWNLZXkoQUNDT1VOVF8yLnB1YmxpY0tleSksIHRydWUpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCByZXR1cm4gdHJ1ZSBmb3IgdmFsaWQgeHB1YicsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCh1dGlscy5pc1ZhbGlkUHVibGljS2V5KFNFRURfQUNDT1VOVC54UHVibGljS2V5KSwgdHJ1ZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJldHVybiB0cnVlIGZvciBBQ0NPVU5UXzEgeHB1YicsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCh1dGlscy5pc1ZhbGlkUHVibGljS2V5KEFDQ09VTlRfMS54UHVibGljS2V5KSwgdHJ1ZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJldHVybiBmYWxzZSBmb3IgaW52YWxpZCBzaG9ydCBwdWJsaWMga2V5JywgZnVuY3Rpb24gKCkge1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHV0aWxzLmlzVmFsaWRQdWJsaWNLZXkoSU5WQUxJRF9TSE9SVF9LRVlQQUlSX0tFWSksIGZhbHNlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmV0dXJuIGZhbHNlIGZvciBjb21wcmVzc2VkIGtleSB3aXRoIHdyb25nIHByZWZpeCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGludmFsaWRLZXkgPSAnMDUnICsgU0VFRF9BQ0NPVU5ULnByaXZhdGVLZXk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwodXRpbHMuaXNWYWxpZFB1YmxpY0tleShpbnZhbGlkS2V5KSwgZmFsc2UpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCByZXR1cm4gZmFsc2UgZm9yIG5vbi1oZXggcHVibGljIGtleScsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGludmFsaWRLZXkgPSAnenonICsgU0VFRF9BQ0NPVU5ULnByaXZhdGVLZXk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwodXRpbHMuaXNWYWxpZFB1YmxpY0tleShpbnZhbGlkS2V5KSwgZmFsc2UpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnaXNWYWxpZFByaXZhdGVLZXknLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ3Nob3VsZCByZXR1cm4gdHJ1ZSBmb3IgdmFsaWQgNjQtY2hhciBoZXggcHJpdmF0ZSBrZXknLCBmdW5jdGlvbiAoKSB7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwodXRpbHMuaXNWYWxpZFByaXZhdGVLZXkoU0VFRF9BQ0NPVU5ULnByaXZhdGVLZXkpLCB0cnVlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmV0dXJuIHRydWUgZm9yIEFDQ09VTlRfMSBwcml2YXRlIGtleScsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCh1dGlscy5pc1ZhbGlkUHJpdmF0ZUtleShBQ0NPVU5UXzEucHJpdmF0ZUtleSksIHRydWUpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCByZXR1cm4gdHJ1ZSBmb3IgQUNDT1VOVF8yIHByaXZhdGUga2V5JywgZnVuY3Rpb24gKCkge1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHV0aWxzLmlzVmFsaWRQcml2YXRlS2V5KEFDQ09VTlRfMi5wcml2YXRlS2V5KSwgdHJ1ZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJldHVybiB0cnVlIGZvciB2YWxpZCB4cHJ2JywgZnVuY3Rpb24gKCkge1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHV0aWxzLmlzVmFsaWRQcml2YXRlS2V5KFNFRURfQUNDT1VOVC54UHJpdmF0ZUtleSksIHRydWUpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCByZXR1cm4gdHJ1ZSBmb3IgNjYtY2hhciBwcml2YXRlIGtleSBlbmRpbmcgd2l0aCAwMScsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGV4dGVuZGVkS2V5ID0gU0VFRF9BQ0NPVU5ULnByaXZhdGVLZXkgKyAnMDEnO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHV0aWxzLmlzVmFsaWRQcml2YXRlS2V5KGV4dGVuZGVkS2V5KSwgdHJ1ZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJldHVybiBmYWxzZSBmb3IgNjYtY2hhciBwcml2YXRlIGtleSBub3QgZW5kaW5nIHdpdGggMDEnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwodXRpbHMuaXNWYWxpZFByaXZhdGVLZXkoSU5WQUxJRF9MT05HX0tFWVBBSVJfUFJWKSwgZmFsc2UpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCByZXR1cm4gZmFsc2UgZm9yIGludmFsaWQgc2hvcnQgcHJpdmF0ZSBrZXknLCBmdW5jdGlvbiAoKSB7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwodXRpbHMuaXNWYWxpZFByaXZhdGVLZXkoSU5WQUxJRF9TSE9SVF9LRVlQQUlSX0tFWSksIGZhbHNlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmV0dXJuIGZhbHNlIGZvciBub24taGV4IHByaXZhdGUga2V5JywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgaW52YWxpZEtleSA9ICd6eicgKyBTRUVEX0FDQ09VTlQucHJpdmF0ZUtleS5zbGljZSgyKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCh1dGlscy5pc1ZhbGlkUHJpdmF0ZUtleShpbnZhbGlkS2V5KSwgZmFsc2UpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnYWxsSGV4Q2hhcnMnLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ3Nob3VsZCByZXR1cm4gdHJ1ZSBmb3IgdmFsaWQgcHJpdmF0ZSBrZXkgaGV4JywgZnVuY3Rpb24gKCkge1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHV0aWxzLmFsbEhleENoYXJzKFNFRURfQUNDT1VOVC5wcml2YXRlS2V5KSwgdHJ1ZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJldHVybiB0cnVlIGZvciB2YWxpZCBwdWJsaWMga2V5IGhleCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCh1dGlscy5hbGxIZXhDaGFycyhTRUVEX0FDQ09VTlQucHVibGljS2V5KSwgdHJ1ZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJldHVybiB0cnVlIGZvciBoZXggc3RyaW5nIHdpdGggMHggcHJlZml4JywgZnVuY3Rpb24gKCkge1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHV0aWxzLmFsbEhleENoYXJzKEVYUE9SVF9JTl9DLmNIZXhBZGRyZXNzKSwgdHJ1ZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJldHVybiB0cnVlIGZvciB2YWxpZCBzaWduYXR1cmUgaGV4JywgZnVuY3Rpb24gKCkge1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHV0aWxzLmFsbEhleENoYXJzKFNFRURfQUNDT1VOVC5zaWduYXR1cmUpLCB0cnVlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmV0dXJuIGZhbHNlIGZvciBub24taGV4IGNoYXJhY3RlcnMnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwodXRpbHMuYWxsSGV4Q2hhcnMoJ2doaWprbCcpLCBmYWxzZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJldHVybiBmYWxzZSBmb3IgZW1wdHkgc3RyaW5nJywgZnVuY3Rpb24gKCkge1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHV0aWxzLmFsbEhleENoYXJzKCcnKSwgZmFsc2UpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnY3JlYXRlU2lnbmF0dXJlIGFuZCB2ZXJpZnlTaWduYXR1cmUnLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ3Nob3VsZCBjcmVhdGUgYSB2YWxpZCA2NS1ieXRlIHNpZ25hdHVyZScsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IG1lc3NhZ2UgPSBCdWZmZXIuZnJvbShTRUVEX0FDQ09VTlQubWVzc2FnZSwgJ3V0ZjgnKTtcbiAgICAgIGNvbnN0IHByaXZhdGVLZXkgPSBCdWZmZXIuZnJvbShTRUVEX0FDQ09VTlQucHJpdmF0ZUtleSwgJ2hleCcpO1xuXG4gICAgICBjb25zdCBzaWduYXR1cmUgPSB1dGlscy5jcmVhdGVTaWduYXR1cmUobmV0d29yaywgbWVzc2FnZSwgcHJpdmF0ZUtleSk7XG5cbiAgICAgIGFzc2VydC5vayhzaWduYXR1cmUgaW5zdGFuY2VvZiBCdWZmZXIpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHNpZ25hdHVyZS5sZW5ndGgsIDY1KTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdmVyaWZ5IGEgdmFsaWQgc2lnbmF0dXJlJywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgbWVzc2FnZSA9IEJ1ZmZlci5mcm9tKFNFRURfQUNDT1VOVC5tZXNzYWdlLCAndXRmOCcpO1xuICAgICAgY29uc3QgcHJpdmF0ZUtleSA9IEJ1ZmZlci5mcm9tKFNFRURfQUNDT1VOVC5wcml2YXRlS2V5LCAnaGV4Jyk7XG4gICAgICBjb25zdCBwdWJsaWNLZXkgPSBCdWZmZXIuZnJvbShTRUVEX0FDQ09VTlQucHVibGljS2V5LCAnaGV4Jyk7XG5cbiAgICAgIGNvbnN0IHNpZ25hdHVyZSA9IHV0aWxzLmNyZWF0ZVNpZ25hdHVyZShuZXR3b3JrLCBtZXNzYWdlLCBwcml2YXRlS2V5KTtcbiAgICAgIGNvbnN0IHNpZ09ubHkgPSBzaWduYXR1cmUuc2xpY2UoMCwgNjQpO1xuXG4gICAgICBjb25zdCBtZXNzYWdlSGFzaCA9IHV0aWxzLnNoYTI1NihtZXNzYWdlKTtcbiAgICAgIGNvbnN0IGlzVmFsaWQgPSB1dGlscy52ZXJpZnlTaWduYXR1cmUobWVzc2FnZUhhc2gsIHNpZ09ubHksIHB1YmxpY0tleSk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoaXNWYWxpZCwgdHJ1ZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJldHVybiBmYWxzZSBmb3IgaW52YWxpZCBzaWduYXR1cmUnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBtZXNzYWdlID0gQnVmZmVyLmZyb20oU0VFRF9BQ0NPVU5ULm1lc3NhZ2UsICd1dGY4Jyk7XG4gICAgICBjb25zdCBwdWJsaWNLZXkgPSBCdWZmZXIuZnJvbShTRUVEX0FDQ09VTlQucHVibGljS2V5LCAnaGV4Jyk7XG4gICAgICBjb25zdCBpbnZhbGlkU2lnbmF0dXJlID0gQnVmZmVyLmFsbG9jKDY0KTtcblxuICAgICAgY29uc3QgbWVzc2FnZUhhc2ggPSB1dGlscy5zaGEyNTYobWVzc2FnZSk7XG4gICAgICBjb25zdCBpc1ZhbGlkID0gdXRpbHMudmVyaWZ5U2lnbmF0dXJlKG1lc3NhZ2VIYXNoLCBpbnZhbGlkU2lnbmF0dXJlLCBwdWJsaWNLZXkpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKGlzVmFsaWQsIGZhbHNlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgY3JlYXRlIHNpZ25hdHVyZSB3aXRoIEFDQ09VTlRfMSBrZXlzJywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgbWVzc2FnZSA9IEJ1ZmZlci5mcm9tKFNFRURfQUNDT1VOVC5tZXNzYWdlLCAndXRmOCcpO1xuICAgICAgY29uc3QgcHJpdmF0ZUtleSA9IEJ1ZmZlci5mcm9tKEFDQ09VTlRfMS5wcml2YXRlS2V5LCAnaGV4Jyk7XG5cbiAgICAgIGNvbnN0IHNpZ25hdHVyZSA9IHV0aWxzLmNyZWF0ZVNpZ25hdHVyZShuZXR3b3JrLCBtZXNzYWdlLCBwcml2YXRlS2V5KTtcblxuICAgICAgYXNzZXJ0Lm9rKHNpZ25hdHVyZSBpbnN0YW5jZW9mIEJ1ZmZlcik7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoc2lnbmF0dXJlLmxlbmd0aCwgNjUpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnY3JlYXRlTmV3U2lnJywgZnVuY3Rpb24gKCkge1xuICAgIGl0KCdzaG91bGQgY3JlYXRlIGEgc2lnbmF0dXJlIGZyb20gdmFsaWQgc2lnbmF0dXJlIGhleCBzdHJpbmcnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBzaWcgPSB1dGlscy5jcmVhdGVOZXdTaWcoU0VFRF9BQ0NPVU5ULnNpZ25hdHVyZSk7XG4gICAgICBhc3NlcnQub2soc2lnKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgY3JlYXRlIGEgc2lnbmF0dXJlIGZyb20gZXhwb3J0IHNpZ25hdHVyZSBoZXgnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBzaWdIZXggPSB1dGlscy5yZW1vdmVIZXhQcmVmaXgoRVhQT1JUX0lOX0Muc2lnbmF0dXJlWzBdKTtcbiAgICAgIGNvbnN0IHNpZyA9IHV0aWxzLmNyZWF0ZU5ld1NpZyhzaWdIZXgpO1xuICAgICAgYXNzZXJ0Lm9rKHNpZyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHBhZCBzaG9ydCBoZXggc3RyaW5ncycsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHNpZ0hleCA9IElOVkFMSURfU0hPUlRfS0VZUEFJUl9LRVk7XG4gICAgICBjb25zdCBzaWcgPSB1dGlscy5jcmVhdGVOZXdTaWcoc2lnSGV4KTtcbiAgICAgIGFzc2VydC5vayhzaWcpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnY3JlYXRlRW1wdHlTaWdXaXRoQWRkcmVzcyBhbmQgZ2V0QWRkcmVzc0Zyb21FbXB0eVNpZycsIGZ1bmN0aW9uICgpIHtcbiAgICBpdCgnc2hvdWxkIGNyZWF0ZSBlbXB0eSBzaWduYXR1cmUgd2l0aCBlbWJlZGRlZCBDLWNoYWluIGFkZHJlc3MnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBhZGRyZXNzSGV4ID0gdXRpbHMucmVtb3ZlSGV4UHJlZml4KEVYUE9SVF9JTl9DLmNIZXhBZGRyZXNzKTtcbiAgICAgIGNvbnN0IHNpZyA9IHV0aWxzLmNyZWF0ZUVtcHR5U2lnV2l0aEFkZHJlc3MoYWRkcmVzc0hleCk7XG4gICAgICBhc3NlcnQub2soc2lnKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgZXh0cmFjdCBlbWJlZGRlZCBhZGRyZXNzIGZyb20gZW1wdHkgc2lnbmF0dXJlJywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgYWRkcmVzc0hleCA9IHV0aWxzLnJlbW92ZUhleFByZWZpeChFWFBPUlRfSU5fQy5jSGV4QWRkcmVzcykudG9Mb3dlckNhc2UoKTtcbiAgICAgIGNvbnN0IHNpZyA9IHV0aWxzLmNyZWF0ZUVtcHR5U2lnV2l0aEFkZHJlc3MoYWRkcmVzc0hleCk7XG5cbiAgICAgIC8vIEdldCBzaWduYXR1cmUgYnl0ZXMgYW5kIGNvbnZlcnQgdG8gaGV4XG4gICAgICBjb25zdCBzaWdCeXRlcyA9IHNpZy50b0J5dGVzKCk7XG4gICAgICBjb25zdCBzaWdIZXggPSBCdWZmZXIuZnJvbShzaWdCeXRlcykudG9TdHJpbmcoJ2hleCcpO1xuXG4gICAgICBjb25zdCBleHRyYWN0ZWRBZGRyZXNzID0gdXRpbHMuZ2V0QWRkcmVzc0Zyb21FbXB0eVNpZyhzaWdIZXgpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKGV4dHJhY3RlZEFkZHJlc3MsIGFkZHJlc3NIZXgpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBoYW5kbGUgMHggcHJlZml4ZWQgYWRkcmVzcycsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHNpZyA9IHV0aWxzLmNyZWF0ZUVtcHR5U2lnV2l0aEFkZHJlc3MoRVhQT1JUX0lOX0MuY0hleEFkZHJlc3MpO1xuICAgICAgYXNzZXJ0Lm9rKHNpZyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJldHVybiBlbXB0eSBzdHJpbmcgZm9yIHNob3J0IHNpZ25hdHVyZScsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHNob3J0U2lnID0gU0VFRF9BQ0NPVU5ULnByaXZhdGVLZXk7IC8vIDY0IGNoYXJzLCBsZXNzIHRoYW4gMTMwXG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwodXRpbHMuZ2V0QWRkcmVzc0Zyb21FbXB0eVNpZyhzaG9ydFNpZyksICcnKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ3NoYTI1NicsIGZ1bmN0aW9uICgpIHtcbiAgICBpdCgnc2hvdWxkIGNvbXB1dGUgU0hBMjU2IGhhc2ggb2YgbWVzc2FnZScsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGRhdGEgPSBCdWZmZXIuZnJvbShTRUVEX0FDQ09VTlQubWVzc2FnZSwgJ3V0ZjgnKTtcbiAgICAgIGNvbnN0IGhhc2ggPSB1dGlscy5zaGEyNTYoZGF0YSk7XG5cbiAgICAgIGFzc2VydC5vayhoYXNoIGluc3RhbmNlb2YgQnVmZmVyKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChoYXNoLmxlbmd0aCwgMzIpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBwcm9kdWNlIGNvbnNpc3RlbnQgaGFzaCBmb3Igc2FtZSBpbnB1dCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGRhdGEgPSBCdWZmZXIuZnJvbShTRUVEX0FDQ09VTlQubWVzc2FnZSwgJ3V0ZjgnKTtcbiAgICAgIGNvbnN0IGhhc2gxID0gdXRpbHMuc2hhMjU2KGRhdGEpO1xuICAgICAgY29uc3QgaGFzaDIgPSB1dGlscy5zaGEyNTYoZGF0YSk7XG5cbiAgICAgIGFzc2VydC5kZWVwU3RyaWN0RXF1YWwoaGFzaDEsIGhhc2gyKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcHJvZHVjZSBkaWZmZXJlbnQgaGFzaCBmb3IgZGlmZmVyZW50IGlucHV0JywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgZGF0YTEgPSBCdWZmZXIuZnJvbShTRUVEX0FDQ09VTlQubWVzc2FnZSwgJ3V0ZjgnKTtcbiAgICAgIGNvbnN0IGRhdGEyID0gQnVmZmVyLmZyb20oU0VFRF9BQ0NPVU5ULnByaXZhdGVLZXksICd1dGY4Jyk7XG4gICAgICBjb25zdCBoYXNoMSA9IHV0aWxzLnNoYTI1NihkYXRhMSk7XG4gICAgICBjb25zdCBoYXNoMiA9IHV0aWxzLnNoYTI1NihkYXRhMik7XG5cbiAgICAgIGFzc2VydC5ub3REZWVwU3RyaWN0RXF1YWwoaGFzaDEsIGhhc2gyKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ3ZhbGlkYXRlUmF3VHJhbnNhY3Rpb24nLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ3Nob3VsZCBub3QgdGhyb3cgZm9yIHZhbGlkIHVuc2lnbmVkIGhleCB0cmFuc2FjdGlvbicsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHJhd1R4ID0gdXRpbHMucmVtb3ZlSGV4UHJlZml4KEVYUE9SVF9JTl9DLnVuc2lnbmVkSGV4KTtcbiAgICAgIGFzc2VydC5kb2VzTm90VGhyb3coKCkgPT4gdXRpbHMudmFsaWRhdGVSYXdUcmFuc2FjdGlvbihyYXdUeCkpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBub3QgdGhyb3cgZm9yIHZhbGlkIHNpZ25lZCBoZXggdHJhbnNhY3Rpb24nLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCByYXdUeCA9IHV0aWxzLnJlbW92ZUhleFByZWZpeChFWFBPUlRfSU5fQy5zaWduZWRIZXgpO1xuICAgICAgYXNzZXJ0LmRvZXNOb3RUaHJvdygoKSA9PiB1dGlscy52YWxpZGF0ZVJhd1RyYW5zYWN0aW9uKHJhd1R4KSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIG5vdCB0aHJvdyBmb3IgaW1wb3J0IHRyYW5zYWN0aW9uIGhleCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHJhd1R4ID0gdXRpbHMucmVtb3ZlSGV4UHJlZml4KElNUE9SVF9JTl9QLnVuc2lnbmVkSGV4KTtcbiAgICAgIGFzc2VydC5kb2VzTm90VGhyb3coKCkgPT4gdXRpbHMudmFsaWRhdGVSYXdUcmFuc2FjdGlvbihyYXdUeCkpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0aHJvdyBmb3IgZW1wdHkgdHJhbnNhY3Rpb24nLCBmdW5jdGlvbiAoKSB7XG4gICAgICBhc3NlcnQudGhyb3dzKCgpID0+IHV0aWxzLnZhbGlkYXRlUmF3VHJhbnNhY3Rpb24oJycpLCAvUmF3IHRyYW5zYWN0aW9uIGlzIGVtcHR5Lyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHRocm93IGZvciBub24taGV4IHRyYW5zYWN0aW9uJywgZnVuY3Rpb24gKCkge1xuICAgICAgYXNzZXJ0LnRocm93cygoKSA9PiB1dGlscy52YWxpZGF0ZVJhd1RyYW5zYWN0aW9uKCd4eXoxMjMnKSwgL1JhdyB0cmFuc2FjdGlvbiBpcyBub3QgaGV4IHN0cmluZy8pO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgncmVtb3ZlSGV4UHJlZml4JywgZnVuY3Rpb24gKCkge1xuICAgIGl0KCdzaG91bGQgcmVtb3ZlIDB4IHByZWZpeCBmcm9tIEMtY2hhaW4gYWRkcmVzcycsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCh1dGlscy5yZW1vdmVIZXhQcmVmaXgoRVhQT1JUX0lOX0MuY0hleEFkZHJlc3MpLCBFWFBPUlRfSU5fQy5jSGV4QWRkcmVzcy5zbGljZSgyKSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJlbW92ZSAweCBwcmVmaXggZnJvbSB1bnNpZ25lZCBoZXgnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwodXRpbHMucmVtb3ZlSGV4UHJlZml4KEVYUE9SVF9JTl9DLnVuc2lnbmVkSGV4KSwgRVhQT1JUX0lOX0MudW5zaWduZWRIZXguc2xpY2UoMikpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCByZXR1cm4gc3RyaW5nIHVuY2hhbmdlZCBpZiBubyBwcmVmaXgnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwodXRpbHMucmVtb3ZlSGV4UHJlZml4KFNFRURfQUNDT1VOVC5wcml2YXRlS2V5KSwgU0VFRF9BQ0NPVU5ULnByaXZhdGVLZXkpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBoYW5kbGUgZW1wdHkgc3RyaW5nJywgZnVuY3Rpb24gKCkge1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHV0aWxzLnJlbW92ZUhleFByZWZpeCgnJyksICcnKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ291dHB1dGlkeE51bWJlclRvQnVmZmVyIGFuZCBvdXRwdXRpZHhCdWZmZXJUb051bWJlcicsIGZ1bmN0aW9uICgpIHtcbiAgICBpdCgnc2hvdWxkIGNvbnZlcnQgb3V0cHV0IGluZGV4IHRvIGJ1ZmZlciBhbmQgYmFjaycsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IG91dHB1dElkeCA9IElNUE9SVF9JTl9QLm91dHB1dHNbMF0ub3V0cHV0aWR4O1xuICAgICAgY29uc3QgYnVmZmVyID0gdXRpbHMub3V0cHV0aWR4TnVtYmVyVG9CdWZmZXIob3V0cHV0SWR4KTtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IHV0aWxzLm91dHB1dGlkeEJ1ZmZlclRvTnVtYmVyKGJ1ZmZlcik7XG5cbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChyZXN1bHQsIG91dHB1dElkeCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGhhbmRsZSBub25jZSB2YWx1ZScsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IG5vbmNlU3RyID0gRVhQT1JUX0lOX0Mubm9uY2UudG9TdHJpbmcoKTtcbiAgICAgIGNvbnN0IGJ1ZmZlciA9IHV0aWxzLm91dHB1dGlkeE51bWJlclRvQnVmZmVyKG5vbmNlU3RyKTtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IHV0aWxzLm91dHB1dGlkeEJ1ZmZlclRvTnVtYmVyKGJ1ZmZlcik7XG5cbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChyZXN1bHQsIG5vbmNlU3RyKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcHJvZHVjZSA0LWJ5dGUgYnVmZmVyJywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgYnVmZmVyID0gdXRpbHMub3V0cHV0aWR4TnVtYmVyVG9CdWZmZXIoJzI1NScpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKGJ1ZmZlci5sZW5ndGgsIDQpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnYWRkcmVzc1RvU3RyaW5nJywgZnVuY3Rpb24gKCkge1xuICAgIGl0KCdzaG91bGQgY29udmVydCBhZGRyZXNzIGJ1ZmZlciB0byBtYWlubmV0IGJlY2gzMiBzdHJpbmcnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBhZGRyZXNzID0gU0VFRF9BQ0NPVU5ULmFkZHJlc3NNYWlubmV0O1xuICAgICAgY29uc3QgYWRkcmVzc0J1ZmZlciA9IHV0aWxzLnBhcnNlQWRkcmVzcyhhZGRyZXNzKTtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IHV0aWxzLmFkZHJlc3NUb1N0cmluZygnZmxhcmUnLCAnUCcsIGFkZHJlc3NCdWZmZXIpO1xuXG4gICAgICBhc3NlcnQub2socmVzdWx0LnN0YXJ0c1dpdGgoJ1AtJykpO1xuICAgICAgYXNzZXJ0Lm9rKHJlc3VsdC5pbmNsdWRlcygnZmxhcmUnKSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGNvbnZlcnQgYWRkcmVzcyBidWZmZXIgdG8gdGVzdG5ldCBiZWNoMzIgc3RyaW5nJywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgYWRkcmVzcyA9IFNFRURfQUNDT1VOVC5hZGRyZXNzVGVzdG5ldDtcbiAgICAgIGNvbnN0IGFkZHJlc3NCdWZmZXIgPSB1dGlscy5wYXJzZUFkZHJlc3MoYWRkcmVzcyk7XG4gICAgICBjb25zdCByZXN1bHQgPSB1dGlscy5hZGRyZXNzVG9TdHJpbmcoJ2Nvc3R3bycsICdQJywgYWRkcmVzc0J1ZmZlcik7XG5cbiAgICAgIGFzc2VydC5vayhyZXN1bHQuc3RhcnRzV2l0aCgnUC0nKSk7XG4gICAgICBhc3NlcnQub2socmVzdWx0LmluY2x1ZGVzKCdjb3N0d28nKSk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdjYjU4RW5jb2RlIGFuZCBjYjU4RGVjb2RlJywgZnVuY3Rpb24gKCkge1xuICAgIGl0KCdzaG91bGQgZW5jb2RlIGFuZCBkZWNvZGUgdGFyZ2V0IGNoYWluIElEIGNvcnJlY3RseScsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGVuY29kZWQgPSBFWFBPUlRfSU5fQy50YXJnZXRDaGFpbklkO1xuICAgICAgY29uc3QgZGVjb2RlZCA9IHV0aWxzLmNiNThEZWNvZGUoZW5jb2RlZCk7XG4gICAgICBjb25zdCByZUVuY29kZWQgPSB1dGlscy5jYjU4RW5jb2RlKGRlY29kZWQpO1xuXG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwocmVFbmNvZGVkLCBlbmNvZGVkKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgZW5jb2RlIGFuZCBkZWNvZGUgc291cmNlIGNoYWluIElEIGNvcnJlY3RseScsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGVuY29kZWQgPSBJTVBPUlRfSU5fUC5zb3VyY2VDaGFpbklkO1xuICAgICAgY29uc3QgZGVjb2RlZCA9IHV0aWxzLmNiNThEZWNvZGUoZW5jb2RlZCk7XG4gICAgICBjb25zdCByZUVuY29kZWQgPSB1dGlscy5jYjU4RW5jb2RlKGRlY29kZWQpO1xuXG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwocmVFbmNvZGVkLCBlbmNvZGVkKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdGhyb3cgZm9yIGludmFsaWQgY2hlY2tzdW0nLCBmdW5jdGlvbiAoKSB7XG4gICAgICBhc3NlcnQudGhyb3dzKCgpID0+IHV0aWxzLmNiNThEZWNvZGUoJzExMTExMTExMTExMTEnKSwgL0ludmFsaWQgY2hlY2tzdW0vKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ3BhcnNlQWRkcmVzcyBhbmQgc3RyaW5nVG9BZGRyZXNzJywgZnVuY3Rpb24gKCkge1xuICAgIGl0KCdzaG91bGQgcGFyc2UgaGV4IGFkZHJlc3Mgd2l0aCAweCBwcmVmaXgnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBidWZmZXIgPSB1dGlscy5wYXJzZUFkZHJlc3MoRVhQT1JUX0lOX0MuY0hleEFkZHJlc3MpO1xuXG4gICAgICBhc3NlcnQub2soYnVmZmVyIGluc3RhbmNlb2YgQnVmZmVyKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChidWZmZXIubGVuZ3RoLCAyMCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHBhcnNlIHJhdyBoZXggYWRkcmVzcyBmcm9tIG91dHB1dHMnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBhZGRyZXNzID0gSU1QT1JUX0lOX1Aub3V0cHV0c1swXS5hZGRyZXNzZXNbMF07XG4gICAgICBjb25zdCBidWZmZXIgPSB1dGlscy5wYXJzZUFkZHJlc3MoYWRkcmVzcyk7XG5cbiAgICAgIGFzc2VydC5vayhidWZmZXIgaW5zdGFuY2VvZiBCdWZmZXIpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKGJ1ZmZlci5sZW5ndGgsIDIwKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcGFyc2UgbWFpbm5ldCBiZWNoMzIgYWRkcmVzcycsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGJ1ZmZlciA9IHV0aWxzLnBhcnNlQWRkcmVzcyhTRUVEX0FDQ09VTlQuYWRkcmVzc01haW5uZXQpO1xuXG4gICAgICBhc3NlcnQub2soYnVmZmVyIGluc3RhbmNlb2YgQnVmZmVyKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChidWZmZXIubGVuZ3RoLCAyMCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHBhcnNlIHRlc3RuZXQgYmVjaDMyIGFkZHJlc3MnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBidWZmZXIgPSB1dGlscy5wYXJzZUFkZHJlc3MoU0VFRF9BQ0NPVU5ULmFkZHJlc3NUZXN0bmV0KTtcblxuICAgICAgYXNzZXJ0Lm9rKGJ1ZmZlciBpbnN0YW5jZW9mIEJ1ZmZlcik7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoYnVmZmVyLmxlbmd0aCwgMjApO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBwYXJzZSBQLWNoYWluIGFkZHJlc3NlcyBmcm9tIGV4cG9ydCBkYXRhJywgZnVuY3Rpb24gKCkge1xuICAgICAgRVhQT1JUX0lOX0MucEFkZHJlc3Nlcy5mb3JFYWNoKChhZGRyZXNzKSA9PiB7XG4gICAgICAgIGNvbnN0IGJ1ZmZlciA9IHV0aWxzLnBhcnNlQWRkcmVzcyhhZGRyZXNzKTtcbiAgICAgICAgYXNzZXJ0Lm9rKGJ1ZmZlciBpbnN0YW5jZW9mIEJ1ZmZlcik7XG4gICAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChidWZmZXIubGVuZ3RoLCAyMCk7XG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdGhyb3cgZm9yIGFkZHJlc3Mgd2l0aG91dCBkYXNoIHNlcGFyYXRvcicsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGFzc2VydC50aHJvd3MoKCkgPT4gdXRpbHMucGFyc2VBZGRyZXNzKCdmbGFyZTFhYmMnKSwgL1ZhbGlkIGFkZHJlc3Mgc2hvdWxkIGluY2x1ZGUgLS8pO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0aHJvdyBmb3IgaW52YWxpZCBIUlAnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBhc3NlcnQudGhyb3dzKCgpID0+IHV0aWxzLnBhcnNlQWRkcmVzcygnUC1pbnZhbGlkMXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxNWV2em15JyksIC9JbnZhbGlkIEhSUC8pO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnZmxhcmVJZFN0cmluZycsIGZ1bmN0aW9uICgpIHtcbiAgICBpdCgnc2hvdWxkIGNyZWF0ZSBJZCBmcm9tIHByaXZhdGUga2V5IGhleCBzdHJpbmcnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBpZCA9IHV0aWxzLmZsYXJlSWRTdHJpbmcoU0VFRF9BQ0NPVU5ULnByaXZhdGVLZXkpO1xuICAgICAgYXNzZXJ0Lm9rKGlkKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgY3JlYXRlIElkIGZyb20gYXNzZXQgSUQgaGV4JywgZnVuY3Rpb24gKCkge1xuICAgICAgLy8gQXNzZXQgSUQgaXMgdHlwaWNhbGx5IDMyIGJ5dGVzICg2NCBoZXggY2hhcnMpXG4gICAgICBjb25zdCBhc3NldElkSGV4ID0gU0VFRF9BQ0NPVU5ULnByaXZhdGVLZXk7IC8vIFVzaW5nIGFzIGEgMzItYnl0ZSBoZXhcbiAgICAgIGNvbnN0IGlkID0gdXRpbHMuZmxhcmVJZFN0cmluZyhhc3NldElkSGV4KTtcbiAgICAgIGFzc2VydC5vayhpZCk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdyZWNvdmVyeVNpZ25hdHVyZScsIGZ1bmN0aW9uICgpIHtcbiAgICBpdCgnc2hvdWxkIHJlY292ZXIgcHVibGljIGtleSBmcm9tIHZhbGlkIHNpZ25hdHVyZScsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IG1lc3NhZ2UgPSBCdWZmZXIuZnJvbShTRUVEX0FDQ09VTlQubWVzc2FnZSwgJ3V0ZjgnKTtcbiAgICAgIGNvbnN0IHByaXZhdGVLZXkgPSBCdWZmZXIuZnJvbShTRUVEX0FDQ09VTlQucHJpdmF0ZUtleSwgJ2hleCcpO1xuXG4gICAgICAvLyBDcmVhdGUgc2lnbmF0dXJlIHVzaW5nIHRoZSBzYW1lIHByaXZhdGUga2V5IChjcmVhdGVTaWduYXR1cmUgaGFzaGVzIHRoZSBtZXNzYWdlIGludGVybmFsbHkpXG4gICAgICBjb25zdCBzaWduYXR1cmUgPSB1dGlscy5jcmVhdGVTaWduYXR1cmUobmV0d29yaywgbWVzc2FnZSwgcHJpdmF0ZUtleSk7XG5cbiAgICAgIC8vIFJlY292ZXIgcHVibGljIGtleSAtIHBhc3MgdGhlIGhhc2hlZCBtZXNzYWdlIHNpbmNlIHJlY292ZXJ5U2lnbmF0dXJlIGV4cGVjdHMgcHJlLWhhc2hlZFxuICAgICAgY29uc3QgbWVzc2FnZUhhc2ggPSB1dGlscy5zaGEyNTYobWVzc2FnZSk7XG4gICAgICBjb25zdCByZWNvdmVyZWRQdWJLZXkgPSB1dGlscy5yZWNvdmVyeVNpZ25hdHVyZShtZXNzYWdlSGFzaCwgc2lnbmF0dXJlKTtcblxuICAgICAgYXNzZXJ0Lm9rKHJlY292ZXJlZFB1YktleSBpbnN0YW5jZW9mIEJ1ZmZlcik7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwocmVjb3ZlcmVkUHViS2V5Lmxlbmd0aCwgMzMpOyAvLyBTaG91bGQgYmUgY29tcHJlc3NlZCBwdWJsaWMga2V5ICgzMyBieXRlcylcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmVjb3ZlciBzYW1lIHB1YmxpYyBrZXkgZm9yIHNhbWUgbWVzc2FnZSBhbmQgc2lnbmF0dXJlJywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgbWVzc2FnZSA9IEJ1ZmZlci5mcm9tKFNFRURfQUNDT1VOVC5tZXNzYWdlLCAndXRmOCcpO1xuICAgICAgY29uc3QgcHJpdmF0ZUtleSA9IEJ1ZmZlci5mcm9tKFNFRURfQUNDT1VOVC5wcml2YXRlS2V5LCAnaGV4Jyk7XG4gICAgICBjb25zdCBzaWduYXR1cmUgPSB1dGlscy5jcmVhdGVTaWduYXR1cmUobmV0d29yaywgbWVzc2FnZSwgcHJpdmF0ZUtleSk7XG5cbiAgICAgIGNvbnN0IG1lc3NhZ2VIYXNoID0gdXRpbHMuc2hhMjU2KG1lc3NhZ2UpO1xuICAgICAgY29uc3QgcHViS2V5MSA9IHV0aWxzLnJlY292ZXJ5U2lnbmF0dXJlKG1lc3NhZ2VIYXNoLCBzaWduYXR1cmUpO1xuICAgICAgY29uc3QgcHViS2V5MiA9IHV0aWxzLnJlY292ZXJ5U2lnbmF0dXJlKG1lc3NhZ2VIYXNoLCBzaWduYXR1cmUpO1xuXG4gICAgICBhc3NlcnQuZGVlcFN0cmljdEVxdWFsKHB1YktleTEsIHB1YktleTIpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCByZWNvdmVyIHB1YmxpYyBrZXkgdGhhdCBtYXRjaGVzIG9yaWdpbmFsIGtleScsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IG1lc3NhZ2UgPSBCdWZmZXIuZnJvbShTRUVEX0FDQ09VTlQubWVzc2FnZSwgJ3V0ZjgnKTtcbiAgICAgIGNvbnN0IHByaXZhdGVLZXkgPSBCdWZmZXIuZnJvbShTRUVEX0FDQ09VTlQucHJpdmF0ZUtleSwgJ2hleCcpO1xuXG4gICAgICAvLyBHZXQgb3JpZ2luYWwgcHVibGljIGtleVxuICAgICAgY29uc3Qgb3JpZ2luYWxQdWJLZXkgPSBCdWZmZXIuZnJvbShlY2MucG9pbnRGcm9tU2NhbGFyKHByaXZhdGVLZXksIHRydWUpIGFzIFVpbnQ4QXJyYXkpO1xuXG4gICAgICAvLyBDcmVhdGUgc2lnbmF0dXJlIGFuZCByZWNvdmVyIHB1YmxpYyBrZXlcbiAgICAgIGNvbnN0IHNpZ25hdHVyZSA9IHV0aWxzLmNyZWF0ZVNpZ25hdHVyZShuZXR3b3JrLCBtZXNzYWdlLCBwcml2YXRlS2V5KTtcbiAgICAgIGNvbnN0IG1lc3NhZ2VIYXNoID0gdXRpbHMuc2hhMjU2KG1lc3NhZ2UpO1xuICAgICAgY29uc3QgcmVjb3ZlcmVkUHViS2V5ID0gdXRpbHMucmVjb3ZlcnlTaWduYXR1cmUobWVzc2FnZUhhc2gsIHNpZ25hdHVyZSk7XG5cbiAgICAgIC8vIENvbnZlcnQgYm90aCB0byBoZXggc3RyaW5ncyBmb3IgY29tcGFyaXNvblxuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHJlY292ZXJlZFB1YktleS50b1N0cmluZygnaGV4JyksIG9yaWdpbmFsUHViS2V5LnRvU3RyaW5nKCdoZXgnKSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJlY292ZXIgcHVibGljIGtleSB1c2luZyBBQ0NPVU5UXzEga2V5cycsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IG1lc3NhZ2UgPSBCdWZmZXIuZnJvbShTRUVEX0FDQ09VTlQubWVzc2FnZSwgJ3V0ZjgnKTtcbiAgICAgIGNvbnN0IHByaXZhdGVLZXkgPSBCdWZmZXIuZnJvbShBQ0NPVU5UXzEucHJpdmF0ZUtleSwgJ2hleCcpO1xuXG4gICAgICBjb25zdCBvcmlnaW5hbFB1YktleSA9IEJ1ZmZlci5mcm9tKGVjYy5wb2ludEZyb21TY2FsYXIocHJpdmF0ZUtleSwgdHJ1ZSkgYXMgVWludDhBcnJheSk7XG5cbiAgICAgIGNvbnN0IHNpZ25hdHVyZSA9IHV0aWxzLmNyZWF0ZVNpZ25hdHVyZShuZXR3b3JrLCBtZXNzYWdlLCBwcml2YXRlS2V5KTtcbiAgICAgIGNvbnN0IG1lc3NhZ2VIYXNoID0gdXRpbHMuc2hhMjU2KG1lc3NhZ2UpO1xuICAgICAgY29uc3QgcmVjb3ZlcmVkUHViS2V5ID0gdXRpbHMucmVjb3ZlcnlTaWduYXR1cmUobWVzc2FnZUhhc2gsIHNpZ25hdHVyZSk7XG5cbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChyZWNvdmVyZWRQdWJLZXkudG9TdHJpbmcoJ2hleCcpLCBvcmlnaW5hbFB1YktleS50b1N0cmluZygnaGV4JykpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0aHJvdyBlcnJvciBmb3IgaW52YWxpZCBzaWduYXR1cmUgbGVuZ3RoJywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgbWVzc2FnZUhhc2ggPSB1dGlscy5zaGEyNTYoQnVmZmVyLmZyb20oU0VFRF9BQ0NPVU5ULm1lc3NhZ2UsICd1dGY4JykpO1xuICAgICAgY29uc3QgaW52YWxpZFNpZ25hdHVyZSA9IEJ1ZmZlci5mcm9tKElOVkFMSURfU0hPUlRfS0VZUEFJUl9LRVksICdoZXgnKTtcblxuICAgICAgYXNzZXJ0LnRocm93cygoKSA9PiB1dGlscy5yZWNvdmVyeVNpZ25hdHVyZShtZXNzYWdlSGFzaCwgaW52YWxpZFNpZ25hdHVyZSksIC9GYWlsZWQgdG8gcmVjb3ZlciBzaWduYXR1cmUvKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdGhyb3cgZXJyb3IgZm9yIHNpZ25hdHVyZSB3aXRoIGludmFsaWQgcmVjb3ZlcnkgcGFyYW1ldGVyJywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgbWVzc2FnZUhhc2ggPSB1dGlscy5zaGEyNTYoQnVmZmVyLmZyb20oU0VFRF9BQ0NPVU5ULm1lc3NhZ2UsICd1dGY4JykpO1xuICAgICAgY29uc3Qgc2lnbmF0dXJlID0gQnVmZmVyLmFsbG9jKDY1KTsgLy8gVmFsaWQgbGVuZ3RoIGJ1dCBhbGwgemVyb3MgLSBpbnZhbGlkIHNpZ25hdHVyZVxuXG4gICAgICBhc3NlcnQudGhyb3dzKCgpID0+IHV0aWxzLnJlY292ZXJ5U2lnbmF0dXJlKG1lc3NhZ2VIYXNoLCBzaWduYXR1cmUpLCAvRmFpbGVkIHRvIHJlY292ZXIgc2lnbmF0dXJlLyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJlY292ZXIgc2lnbmF0dXJlIGFuZCB2ZXJpZnkgc2VuZGVyIGFkZHJlc3MgZnJvbSBzaWduZWQgQy1jaGFpbiBFeHBvcnQgdHgnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAvLyBUcmFuc2FjdGlvbiBmcm9tIGFjdHVhbCBidWlsZCByZXNwb25zZSAtIEMtY2hhaW4gRXhwb3J0IHR4XG4gICAgICBjb25zdCB0eCA9XG4gICAgICAgICcweDAwMDAwMDAwMDAwMTAwMDAwMDcyNzhkYjVjMzBiZWQwNGMwNWNlMjA5MTc5ODEyODUwYmJiM2ZlNmQ0NmQ3ZWVmMzc0NGQ4MTRjMGRhNTU1MjQ3OTAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMTJhOTYwMjVhZDUwNmI5ZmJiOTAyM2ZiZGMxNjY1YzdmN2Q3YzkyM2YwMDAwMDAwMDA2MDUyMzY2NTg3MzRmOTRhZjg3MWMzZDEzMWI1NjEzMWI2ZmI3YTAyOTFlYWNhZGQyNjFlNjlkZmI0MmE5Y2RmNmY3ZmRkZDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMTU4NzM0Zjk0YWY4NzFjM2QxMzFiNTYxMzFiNmZiN2EwMjkxZWFjYWRkMjYxZTY5ZGZiNDJhOWNkZjZmN2ZkZGQwMDAwMDAwNzAwMDAwMDAwMDYwNTIzNDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDIwMDAwMDAwMzdmYThjN2UwYzhhZDlmMDlmOTE3OWI0MmI3N2U5NGE0ODdjM2RmNzU4ZDRiYTUzOGY3NzIzMzNjYTdiZjM2NjhhMmZlMzY2NDg0MzhjNzlkOWI2Yjc3YjU2ZWZmYjg2MGVhYTQzMGUwZTMwYzRlMzkyZjU5Y2QwODAwMDAwMDAxMDAwMDAwMDkwMDAwMDAwMTc1MDA3NmU2N2Q5NzIwMjgzYTcxYzZlN2E5YTg4ZmY2NjI2MDhmZWZkZDNmMzE2ZjEyMTE5NTdjYTE4NzNlZWUzZWU0YTc0YjQ2OGJkYTY2MTc2YTNlNWQzYWI1NGQ0M2E4YzBiZTEyMzQ4ZjI1MWEzMDkzYzE2ZDlkYjAwY2QwMDFjMzFlOWMxNSc7XG4gICAgICBjb25zdCBleHBlY3RlZFNlbmRlckFkZHJlc3MgPSAnMHgyYTk2MDI1YWQ1MDZiOWZiYjkwMjNmYmRjMTY2NWM3ZjdkN2M5MjNmJztcblxuICAgICAgY29uc3QgZmFjdG9yeSA9IG5ldyBUcmFuc2FjdGlvbkJ1aWxkZXJGYWN0b3J5KGNvaW5zLmdldCgndGZscnAnKSk7XG4gICAgICBjb25zdCB0eG4gPSAoYXdhaXQgZmFjdG9yeS5mcm9tKHR4KS5idWlsZCgpKSBhcyBUcmFuc2FjdGlvbjtcbiAgICAgIGNvbnN0IHNpZ25hYmxlUGF5bG9hZCA9IHR4bi5zaWduYWJsZVBheWxvYWQ7XG4gICAgICBjb25zdCBzaWduYXR1cmVzID0gdHhuLnNpZ25hdHVyZTtcbiAgICAgIGNvbnN0IHNpZyA9IEJ1ZmZlci5mcm9tKHV0aWxzLnJlbW92ZUhleFByZWZpeChzaWduYXR1cmVzWzBdKSwgJ2hleCcpO1xuXG4gICAgICAvLyBSZWNvdmVyIHB1YmxpYyBrZXkgZnJvbSBzaWduYXR1cmUgKHNpZ25hYmxlUGF5bG9hZCBpcyBhbHJlYWR5IFNIQTI1NiBoYXNoZWQpXG4gICAgICBjb25zdCByZWNvdmVyZWRQdWJLZXkgPSB1dGlscy5yZWNvdmVyeVNpZ25hdHVyZShzaWduYWJsZVBheWxvYWQsIHNpZyk7XG5cbiAgICAgIC8vIEdldCB0aGUgc2VuZGVyIGFkZHJlc3MgZnJvbSB0aGUgdHJhbnNhY3Rpb24gaW5wdXRzXG4gICAgICBjb25zdCB0eElucHV0cyA9IHR4bi5pbnB1dHM7XG4gICAgICBjb25zdCBzZW5kZXJBZGRyZXNzRnJvbVR4ID0gdHhJbnB1dHNbMF0uYWRkcmVzcy50b0xvd2VyQ2FzZSgpO1xuXG4gICAgICAvLyBWZXJpZnkgc2VuZGVyIGFkZHJlc3MgbWF0Y2hlcyBleHBlY3RlZFxuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKFxuICAgICAgICBzZW5kZXJBZGRyZXNzRnJvbVR4LFxuICAgICAgICBleHBlY3RlZFNlbmRlckFkZHJlc3MudG9Mb3dlckNhc2UoKSxcbiAgICAgICAgJ1RyYW5zYWN0aW9uIHNlbmRlciBhZGRyZXNzIGRvZXMgbm90IG1hdGNoIGV4cGVjdGVkJ1xuICAgICAgKTtcblxuICAgICAgLy8gRGVyaXZlIGFkZHJlc3MgZnJvbSByZWNvdmVyZWQgcHVibGljIGtleVxuICAgICAgY29uc3QgZGVyaXZlZEV2bUFkZHJlc3MgPVxuICAgICAgICAnMHgnICsgQnVmZmVyLmZyb20obmV3IEFkZHJlc3Moc2VjcDI1NmsxLnB1YmxpY0tleVRvRXRoQWRkcmVzcyhyZWNvdmVyZWRQdWJLZXkpKS50b0J5dGVzKCkpLnRvU3RyaW5nKCdoZXgnKTtcblxuICAgICAgLy8gVmVyaWZ5IHRoZSByZWNvdmVyZWQgcHVibGljIGtleSBtYXRjaGVzIHRoZSBzZW5kZXJcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChcbiAgICAgICAgZGVyaXZlZEV2bUFkZHJlc3MudG9Mb3dlckNhc2UoKSxcbiAgICAgICAgc2VuZGVyQWRkcmVzc0Zyb21UeCxcbiAgICAgICAgJ1JlY292ZXJlZCBwdWJsaWMga2V5IGRvZXMgbm90IG1hdGNoIHNlbmRlciBhZGRyZXNzJ1xuICAgICAgKTtcblxuICAgICAgLy8gQWxzbyB2ZXJpZnkgc2lnbmF0dXJlIHZhbGlkaXR5XG4gICAgICBjb25zdCBzaWdPbmx5ID0gc2lnLnNsaWNlKDAsIDY0KTtcbiAgICAgIGNvbnN0IGlzVmFsaWQgPSB1dGlscy52ZXJpZnlTaWduYXR1cmUoc2lnbmFibGVQYXlsb2FkLCBzaWdPbmx5LCByZWNvdmVyZWRQdWJLZXkpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKGlzVmFsaWQsIHRydWUsICdTaWduYXR1cmUgdmVyaWZpY2F0aW9uIGZhaWxlZCcpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnaXNUcmFuc2FjdGlvbk9mJywgZnVuY3Rpb24gKCkge1xuICAgIGNvbnN0IGZhY3RvcnkgPSBuZXcgVHJhbnNhY3Rpb25CdWlsZGVyRmFjdG9yeShjb2lucy5nZXQoJ3RmbHJwJykpO1xuICAgIGNvbnN0IHV0aWxzSW5zdGFuY2UgPSBuZXcgVXRpbHMoKTtcbiAgICBjb25zdCB0ZXN0bmV0TmV0d29yayA9IGNvaW5zLmdldCgndGZscnAnKS5uZXR3b3JrIGFzIEZsYXJlTmV0d29yaztcbiAgICBjb25zdCBwQ2hhaW5CbG9ja2NoYWluSWRIZXggPSBCdWZmZXIuZnJvbSh1dGlsc0luc3RhbmNlLmNiNThEZWNvZGUodGVzdG5ldE5ldHdvcmsuYmxvY2tjaGFpbklEKSkudG9TdHJpbmcoJ2hleCcpO1xuICAgIGNvbnN0IGNDaGFpbkJsb2NrY2hhaW5JZEhleCA9IEJ1ZmZlci5mcm9tKHV0aWxzSW5zdGFuY2UuY2I1OERlY29kZSh0ZXN0bmV0TmV0d29yay5jQ2hhaW5CbG9ja2NoYWluSUQpKS50b1N0cmluZyhcbiAgICAgICdoZXgnXG4gICAgKTtcblxuICAgIGl0KCdzaG91bGQgcmV0dXJuIHRydWUgZm9yIEltcG9ydCBpbiBQIHRyYW5zYWN0aW9uIHdpdGggbWF0Y2hpbmcgUC1jaGFpbiBibG9ja2NoYWluIElEJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgdHhCdWlsZGVyID0gZmFjdG9yeVxuICAgICAgICAuZ2V0SW1wb3J0SW5QQnVpbGRlcigpXG4gICAgICAgIC50aHJlc2hvbGQoSU1QT1JUX0lOX1AudGhyZXNob2xkKVxuICAgICAgICAubG9ja3RpbWUoSU1QT1JUX0lOX1AubG9ja3RpbWUpXG4gICAgICAgIC5mcm9tUHViS2V5KElNUE9SVF9JTl9QLnBBZGRyZXNzZXMpXG4gICAgICAgIC5leHRlcm5hbENoYWluSWQoSU1QT1JUX0lOX1Auc291cmNlQ2hhaW5JZClcbiAgICAgICAgLmZlZShJTVBPUlRfSU5fUC5mZWUpXG4gICAgICAgIC51dHhvcyhJTVBPUlRfSU5fUC5vdXRwdXRzKTtcblxuICAgICAgY29uc3QgdHggPSAoYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCkpIGFzIFRyYW5zYWN0aW9uO1xuICAgICAgY29uc3QgZmxhcmVUcmFuc2FjdGlvbiA9IHR4LmdldEZsYXJlVHJhbnNhY3Rpb24oKTtcblxuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHV0aWxzSW5zdGFuY2UuaXNUcmFuc2FjdGlvbk9mKGZsYXJlVHJhbnNhY3Rpb24sIHBDaGFpbkJsb2NrY2hhaW5JZEhleCksIHRydWUpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCByZXR1cm4gZmFsc2UgZm9yIEltcG9ydCBpbiBQIHRyYW5zYWN0aW9uIHdpdGggbm9uLW1hdGNoaW5nIEMtY2hhaW4gYmxvY2tjaGFpbiBJRCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHR4QnVpbGRlciA9IGZhY3RvcnlcbiAgICAgICAgLmdldEltcG9ydEluUEJ1aWxkZXIoKVxuICAgICAgICAudGhyZXNob2xkKElNUE9SVF9JTl9QLnRocmVzaG9sZClcbiAgICAgICAgLmxvY2t0aW1lKElNUE9SVF9JTl9QLmxvY2t0aW1lKVxuICAgICAgICAuZnJvbVB1YktleShJTVBPUlRfSU5fUC5wQWRkcmVzc2VzKVxuICAgICAgICAuZXh0ZXJuYWxDaGFpbklkKElNUE9SVF9JTl9QLnNvdXJjZUNoYWluSWQpXG4gICAgICAgIC5mZWUoSU1QT1JUX0lOX1AuZmVlKVxuICAgICAgICAudXR4b3MoSU1QT1JUX0lOX1Aub3V0cHV0cyk7XG5cbiAgICAgIGNvbnN0IHR4ID0gKGF3YWl0IHR4QnVpbGRlci5idWlsZCgpKSBhcyBUcmFuc2FjdGlvbjtcbiAgICAgIGNvbnN0IGZsYXJlVHJhbnNhY3Rpb24gPSB0eC5nZXRGbGFyZVRyYW5zYWN0aW9uKCk7XG5cbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCh1dGlsc0luc3RhbmNlLmlzVHJhbnNhY3Rpb25PZihmbGFyZVRyYW5zYWN0aW9uLCBjQ2hhaW5CbG9ja2NoYWluSWRIZXgpLCBmYWxzZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJldHVybiB0cnVlIGZvciBFeHBvcnQgaW4gUCB0cmFuc2FjdGlvbiB3aXRoIG1hdGNoaW5nIFAtY2hhaW4gYmxvY2tjaGFpbiBJRCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHR4QnVpbGRlciA9IGZhY3RvcnlcbiAgICAgICAgLmdldEV4cG9ydEluUEJ1aWxkZXIoKVxuICAgICAgICAudGhyZXNob2xkKEVYUE9SVF9JTl9QLnRocmVzaG9sZClcbiAgICAgICAgLmxvY2t0aW1lKEVYUE9SVF9JTl9QLmxvY2t0aW1lKVxuICAgICAgICAuZnJvbVB1YktleShFWFBPUlRfSU5fUC5wQWRkcmVzc2VzKVxuICAgICAgICAuZXh0ZXJuYWxDaGFpbklkKEVYUE9SVF9JTl9QLnNvdXJjZUNoYWluSWQpXG4gICAgICAgIC5mZWUoRVhQT1JUX0lOX1AuZmVlKVxuICAgICAgICAuYW1vdW50KEVYUE9SVF9JTl9QLmFtb3VudClcbiAgICAgICAgLnV0eG9zKEVYUE9SVF9JTl9QLm91dHB1dHMpO1xuXG4gICAgICBjb25zdCB0eCA9IChhd2FpdCB0eEJ1aWxkZXIuYnVpbGQoKSkgYXMgVHJhbnNhY3Rpb247XG4gICAgICBjb25zdCBmbGFyZVRyYW5zYWN0aW9uID0gdHguZ2V0RmxhcmVUcmFuc2FjdGlvbigpO1xuXG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwodXRpbHNJbnN0YW5jZS5pc1RyYW5zYWN0aW9uT2YoZmxhcmVUcmFuc2FjdGlvbiwgcENoYWluQmxvY2tjaGFpbklkSGV4KSwgdHJ1ZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJldHVybiBmYWxzZSBmb3IgRXhwb3J0IGluIFAgdHJhbnNhY3Rpb24gd2l0aCBub24tbWF0Y2hpbmcgQy1jaGFpbiBibG9ja2NoYWluIElEJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgdHhCdWlsZGVyID0gZmFjdG9yeVxuICAgICAgICAuZ2V0RXhwb3J0SW5QQnVpbGRlcigpXG4gICAgICAgIC50aHJlc2hvbGQoRVhQT1JUX0lOX1AudGhyZXNob2xkKVxuICAgICAgICAubG9ja3RpbWUoRVhQT1JUX0lOX1AubG9ja3RpbWUpXG4gICAgICAgIC5mcm9tUHViS2V5KEVYUE9SVF9JTl9QLnBBZGRyZXNzZXMpXG4gICAgICAgIC5leHRlcm5hbENoYWluSWQoRVhQT1JUX0lOX1Auc291cmNlQ2hhaW5JZClcbiAgICAgICAgLmZlZShFWFBPUlRfSU5fUC5mZWUpXG4gICAgICAgIC5hbW91bnQoRVhQT1JUX0lOX1AuYW1vdW50KVxuICAgICAgICAudXR4b3MoRVhQT1JUX0lOX1Aub3V0cHV0cyk7XG5cbiAgICAgIGNvbnN0IHR4ID0gKGF3YWl0IHR4QnVpbGRlci5idWlsZCgpKSBhcyBUcmFuc2FjdGlvbjtcbiAgICAgIGNvbnN0IGZsYXJlVHJhbnNhY3Rpb24gPSB0eC5nZXRGbGFyZVRyYW5zYWN0aW9uKCk7XG5cbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCh1dGlsc0luc3RhbmNlLmlzVHJhbnNhY3Rpb25PZihmbGFyZVRyYW5zYWN0aW9uLCBjQ2hhaW5CbG9ja2NoYWluSWRIZXgpLCBmYWxzZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJldHVybiB0cnVlIGZvciBJbXBvcnQgaW4gQyB0cmFuc2FjdGlvbiB3aXRoIG1hdGNoaW5nIEMtY2hhaW4gYmxvY2tjaGFpbiBJRCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHR4QnVpbGRlciA9IGZhY3RvcnlcbiAgICAgICAgLmdldEltcG9ydEluQ0J1aWxkZXIoKVxuICAgICAgICAudGhyZXNob2xkKElNUE9SVF9JTl9DLnRocmVzaG9sZClcbiAgICAgICAgLmxvY2t0aW1lKElNUE9SVF9JTl9DLmxvY2t0aW1lKVxuICAgICAgICAuZnJvbVB1YktleShJTVBPUlRfSU5fQy5wQWRkcmVzc2VzKVxuICAgICAgICAuZXh0ZXJuYWxDaGFpbklkKElNUE9SVF9JTl9DLnNvdXJjZUNoYWluSWQpXG4gICAgICAgIC5mZWVSYXRlKElNUE9SVF9JTl9DLmZlZSlcbiAgICAgICAgLnRvKElNUE9SVF9JTl9DLnRvKVxuICAgICAgICAudXR4b3MoSU1QT1JUX0lOX0Mub3V0cHV0cyk7XG5cbiAgICAgIGNvbnN0IHR4ID0gKGF3YWl0IHR4QnVpbGRlci5idWlsZCgpKSBhcyBUcmFuc2FjdGlvbjtcbiAgICAgIGNvbnN0IGZsYXJlVHJhbnNhY3Rpb24gPSB0eC5nZXRGbGFyZVRyYW5zYWN0aW9uKCk7XG5cbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCh1dGlsc0luc3RhbmNlLmlzVHJhbnNhY3Rpb25PZihmbGFyZVRyYW5zYWN0aW9uLCBjQ2hhaW5CbG9ja2NoYWluSWRIZXgpLCB0cnVlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmV0dXJuIGZhbHNlIGZvciBJbXBvcnQgaW4gQyB0cmFuc2FjdGlvbiB3aXRoIG5vbi1tYXRjaGluZyBQLWNoYWluIGJsb2NrY2hhaW4gSUQnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB0eEJ1aWxkZXIgPSBmYWN0b3J5XG4gICAgICAgIC5nZXRJbXBvcnRJbkNCdWlsZGVyKClcbiAgICAgICAgLnRocmVzaG9sZChJTVBPUlRfSU5fQy50aHJlc2hvbGQpXG4gICAgICAgIC5sb2NrdGltZShJTVBPUlRfSU5fQy5sb2NrdGltZSlcbiAgICAgICAgLmZyb21QdWJLZXkoSU1QT1JUX0lOX0MucEFkZHJlc3NlcylcbiAgICAgICAgLmV4dGVybmFsQ2hhaW5JZChJTVBPUlRfSU5fQy5zb3VyY2VDaGFpbklkKVxuICAgICAgICAuZmVlUmF0ZShJTVBPUlRfSU5fQy5mZWUpXG4gICAgICAgIC50byhJTVBPUlRfSU5fQy50bylcbiAgICAgICAgLnV0eG9zKElNUE9SVF9JTl9DLm91dHB1dHMpO1xuXG4gICAgICBjb25zdCB0eCA9IChhd2FpdCB0eEJ1aWxkZXIuYnVpbGQoKSkgYXMgVHJhbnNhY3Rpb247XG4gICAgICBjb25zdCBmbGFyZVRyYW5zYWN0aW9uID0gdHguZ2V0RmxhcmVUcmFuc2FjdGlvbigpO1xuXG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwodXRpbHNJbnN0YW5jZS5pc1RyYW5zYWN0aW9uT2YoZmxhcmVUcmFuc2FjdGlvbiwgcENoYWluQmxvY2tjaGFpbklkSGV4KSwgZmFsc2UpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCByZXR1cm4gdHJ1ZSBmb3IgRXhwb3J0IGluIEMgdHJhbnNhY3Rpb24gd2l0aCBtYXRjaGluZyBDLWNoYWluIGJsb2NrY2hhaW4gSUQnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB0eEJ1aWxkZXIgPSBmYWN0b3J5XG4gICAgICAgIC5nZXRFeHBvcnRJbkNCdWlsZGVyKClcbiAgICAgICAgLmZyb21QdWJLZXkoRVhQT1JUX0lOX0MuY0hleEFkZHJlc3MpXG4gICAgICAgIC5ub25jZShFWFBPUlRfSU5fQy5ub25jZSlcbiAgICAgICAgLmFtb3VudChFWFBPUlRfSU5fQy5hbW91bnQpXG4gICAgICAgIC50aHJlc2hvbGQoRVhQT1JUX0lOX0MudGhyZXNob2xkKVxuICAgICAgICAubG9ja3RpbWUoRVhQT1JUX0lOX0MubG9ja3RpbWUpXG4gICAgICAgIC50byhFWFBPUlRfSU5fQy5wQWRkcmVzc2VzKVxuICAgICAgICAuZmVlUmF0ZShFWFBPUlRfSU5fQy5mZWUpO1xuXG4gICAgICBjb25zdCB0eCA9IChhd2FpdCB0eEJ1aWxkZXIuYnVpbGQoKSkgYXMgVHJhbnNhY3Rpb247XG4gICAgICBjb25zdCBmbGFyZVRyYW5zYWN0aW9uID0gdHguZ2V0RmxhcmVUcmFuc2FjdGlvbigpO1xuXG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwodXRpbHNJbnN0YW5jZS5pc1RyYW5zYWN0aW9uT2YoZmxhcmVUcmFuc2FjdGlvbiwgY0NoYWluQmxvY2tjaGFpbklkSGV4KSwgdHJ1ZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJldHVybiBmYWxzZSBmb3IgRXhwb3J0IGluIEMgdHJhbnNhY3Rpb24gd2l0aCBub24tbWF0Y2hpbmcgUC1jaGFpbiBibG9ja2NoYWluIElEJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgdHhCdWlsZGVyID0gZmFjdG9yeVxuICAgICAgICAuZ2V0RXhwb3J0SW5DQnVpbGRlcigpXG4gICAgICAgIC5mcm9tUHViS2V5KEVYUE9SVF9JTl9DLmNIZXhBZGRyZXNzKVxuICAgICAgICAubm9uY2UoRVhQT1JUX0lOX0Mubm9uY2UpXG4gICAgICAgIC5hbW91bnQoRVhQT1JUX0lOX0MuYW1vdW50KVxuICAgICAgICAudGhyZXNob2xkKEVYUE9SVF9JTl9DLnRocmVzaG9sZClcbiAgICAgICAgLmxvY2t0aW1lKEVYUE9SVF9JTl9DLmxvY2t0aW1lKVxuICAgICAgICAudG8oRVhQT1JUX0lOX0MucEFkZHJlc3NlcylcbiAgICAgICAgLmZlZVJhdGUoRVhQT1JUX0lOX0MuZmVlKTtcblxuICAgICAgY29uc3QgdHggPSAoYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCkpIGFzIFRyYW5zYWN0aW9uO1xuICAgICAgY29uc3QgZmxhcmVUcmFuc2FjdGlvbiA9IHR4LmdldEZsYXJlVHJhbnNhY3Rpb24oKTtcblxuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHV0aWxzSW5zdGFuY2UuaXNUcmFuc2FjdGlvbk9mKGZsYXJlVHJhbnNhY3Rpb24sIHBDaGFpbkJsb2NrY2hhaW5JZEhleCksIGZhbHNlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmV0dXJuIGZhbHNlIGZvciBpbnZhbGlkIGJsb2NrY2hhaW4gSUQnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB0eEJ1aWxkZXIgPSBmYWN0b3J5XG4gICAgICAgIC5nZXRJbXBvcnRJblBCdWlsZGVyKClcbiAgICAgICAgLnRocmVzaG9sZChJTVBPUlRfSU5fUC50aHJlc2hvbGQpXG4gICAgICAgIC5sb2NrdGltZShJTVBPUlRfSU5fUC5sb2NrdGltZSlcbiAgICAgICAgLmZyb21QdWJLZXkoSU1QT1JUX0lOX1AucEFkZHJlc3NlcylcbiAgICAgICAgLmV4dGVybmFsQ2hhaW5JZChJTVBPUlRfSU5fUC5zb3VyY2VDaGFpbklkKVxuICAgICAgICAuZmVlKElNUE9SVF9JTl9QLmZlZSlcbiAgICAgICAgLnV0eG9zKElNUE9SVF9JTl9QLm91dHB1dHMpO1xuXG4gICAgICBjb25zdCB0eCA9IChhd2FpdCB0eEJ1aWxkZXIuYnVpbGQoKSkgYXMgVHJhbnNhY3Rpb247XG4gICAgICBjb25zdCBmbGFyZVRyYW5zYWN0aW9uID0gdHguZ2V0RmxhcmVUcmFuc2FjdGlvbigpO1xuXG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwodXRpbHNJbnN0YW5jZS5pc1RyYW5zYWN0aW9uT2YoZmxhcmVUcmFuc2FjdGlvbiwgJ2ludmFsaWRibG9ja2NoYWluaWQnKSwgZmFsc2UpO1xuICAgIH0pO1xuICB9KTtcbn0pO1xuIl19