@bitgo-beta/sdk-coin-flrp 1.0.1-beta.39 → 1.0.1-beta.390

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 (122) 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 +43 -0
  8. package/dist/src/lib/ExportInCTxBuilder.d.ts.map +1 -0
  9. package/dist/src/lib/ExportInCTxBuilder.js +150 -0
  10. package/dist/src/lib/ExportInPTxBuilder.d.ts +29 -0
  11. package/dist/src/lib/ExportInPTxBuilder.d.ts.map +1 -0
  12. package/dist/src/lib/ExportInPTxBuilder.js +180 -0
  13. package/dist/src/lib/ImportInCTxBuilder.d.ts +35 -0
  14. package/dist/src/lib/ImportInCTxBuilder.d.ts.map +1 -0
  15. package/dist/src/lib/ImportInCTxBuilder.js +181 -0
  16. package/dist/src/lib/ImportInPTxBuilder.d.ts +48 -0
  17. package/dist/src/lib/ImportInPTxBuilder.d.ts.map +1 -0
  18. package/dist/src/lib/ImportInPTxBuilder.js +223 -0
  19. package/dist/src/lib/atomicInCTransactionBuilder.d.ts +12 -16
  20. package/dist/src/lib/atomicInCTransactionBuilder.d.ts.map +1 -1
  21. package/dist/src/lib/atomicInCTransactionBuilder.js +30 -41
  22. package/dist/src/lib/atomicTransactionBuilder.d.ts +81 -69
  23. package/dist/src/lib/atomicTransactionBuilder.d.ts.map +1 -1
  24. package/dist/src/lib/atomicTransactionBuilder.js +189 -212
  25. package/dist/src/lib/iface.d.ts +65 -57
  26. package/dist/src/lib/iface.d.ts.map +1 -1
  27. package/dist/src/lib/iface.js +20 -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 +41 -0
  35. package/dist/src/lib/permissionlessValidatorTxBuilder.d.ts.map +1 -0
  36. package/dist/src/lib/permissionlessValidatorTxBuilder.js +126 -0
  37. package/dist/src/lib/transaction.d.ts +30 -66
  38. package/dist/src/lib/transaction.d.ts.map +1 -1
  39. package/dist/src/lib/transaction.js +338 -199
  40. package/dist/src/lib/transactionBuilder.d.ts +115 -0
  41. package/dist/src/lib/transactionBuilder.d.ts.map +1 -0
  42. package/dist/src/lib/transactionBuilder.js +228 -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 +106 -146
  47. package/dist/src/lib/utils.d.ts.map +1 -1
  48. package/dist/src/lib/utils.js +305 -321
  49. package/dist/test/resources/account.d.ts +81 -0
  50. package/dist/test/resources/account.d.ts.map +1 -0
  51. package/dist/test/resources/account.js +79 -0
  52. package/dist/test/resources/transactionData/exportInC.d.ts +50 -0
  53. package/dist/test/resources/transactionData/exportInC.d.ts.map +1 -0
  54. package/dist/test/resources/transactionData/exportInC.js +58 -0
  55. package/dist/test/resources/transactionData/exportInP.d.ts +60 -0
  56. package/dist/test/resources/transactionData/exportInP.d.ts.map +1 -0
  57. package/dist/test/resources/transactionData/exportInP.js +101 -0
  58. package/dist/test/resources/transactionData/importInC.d.ts +56 -0
  59. package/dist/test/resources/transactionData/importInC.d.ts.map +1 -0
  60. package/dist/test/resources/transactionData/importInC.js +120 -0
  61. package/dist/test/resources/transactionData/importInP.d.ts +66 -0
  62. package/dist/test/resources/transactionData/importInP.d.ts.map +1 -0
  63. package/dist/test/resources/transactionData/importInP.js +84 -0
  64. package/dist/test/unit/flrp.js +449 -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 +193 -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 +191 -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 +204 -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 +312 -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/signatureIndex.d.ts +13 -0
  84. package/dist/test/unit/lib/signatureIndex.d.ts.map +1 -0
  85. package/dist/test/unit/lib/signatureIndex.js +591 -0
  86. package/dist/test/unit/lib/transactionBuilderFactory.d.ts +2 -0
  87. package/dist/test/unit/lib/transactionBuilderFactory.d.ts.map +1 -0
  88. package/dist/test/unit/lib/transactionBuilderFactory.js +60 -0
  89. package/dist/test/unit/lib/utils.js +601 -207
  90. package/dist/tsconfig.tsbuildinfo +1 -1
  91. package/package.json +19 -10
  92. package/.eslintignore +0 -5
  93. package/.eslintrc.json +0 -7
  94. package/.mocharc.yml +0 -8
  95. package/CHANGELOG.md +0 -0
  96. package/dist/src/iface.d.ts +0 -25
  97. package/dist/src/iface.d.ts.map +0 -1
  98. package/dist/src/iface.js +0 -3
  99. package/dist/src/lib/constants.d.ts +0 -11
  100. package/dist/src/lib/constants.d.ts.map +0 -1
  101. package/dist/src/lib/constants.js +0 -17
  102. package/dist/src/lib/errors.d.ts +0 -8
  103. package/dist/src/lib/errors.d.ts.map +0 -1
  104. package/dist/src/lib/errors.js +0 -19
  105. package/dist/src/lib/exportInCTxBuilder.d.ts +0 -77
  106. package/dist/src/lib/exportInCTxBuilder.d.ts.map +0 -1
  107. package/dist/src/lib/exportInCTxBuilder.js +0 -170
  108. package/dist/src/lib/exportInPTxBuilder.d.ts +0 -30
  109. package/dist/src/lib/exportInPTxBuilder.d.ts.map +0 -1
  110. package/dist/src/lib/exportInPTxBuilder.js +0 -56
  111. package/dist/test/unit/lib/atomicTransactionBuilder.d.ts +0 -2
  112. package/dist/test/unit/lib/atomicTransactionBuilder.d.ts.map +0 -1
  113. package/dist/test/unit/lib/atomicTransactionBuilder.js +0 -222
  114. package/dist/test/unit/lib/exportTxBuilder.d.ts +0 -2
  115. package/dist/test/unit/lib/exportTxBuilder.d.ts.map +0 -1
  116. package/dist/test/unit/lib/exportTxBuilder.js +0 -45
  117. package/dist/test/unit/lib/transaction.d.ts +0 -2
  118. package/dist/test/unit/lib/transaction.d.ts.map +0 -1
  119. package/dist/test/unit/lib/transaction.js +0 -460
  120. package/dist/test/unit/smoke.d.ts +0 -2
  121. package/dist/test/unit/smoke.d.ts.map +0 -1
  122. package/dist/test/unit/smoke.js +0 -23
@@ -34,253 +34,647 @@ 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
  });
53
+ describe('decodedToUtxo', function () {
54
+ const assetId = 'fxMAKpBQQpFedrUhWMsDYfCUJxdUw4mneTczKBzNg3rc2JUub';
55
+ it('should convert DecodedUtxoObj to FlareJS Utxo', function () {
56
+ const decodedUtxo = {
57
+ outputID: 7,
58
+ amount: '50000000',
59
+ txid: '2XJ1MptpmBWVFSzCz44jauGLoooSFShZJM8aykSL1dfVHehFjn',
60
+ threshold: 2,
61
+ addresses: [
62
+ 'P-costwo1xv5mulgpe5lt4tnx2ntnylwe79azu9vpja6lut',
63
+ 'P-costwo106gc5h5qswhye8e0pmthq4wzf0ekv5qppsrvpu',
64
+ 'P-costwo1cueygd7fd37g56s49k3rshqakhp6k8u3adzt6m',
65
+ ],
66
+ outputidx: '0',
67
+ locktime: '0',
68
+ };
69
+ const convertedUtxo = utils.decodedToUtxo(decodedUtxo, assetId);
70
+ assert.ok(convertedUtxo instanceof flarejs_1.Utxo);
71
+ assert.ok(convertedUtxo.utxoId, 'utxoId should exist');
72
+ assert.ok(convertedUtxo.assetId, 'assetId should exist');
73
+ assert.ok(convertedUtxo.output, 'output should exist');
74
+ const expectedTxIdHex = 'c87b0455de7ba1a7a3ca508f2df8d9f54488b486a8600aa207229678ee13bb84';
75
+ assert.strictEqual(Buffer.from(convertedUtxo.utxoId.txID.toBytes()).toString('hex'), expectedTxIdHex);
76
+ assert.strictEqual(Number(convertedUtxo.utxoId.outputIdx.value()), 0);
77
+ assert.strictEqual(convertedUtxo.output.amount().toString(), '50000000');
78
+ });
79
+ it('should convert array of DecodedUtxoObj to FlareJS Utxo array', function () {
80
+ const decodedUtxos = [
81
+ {
82
+ outputID: 7,
83
+ amount: '50000000',
84
+ txid: '2XJ1MptpmBWVFSzCz44jauGLoooSFShZJM8aykSL1dfVHehFjn',
85
+ threshold: 2,
86
+ addresses: [
87
+ 'P-costwo1xv5mulgpe5lt4tnx2ntnylwe79azu9vpja6lut',
88
+ 'P-costwo106gc5h5qswhye8e0pmthq4wzf0ekv5qppsrvpu',
89
+ 'P-costwo1cueygd7fd37g56s49k3rshqakhp6k8u3adzt6m',
90
+ ],
91
+ outputidx: '0',
92
+ locktime: '0',
93
+ },
94
+ ];
95
+ const convertedUtxos = utils.decodedToUtxos(decodedUtxos, assetId);
96
+ assert.strictEqual(convertedUtxos.length, 1);
97
+ assert.ok(convertedUtxos[0] instanceof flarejs_1.Utxo);
98
+ assert.strictEqual(convertedUtxos[0].output.amount().toString(), '50000000');
99
+ });
100
+ it('should handle locktime correctly', function () {
101
+ const decodedUtxo = {
102
+ outputID: 7,
103
+ amount: '100000000',
104
+ txid: '2XJ1MptpmBWVFSzCz44jauGLoooSFShZJM8aykSL1dfVHehFjn',
105
+ threshold: 2,
106
+ addresses: ['P-costwo1xv5mulgpe5lt4tnx2ntnylwe79azu9vpja6lut'],
107
+ outputidx: '1',
108
+ locktime: '1704067200',
109
+ };
110
+ const convertedUtxo = utils.decodedToUtxo(decodedUtxo, assetId);
111
+ const outputOwners = convertedUtxo.getOutputOwners();
112
+ assert.strictEqual(outputOwners.locktime.value().toString(), '1704067200');
113
+ });
114
+ });
45
115
  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);
116
+ it('should return true when all wallet addresses are in UTXO output addresses', function () {
117
+ const walletAddresses = [exportInC_1.EXPORT_IN_C.pAddresses[0], exportInC_1.EXPORT_IN_C.pAddresses[1]];
118
+ const utxoOutputAddresses = [...exportInC_1.EXPORT_IN_C.pAddresses];
119
+ assert.strictEqual(utils.includeIn(walletAddresses, utxoOutputAddresses), true);
50
120
  });
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);
121
+ it('should return false when some wallet addresses are not in UTXO output addresses', function () {
122
+ const walletAddresses = [exportInC_1.EXPORT_IN_C.pAddresses[0], account_1.ACCOUNT_3.address];
123
+ const utxoOutputAddresses = [exportInC_1.EXPORT_IN_C.pAddresses[0], exportInC_1.EXPORT_IN_C.pAddresses[1]];
124
+ assert.strictEqual(utils.includeIn(walletAddresses, utxoOutputAddresses), false);
55
125
  });
56
126
  it('should return true for empty wallet addresses', function () {
57
127
  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);
128
+ const utxoOutputAddresses = [exportInC_1.EXPORT_IN_C.pAddresses[0]];
129
+ assert.strictEqual(utils.includeIn(walletAddresses, utxoOutputAddresses), true);
65
130
  });
66
131
  });
67
132
  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
- });
133
+ it('should return true for valid mainnet P-chain address', function () {
134
+ assert.strictEqual(utils.isValidAddress(account_1.SEED_ACCOUNT.addressMainnet), true);
81
135
  });
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
- });
136
+ it('should return true for valid testnet P-chain address', function () {
137
+ assert.strictEqual(utils.isValidAddress(account_1.SEED_ACCOUNT.addressTestnet), true);
138
+ });
139
+ it('should return true for valid NodeID address', function () {
140
+ assert.strictEqual(utils.isValidAddress('NodeID-abc123xyz'), true);
141
+ });
142
+ it('should return true for array of valid addresses', function () {
143
+ assert.strictEqual(utils.isValidAddress(exportInC_1.EXPORT_IN_C.pAddresses), true);
144
+ });
145
+ it('should return true for tilde-separated addresses', function () {
146
+ const combined = exportInC_1.EXPORT_IN_C.pAddresses.join('~');
147
+ assert.strictEqual(utils.isValidAddress(combined), true);
148
+ });
149
+ it('should return false for invalid address format', function () {
150
+ assert.strictEqual(utils.isValidAddress('invalid'), false);
151
+ });
152
+ it('should return false for address without prefix', function () {
153
+ assert.strictEqual(utils.isValidAddress('flare1abc123'), false);
108
154
  });
109
155
  });
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');
156
+ describe('isValidBlockId', function () {
157
+ it('should return true for valid 32-byte hex block ID', function () {
158
+ assert.strictEqual(utils.isValidBlockId(account_1.SEED_ACCOUNT.privateKey), true); // 64 hex chars = 32 bytes
159
+ });
160
+ it('should return false for invalid length block ID', function () {
161
+ assert.strictEqual(utils.isValidBlockId(account_1.INVALID_SHORT_KEYPAIR_KEY), false);
115
162
  });
116
- it('should reject empty strings', function () {
117
- const result = utils['isValidAddressRegex']('');
118
- assert.strictEqual(result, false);
163
+ it('should return false for empty block ID', function () {
164
+ assert.strictEqual(utils.isValidBlockId(''), false);
119
165
  });
120
166
  });
121
- describe('isValidTransactionId', function () {
122
- it('should throw NotImplementedError', function () {
123
- assert.throws(() => utils.isValidTransactionId('txid123'), sdk_core_1.NotImplementedError, 'isValidTransactionId not implemented');
167
+ describe('isValidPublicKey', function () {
168
+ it('should return true for valid compressed public key starting with 03', function () {
169
+ assert.strictEqual(utils.isValidPublicKey(account_1.SEED_ACCOUNT.publicKey), true);
170
+ });
171
+ it('should return true for valid compressed public key starting with 02', function () {
172
+ assert.strictEqual(utils.isValidPublicKey(account_1.ACCOUNT_1.publicKey), true);
173
+ });
174
+ it('should return true for another valid compressed public key', function () {
175
+ assert.strictEqual(utils.isValidPublicKey(account_1.ACCOUNT_2.publicKey), true);
176
+ });
177
+ it('should return true for valid xpub', function () {
178
+ assert.strictEqual(utils.isValidPublicKey(account_1.SEED_ACCOUNT.xPublicKey), true);
179
+ });
180
+ it('should return true for ACCOUNT_1 xpub', function () {
181
+ assert.strictEqual(utils.isValidPublicKey(account_1.ACCOUNT_1.xPublicKey), true);
182
+ });
183
+ it('should return false for invalid short public key', function () {
184
+ assert.strictEqual(utils.isValidPublicKey(account_1.INVALID_SHORT_KEYPAIR_KEY), false);
185
+ });
186
+ it('should return false for compressed key with wrong prefix', function () {
187
+ const invalidKey = '05' + account_1.SEED_ACCOUNT.privateKey;
188
+ assert.strictEqual(utils.isValidPublicKey(invalidKey), false);
189
+ });
190
+ it('should return false for non-hex public key', function () {
191
+ const invalidKey = 'zz' + account_1.SEED_ACCOUNT.privateKey;
192
+ assert.strictEqual(utils.isValidPublicKey(invalidKey), false);
124
193
  });
125
194
  });
126
- describe('isValidSignature', function () {
127
- it('should throw NotImplementedError', function () {
128
- assert.throws(() => utils.isValidSignature('signature123'), sdk_core_1.NotImplementedError, 'isValidSignature not implemented');
195
+ describe('isValidPrivateKey', function () {
196
+ it('should return true for valid 64-char hex private key', function () {
197
+ assert.strictEqual(utils.isValidPrivateKey(account_1.SEED_ACCOUNT.privateKey), true);
198
+ });
199
+ it('should return true for ACCOUNT_1 private key', function () {
200
+ assert.strictEqual(utils.isValidPrivateKey(account_1.ACCOUNT_1.privateKey), true);
201
+ });
202
+ it('should return true for ACCOUNT_2 private key', function () {
203
+ assert.strictEqual(utils.isValidPrivateKey(account_1.ACCOUNT_2.privateKey), true);
204
+ });
205
+ it('should return true for valid xprv', function () {
206
+ assert.strictEqual(utils.isValidPrivateKey(account_1.SEED_ACCOUNT.xPrivateKey), true);
207
+ });
208
+ it('should return true for 66-char private key ending with 01', function () {
209
+ const extendedKey = account_1.SEED_ACCOUNT.privateKey + '01';
210
+ assert.strictEqual(utils.isValidPrivateKey(extendedKey), true);
211
+ });
212
+ it('should return false for 66-char private key not ending with 01', function () {
213
+ assert.strictEqual(utils.isValidPrivateKey(account_1.INVALID_LONG_KEYPAIR_PRV), false);
214
+ });
215
+ it('should return false for invalid short private key', function () {
216
+ assert.strictEqual(utils.isValidPrivateKey(account_1.INVALID_SHORT_KEYPAIR_KEY), false);
217
+ });
218
+ it('should return false for non-hex private key', function () {
219
+ const invalidKey = 'zz' + account_1.SEED_ACCOUNT.privateKey.slice(2);
220
+ assert.strictEqual(utils.isValidPrivateKey(invalidKey), false);
129
221
  });
130
222
  });
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');
223
+ describe('allHexChars', function () {
224
+ it('should return true for valid private key hex', function () {
225
+ assert.strictEqual(utils.allHexChars(account_1.SEED_ACCOUNT.privateKey), true);
226
+ });
227
+ it('should return true for valid public key hex', function () {
228
+ assert.strictEqual(utils.allHexChars(account_1.SEED_ACCOUNT.publicKey), true);
229
+ });
230
+ it('should return true for hex string with 0x prefix', function () {
231
+ assert.strictEqual(utils.allHexChars(exportInC_1.EXPORT_IN_C.cHexAddress), true);
232
+ });
233
+ it('should return true for valid signature hex', function () {
234
+ assert.strictEqual(utils.allHexChars(account_1.SEED_ACCOUNT.signature), true);
235
+ });
236
+ it('should return false for non-hex characters', function () {
237
+ assert.strictEqual(utils.allHexChars('ghijkl'), false);
238
+ });
239
+ it('should return false for empty string', function () {
240
+ assert.strictEqual(utils.allHexChars(''), false);
241
+ });
242
+ });
243
+ describe('createSignature and verifySignature', function () {
244
+ it('should create a valid 65-byte signature', function () {
245
+ const message = Buffer.from(account_1.SEED_ACCOUNT.message, 'utf8');
246
+ const privateKey = Buffer.from(account_1.SEED_ACCOUNT.privateKey, 'hex');
136
247
  const signature = utils.createSignature(network, message, privateKey);
137
248
  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/);
249
+ assert.strictEqual(signature.length, 65);
154
250
  });
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
251
+ it('should verify a valid signature', function () {
252
+ const message = Buffer.from(account_1.SEED_ACCOUNT.message, 'utf8');
253
+ const privateKey = Buffer.from(account_1.SEED_ACCOUNT.privateKey, 'hex');
254
+ const publicKey = Buffer.from(account_1.SEED_ACCOUNT.publicKey, 'hex');
162
255
  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);
256
+ const sigOnly = signature.slice(0, 64);
257
+ const messageHash = utils.sha256(message);
258
+ const isValid = utils.verifySignature(messageHash, sigOnly, publicKey);
259
+ assert.strictEqual(isValid, true);
173
260
  });
174
261
  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);
262
+ const message = Buffer.from(account_1.SEED_ACCOUNT.message, 'utf8');
263
+ const publicKey = Buffer.from(account_1.SEED_ACCOUNT.publicKey, 'hex');
264
+ const invalidSignature = Buffer.alloc(64);
265
+ const messageHash = utils.sha256(message);
266
+ const isValid = utils.verifySignature(messageHash, invalidSignature, publicKey);
267
+ assert.strictEqual(isValid, false);
268
+ });
269
+ it('should create signature with ACCOUNT_1 keys', function () {
270
+ const message = Buffer.from(account_1.SEED_ACCOUNT.message, 'utf8');
271
+ const privateKey = Buffer.from(account_1.ACCOUNT_1.privateKey, 'hex');
272
+ const signature = utils.createSignature(network, message, privateKey);
273
+ assert.ok(signature instanceof Buffer);
274
+ assert.strictEqual(signature.length, 65);
275
+ });
276
+ });
277
+ describe('createNewSig', function () {
278
+ it('should create a signature from valid signature hex string', function () {
279
+ const sig = utils.createNewSig(account_1.SEED_ACCOUNT.signature);
280
+ assert.ok(sig);
281
+ });
282
+ it('should create a signature from export signature hex', function () {
283
+ const sigHex = utils.removeHexPrefix(exportInC_1.EXPORT_IN_C.signature[0]);
284
+ const sig = utils.createNewSig(sigHex);
285
+ assert.ok(sig);
286
+ });
287
+ it('should pad short hex strings', function () {
288
+ const sigHex = account_1.INVALID_SHORT_KEYPAIR_KEY;
289
+ const sig = utils.createNewSig(sigHex);
290
+ assert.ok(sig);
291
+ });
292
+ });
293
+ describe('createEmptySigWithAddress and getAddressFromEmptySig', function () {
294
+ it('should create empty signature with embedded C-chain address', function () {
295
+ const addressHex = utils.removeHexPrefix(exportInC_1.EXPORT_IN_C.cHexAddress);
296
+ const sig = utils.createEmptySigWithAddress(addressHex);
297
+ assert.ok(sig);
298
+ });
299
+ it('should extract embedded address from empty signature', function () {
300
+ const addressHex = utils.removeHexPrefix(exportInC_1.EXPORT_IN_C.cHexAddress).toLowerCase();
301
+ const sig = utils.createEmptySigWithAddress(addressHex);
302
+ // Get signature bytes and convert to hex
303
+ const sigBytes = sig.toBytes();
304
+ const sigHex = Buffer.from(sigBytes).toString('hex');
305
+ const extractedAddress = utils.getAddressFromEmptySig(sigHex);
306
+ assert.strictEqual(extractedAddress, addressHex);
307
+ });
308
+ it('should handle 0x prefixed address', function () {
309
+ const sig = utils.createEmptySigWithAddress(exportInC_1.EXPORT_IN_C.cHexAddress);
310
+ assert.ok(sig);
311
+ });
312
+ it('should return empty string for short signature', function () {
313
+ const shortSig = account_1.SEED_ACCOUNT.privateKey; // 64 chars, less than 130
314
+ assert.strictEqual(utils.getAddressFromEmptySig(shortSig), '');
315
+ });
316
+ });
317
+ describe('sha256', function () {
318
+ it('should compute SHA256 hash of message', function () {
319
+ const data = Buffer.from(account_1.SEED_ACCOUNT.message, 'utf8');
320
+ const hash = utils.sha256(data);
321
+ assert.ok(hash instanceof Buffer);
322
+ assert.strictEqual(hash.length, 32);
323
+ });
324
+ it('should produce consistent hash for same input', function () {
325
+ const data = Buffer.from(account_1.SEED_ACCOUNT.message, 'utf8');
326
+ const hash1 = utils.sha256(data);
327
+ const hash2 = utils.sha256(data);
328
+ assert.deepStrictEqual(hash1, hash2);
329
+ });
330
+ it('should produce different hash for different input', function () {
331
+ const data1 = Buffer.from(account_1.SEED_ACCOUNT.message, 'utf8');
332
+ const data2 = Buffer.from(account_1.SEED_ACCOUNT.privateKey, 'utf8');
333
+ const hash1 = utils.sha256(data1);
334
+ const hash2 = utils.sha256(data2);
335
+ assert.notDeepStrictEqual(hash1, hash2);
336
+ });
337
+ });
338
+ describe('validateRawTransaction', function () {
339
+ it('should not throw for valid unsigned hex transaction', function () {
340
+ const rawTx = utils.removeHexPrefix(exportInC_1.EXPORT_IN_C.unsignedHex);
341
+ assert.doesNotThrow(() => utils.validateRawTransaction(rawTx));
342
+ });
343
+ it('should not throw for valid signed hex transaction', function () {
344
+ const rawTx = utils.removeHexPrefix(exportInC_1.EXPORT_IN_C.signedHex);
345
+ assert.doesNotThrow(() => utils.validateRawTransaction(rawTx));
346
+ });
347
+ it('should not throw for import transaction hex', function () {
348
+ const rawTx = utils.removeHexPrefix(importInP_1.IMPORT_IN_P.unsignedHex);
349
+ assert.doesNotThrow(() => utils.validateRawTransaction(rawTx));
350
+ });
351
+ it('should throw for empty transaction', function () {
352
+ assert.throws(() => utils.validateRawTransaction(''), /Raw transaction is empty/);
353
+ });
354
+ it('should throw for non-hex transaction', function () {
355
+ assert.throws(() => utils.validateRawTransaction('xyz123'), /Raw transaction is not hex string/);
356
+ });
357
+ });
358
+ describe('removeHexPrefix', function () {
359
+ it('should remove 0x prefix from C-chain address', function () {
360
+ assert.strictEqual(utils.removeHexPrefix(exportInC_1.EXPORT_IN_C.cHexAddress), exportInC_1.EXPORT_IN_C.cHexAddress.slice(2));
361
+ });
362
+ it('should remove 0x prefix from unsigned hex', function () {
363
+ assert.strictEqual(utils.removeHexPrefix(exportInC_1.EXPORT_IN_C.unsignedHex), exportInC_1.EXPORT_IN_C.unsignedHex.slice(2));
364
+ });
365
+ it('should return string unchanged if no prefix', function () {
366
+ assert.strictEqual(utils.removeHexPrefix(account_1.SEED_ACCOUNT.privateKey), account_1.SEED_ACCOUNT.privateKey);
367
+ });
368
+ it('should handle empty string', function () {
369
+ assert.strictEqual(utils.removeHexPrefix(''), '');
183
370
  });
184
371
  });
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, '~');
372
+ describe('outputidxNumberToBuffer and outputidxBufferToNumber', function () {
373
+ it('should handle nonce value', function () {
374
+ const nonceStr = exportInC_1.EXPORT_IN_C.nonce.toString();
375
+ const buffer = utils.outputidxNumberToBuffer(nonceStr);
376
+ const result = utils.outputidxBufferToNumber(buffer);
377
+ assert.strictEqual(result, nonceStr);
189
378
  });
190
- it('should handle input separator constants', function () {
191
- const { INPUT_SEPARATOR } = require('../../../src/lib/iface');
192
- assert.strictEqual(INPUT_SEPARATOR, ':');
379
+ it('should produce 4-byte buffer', function () {
380
+ const buffer = utils.outputidxNumberToBuffer('255');
381
+ assert.strictEqual(buffer.length, 4);
193
382
  });
194
383
  });
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
- }
384
+ describe('addressToString', function () {
385
+ it('should convert address buffer to mainnet bech32 string', function () {
386
+ const address = account_1.SEED_ACCOUNT.addressMainnet;
387
+ const addressBuffer = utils.parseAddress(address);
388
+ const result = utils.addressToString('flare', 'P', addressBuffer);
389
+ assert.ok(result.startsWith('P-'));
390
+ assert.ok(result.includes('flare'));
391
+ });
392
+ it('should convert address buffer to testnet bech32 string', function () {
393
+ const address = account_1.SEED_ACCOUNT.addressTestnet;
394
+ const addressBuffer = utils.parseAddress(address);
395
+ const result = utils.addressToString('costwo', 'P', addressBuffer);
396
+ assert.ok(result.startsWith('P-'));
397
+ assert.ok(result.includes('costwo'));
214
398
  });
215
399
  });
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);
400
+ describe('cb58Encode and cb58Decode', function () {
401
+ it('should encode and decode target chain ID correctly', function () {
402
+ const encoded = exportInC_1.EXPORT_IN_C.targetChainId;
403
+ const decoded = utils.cb58Decode(encoded);
404
+ const reEncoded = utils.cb58Encode(decoded);
405
+ assert.strictEqual(reEncoded, encoded);
406
+ });
407
+ it('should encode and decode source chain ID correctly', function () {
408
+ const encoded = importInP_1.IMPORT_IN_P.sourceChainId;
409
+ const decoded = utils.cb58Decode(encoded);
410
+ const reEncoded = utils.cb58Encode(decoded);
411
+ assert.strictEqual(reEncoded, encoded);
412
+ });
413
+ it('should throw for invalid checksum', function () {
414
+ assert.throws(() => utils.cb58Decode('1111111111111'), /Invalid checksum/);
229
415
  });
230
416
  });
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);
417
+ describe('parseAddress and stringToAddress', function () {
418
+ it('should parse hex address with 0x prefix', function () {
419
+ const buffer = utils.parseAddress(exportInC_1.EXPORT_IN_C.cHexAddress);
420
+ assert.ok(buffer instanceof Buffer);
421
+ assert.strictEqual(buffer.length, 20);
422
+ });
423
+ it('should parse mainnet bech32 address', function () {
424
+ const buffer = utils.parseAddress(account_1.SEED_ACCOUNT.addressMainnet);
425
+ assert.ok(buffer instanceof Buffer);
426
+ assert.strictEqual(buffer.length, 20);
427
+ });
428
+ it('should parse testnet bech32 address', function () {
429
+ const buffer = utils.parseAddress(account_1.SEED_ACCOUNT.addressTestnet);
430
+ assert.ok(buffer instanceof Buffer);
431
+ assert.strictEqual(buffer.length, 20);
432
+ });
433
+ it('should parse P-chain addresses from export data', function () {
434
+ exportInC_1.EXPORT_IN_C.pAddresses.forEach((address) => {
435
+ const buffer = utils.parseAddress(address);
436
+ assert.ok(buffer instanceof Buffer);
437
+ assert.strictEqual(buffer.length, 20);
438
+ });
439
+ });
440
+ it('should throw for address without dash separator', function () {
441
+ assert.throws(() => utils.parseAddress('flare1abc'), /Valid address should include -/);
442
+ });
443
+ it('should throw for invalid HRP', function () {
444
+ assert.throws(() => utils.parseAddress('P-invalid1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq5evzmy'), /Invalid HRP/);
445
+ });
446
+ });
447
+ describe('flareIdString', function () {
448
+ it('should create Id from private key hex string', function () {
449
+ const id = utils.flareIdString(account_1.SEED_ACCOUNT.privateKey);
450
+ assert.ok(id);
451
+ });
452
+ it('should create Id from asset ID hex', function () {
453
+ // Asset ID is typically 32 bytes (64 hex chars)
454
+ const assetIdHex = account_1.SEED_ACCOUNT.privateKey; // Using as a 32-byte hex
455
+ const id = utils.flareIdString(assetIdHex);
456
+ assert.ok(id);
457
+ });
458
+ });
459
+ describe('recoverySignature', function () {
460
+ it('should recover public key from valid signature', function () {
461
+ const message = Buffer.from(account_1.SEED_ACCOUNT.message, 'utf8');
462
+ const privateKey = Buffer.from(account_1.SEED_ACCOUNT.privateKey, 'hex');
463
+ // Create signature using the same private key (createSignature hashes the message internally)
464
+ const signature = utils.createSignature(network, message, privateKey);
465
+ // Recover public key - pass the hashed message since recoverySignature expects pre-hashed
466
+ const messageHash = utils.sha256(message);
467
+ const recoveredPubKey = utils.recoverySignature(messageHash, signature);
468
+ assert.ok(recoveredPubKey instanceof Buffer);
469
+ assert.strictEqual(recoveredPubKey.length, 33); // Should be compressed public key (33 bytes)
470
+ });
471
+ it('should recover same public key for same message and signature', function () {
472
+ const message = Buffer.from(account_1.SEED_ACCOUNT.message, 'utf8');
473
+ const privateKey = Buffer.from(account_1.SEED_ACCOUNT.privateKey, 'hex');
474
+ const signature = utils.createSignature(network, message, privateKey);
475
+ const messageHash = utils.sha256(message);
476
+ const pubKey1 = utils.recoverySignature(messageHash, signature);
477
+ const pubKey2 = utils.recoverySignature(messageHash, signature);
478
+ assert.deepStrictEqual(pubKey1, pubKey2);
479
+ });
480
+ it('should recover public key that matches original key', function () {
481
+ const message = Buffer.from(account_1.SEED_ACCOUNT.message, 'utf8');
482
+ const privateKey = Buffer.from(account_1.SEED_ACCOUNT.privateKey, 'hex');
483
+ // Get original public key
484
+ const originalPubKey = Buffer.from(secp256k1_1.ecc.pointFromScalar(privateKey, true));
485
+ // Create signature and recover public key
486
+ const signature = utils.createSignature(network, message, privateKey);
487
+ const messageHash = utils.sha256(message);
488
+ const recoveredPubKey = utils.recoverySignature(messageHash, signature);
489
+ // Convert both to hex strings for comparison
490
+ assert.strictEqual(recoveredPubKey.toString('hex'), originalPubKey.toString('hex'));
491
+ });
492
+ it('should recover public key using ACCOUNT_1 keys', function () {
493
+ const message = Buffer.from(account_1.SEED_ACCOUNT.message, 'utf8');
494
+ const privateKey = Buffer.from(account_1.ACCOUNT_1.privateKey, 'hex');
495
+ const originalPubKey = Buffer.from(secp256k1_1.ecc.pointFromScalar(privateKey, true));
496
+ const signature = utils.createSignature(network, message, privateKey);
497
+ const messageHash = utils.sha256(message);
498
+ const recoveredPubKey = utils.recoverySignature(messageHash, signature);
499
+ assert.strictEqual(recoveredPubKey.toString('hex'), originalPubKey.toString('hex'));
500
+ });
501
+ it('should throw error for invalid signature length', function () {
502
+ const messageHash = utils.sha256(Buffer.from(account_1.SEED_ACCOUNT.message, 'utf8'));
503
+ const invalidSignature = Buffer.from(account_1.INVALID_SHORT_KEYPAIR_KEY, 'hex');
504
+ assert.throws(() => utils.recoverySignature(messageHash, invalidSignature), /Failed to recover signature/);
505
+ });
506
+ it('should throw error for signature with invalid recovery parameter', function () {
507
+ const messageHash = utils.sha256(Buffer.from(account_1.SEED_ACCOUNT.message, 'utf8'));
508
+ const signature = Buffer.alloc(65); // Valid length but all zeros - invalid signature
509
+ assert.throws(() => utils.recoverySignature(messageHash, signature), /Failed to recover signature/);
510
+ });
511
+ it('should recover signature and verify sender address from signed C-chain Export tx', async function () {
512
+ // Transaction from actual build response - C-chain Export tx
513
+ const tx = '0x0000000000010000007278db5c30bed04c05ce209179812850bbb3fe6d46d7eef3744d814c0da55524790000000000000000000000000000000000000000000000000000000000000000000000012a96025ad506b9fbb9023fbdc1665c7f7d7c923f000000000605236658734f94af871c3d131b56131b6fb7a0291eacadd261e69dfb42a9cdf6f7fddd00000000000000000000000158734f94af871c3d131b56131b6fb7a0291eacadd261e69dfb42a9cdf6f7fddd000000070000000006052340000000000000000000000002000000037fa8c7e0c8ad9f09f9179b42b77e94a487c3df758d4ba538f772333ca7bf3668a2fe36648438c79d9b6b77b56effb860eaa430e0e30c4e392f59cd08000000010000000900000001750076e67d9720283a71c6e7a9a88ff662608fefdd3f316f1211957ca1873eee3ee4a74b468bda66176a3e5d3ab54d43a8c0be12348f251a3093c16d9db00cd001c31e9c15';
514
+ const expectedSenderAddress = '0x2a96025ad506b9fbb9023fbdc1665c7f7d7c923f';
515
+ const factory = new lib_1.TransactionBuilderFactory(statics_1.coins.get('tflrp'));
516
+ const txn = (await factory.from(tx).build());
517
+ const signablePayload = txn.signablePayload;
518
+ const signatures = txn.signature;
519
+ const sig = Buffer.from(utils.removeHexPrefix(signatures[0]), 'hex');
520
+ // Recover public key from signature (signablePayload is already SHA256 hashed)
521
+ const recoveredPubKey = utils.recoverySignature(signablePayload, sig);
522
+ // Get the sender address from the transaction inputs
523
+ const txInputs = txn.inputs;
524
+ const senderAddressFromTx = txInputs[0].address.toLowerCase();
525
+ // Verify sender address matches expected
526
+ assert.strictEqual(senderAddressFromTx, expectedSenderAddress.toLowerCase(), 'Transaction sender address does not match expected');
527
+ // Derive address from recovered public key
528
+ const derivedEvmAddress = '0x' + Buffer.from(new flarejs_1.Address(flarejs_1.secp256k1.publicKeyToEthAddress(recoveredPubKey)).toBytes()).toString('hex');
529
+ // Verify the recovered public key matches the sender
530
+ assert.strictEqual(derivedEvmAddress.toLowerCase(), senderAddressFromTx, 'Recovered public key does not match sender address');
531
+ // Also verify signature validity
532
+ const sigOnly = sig.slice(0, 64);
533
+ const isValid = utils.verifySignature(signablePayload, sigOnly, recoveredPubKey);
534
+ assert.strictEqual(isValid, true, 'Signature verification failed');
535
+ });
536
+ });
537
+ describe('isTransactionOf', function () {
538
+ const factory = new lib_1.TransactionBuilderFactory(statics_1.coins.get('tflrp'));
539
+ const utilsInstance = new utils_1.Utils();
540
+ const testnetNetwork = statics_1.coins.get('tflrp').network;
541
+ const pChainBlockchainIdHex = Buffer.from(utilsInstance.cb58Decode(testnetNetwork.blockchainID)).toString('hex');
542
+ const cChainBlockchainIdHex = Buffer.from(utilsInstance.cb58Decode(testnetNetwork.cChainBlockchainID)).toString('hex');
543
+ it('should return true for Import in P transaction with matching P-chain blockchain ID', async function () {
544
+ const txBuilder = factory
545
+ .getImportInPBuilder()
546
+ .threshold(importInP_1.IMPORT_IN_P.threshold)
547
+ .locktime(importInP_1.IMPORT_IN_P.locktime)
548
+ .fromPubKey(importInP_1.IMPORT_IN_P.corethAddresses)
549
+ .to(importInP_1.IMPORT_IN_P.pAddresses)
550
+ .externalChainId(importInP_1.IMPORT_IN_P.sourceChainId)
551
+ .feeState(importInP_1.IMPORT_IN_P.feeState)
552
+ .context(importInP_1.IMPORT_IN_P.context)
553
+ .decodedUtxos(importInP_1.IMPORT_IN_P.utxos);
554
+ const tx = (await txBuilder.build());
555
+ const flareTransaction = tx.getFlareTransaction();
556
+ assert.strictEqual(utilsInstance.isTransactionOf(flareTransaction, pChainBlockchainIdHex), true);
557
+ });
558
+ it('should return false for Import in P transaction with non-matching C-chain blockchain ID', async function () {
559
+ const txBuilder = factory
560
+ .getImportInPBuilder()
561
+ .threshold(importInP_1.IMPORT_IN_P.threshold)
562
+ .locktime(importInP_1.IMPORT_IN_P.locktime)
563
+ .fromPubKey(importInP_1.IMPORT_IN_P.corethAddresses)
564
+ .to(importInP_1.IMPORT_IN_P.pAddresses)
565
+ .externalChainId(importInP_1.IMPORT_IN_P.sourceChainId)
566
+ .feeState(importInP_1.IMPORT_IN_P.feeState)
567
+ .context(importInP_1.IMPORT_IN_P.context)
568
+ .decodedUtxos(importInP_1.IMPORT_IN_P.utxos);
569
+ const tx = (await txBuilder.build());
570
+ const flareTransaction = tx.getFlareTransaction();
571
+ assert.strictEqual(utilsInstance.isTransactionOf(flareTransaction, cChainBlockchainIdHex), false);
572
+ });
573
+ it('should return true for Export in P transaction with matching P-chain blockchain ID', async function () {
574
+ const txBuilder = factory
575
+ .getExportInPBuilder()
576
+ .threshold(exportInP_1.EXPORT_IN_P.threshold)
577
+ .locktime(exportInP_1.EXPORT_IN_P.locktime)
578
+ .fromPubKey(exportInP_1.EXPORT_IN_P.pAddresses)
579
+ .externalChainId(exportInP_1.EXPORT_IN_P.sourceChainId)
580
+ .feeState(exportInP_1.EXPORT_IN_P.feeState)
581
+ .context(exportInP_1.EXPORT_IN_P.context)
582
+ .amount(exportInP_1.EXPORT_IN_P.amount)
583
+ .decodedUtxos(exportInP_1.EXPORT_IN_P.utxos);
584
+ const tx = (await txBuilder.build());
585
+ const flareTransaction = tx.getFlareTransaction();
586
+ assert.strictEqual(utilsInstance.isTransactionOf(flareTransaction, pChainBlockchainIdHex), true);
587
+ });
588
+ it('should return false for Export in P transaction with non-matching C-chain blockchain ID', async function () {
589
+ const txBuilder = factory
590
+ .getExportInPBuilder()
591
+ .threshold(exportInP_1.EXPORT_IN_P.threshold)
592
+ .locktime(exportInP_1.EXPORT_IN_P.locktime)
593
+ .fromPubKey(exportInP_1.EXPORT_IN_P.pAddresses)
594
+ .externalChainId(exportInP_1.EXPORT_IN_P.sourceChainId)
595
+ .feeState(exportInP_1.EXPORT_IN_P.feeState)
596
+ .context(exportInP_1.EXPORT_IN_P.context)
597
+ .amount(exportInP_1.EXPORT_IN_P.amount)
598
+ .decodedUtxos(exportInP_1.EXPORT_IN_P.utxos);
599
+ const tx = (await txBuilder.build());
600
+ const flareTransaction = tx.getFlareTransaction();
601
+ assert.strictEqual(utilsInstance.isTransactionOf(flareTransaction, cChainBlockchainIdHex), false);
602
+ });
603
+ it('should return true for Import in C transaction with matching C-chain blockchain ID', async function () {
604
+ const txBuilder = factory
605
+ .getImportInCBuilder()
606
+ .threshold(importInC_1.IMPORT_IN_C.threshold)
607
+ .locktime(importInC_1.IMPORT_IN_C.locktime)
608
+ .fromPubKey(importInC_1.IMPORT_IN_C.pAddresses)
609
+ .externalChainId(importInC_1.IMPORT_IN_C.sourceChainId)
610
+ .fee(importInC_1.IMPORT_IN_C.fee)
611
+ .context(importInC_1.IMPORT_IN_C.context)
612
+ .to(importInC_1.IMPORT_IN_C.to)
613
+ .decodedUtxos(importInC_1.IMPORT_IN_C.utxos);
614
+ const tx = (await txBuilder.build());
615
+ const flareTransaction = tx.getFlareTransaction();
616
+ assert.strictEqual(utilsInstance.isTransactionOf(flareTransaction, cChainBlockchainIdHex), true);
617
+ });
618
+ it('should return false for Import in C transaction with non-matching P-chain blockchain ID', async function () {
619
+ const txBuilder = factory
620
+ .getImportInCBuilder()
621
+ .threshold(importInC_1.IMPORT_IN_C.threshold)
622
+ .locktime(importInC_1.IMPORT_IN_C.locktime)
623
+ .fromPubKey(importInC_1.IMPORT_IN_C.pAddresses)
624
+ .externalChainId(importInC_1.IMPORT_IN_C.sourceChainId)
625
+ .fee(importInC_1.IMPORT_IN_C.fee)
626
+ .context(importInC_1.IMPORT_IN_C.context)
627
+ .to(importInC_1.IMPORT_IN_C.to)
628
+ .decodedUtxos(importInC_1.IMPORT_IN_C.utxos);
629
+ const tx = (await txBuilder.build());
630
+ const flareTransaction = tx.getFlareTransaction();
631
+ assert.strictEqual(utilsInstance.isTransactionOf(flareTransaction, pChainBlockchainIdHex), false);
632
+ });
633
+ it('should return true for Export in C transaction with matching C-chain blockchain ID', async function () {
634
+ const txBuilder = factory
635
+ .getExportInCBuilder()
636
+ .fromPubKey(exportInC_1.EXPORT_IN_C.cHexAddress)
637
+ .nonce(exportInC_1.EXPORT_IN_C.nonce)
638
+ .amount(exportInC_1.EXPORT_IN_C.amount)
639
+ .threshold(exportInC_1.EXPORT_IN_C.threshold)
640
+ .locktime(exportInC_1.EXPORT_IN_C.locktime)
641
+ .to(exportInC_1.EXPORT_IN_C.pAddresses)
642
+ .fee(exportInC_1.EXPORT_IN_C.fee)
643
+ .context(exportInC_1.EXPORT_IN_C.context);
644
+ const tx = (await txBuilder.build());
645
+ const flareTransaction = tx.getFlareTransaction();
646
+ assert.strictEqual(utilsInstance.isTransactionOf(flareTransaction, cChainBlockchainIdHex), true);
647
+ });
648
+ it('should return false for Export in C transaction with non-matching P-chain blockchain ID', async function () {
649
+ const txBuilder = factory
650
+ .getExportInCBuilder()
651
+ .fromPubKey(exportInC_1.EXPORT_IN_C.cHexAddress)
652
+ .nonce(exportInC_1.EXPORT_IN_C.nonce)
653
+ .amount(exportInC_1.EXPORT_IN_C.amount)
654
+ .threshold(exportInC_1.EXPORT_IN_C.threshold)
655
+ .locktime(exportInC_1.EXPORT_IN_C.locktime)
656
+ .to(exportInC_1.EXPORT_IN_C.pAddresses)
657
+ .fee(exportInC_1.EXPORT_IN_C.fee)
658
+ .context(exportInC_1.EXPORT_IN_C.context);
659
+ const tx = (await txBuilder.build());
660
+ const flareTransaction = tx.getFlareTransaction();
661
+ assert.strictEqual(utilsInstance.isTransactionOf(flareTransaction, pChainBlockchainIdHex), false);
662
+ });
663
+ it('should return false for invalid blockchain ID', async function () {
664
+ const txBuilder = factory
665
+ .getImportInPBuilder()
666
+ .threshold(importInP_1.IMPORT_IN_P.threshold)
667
+ .locktime(importInP_1.IMPORT_IN_P.locktime)
668
+ .fromPubKey(importInP_1.IMPORT_IN_P.corethAddresses)
669
+ .to(importInP_1.IMPORT_IN_P.pAddresses)
670
+ .externalChainId(importInP_1.IMPORT_IN_P.sourceChainId)
671
+ .feeState(importInP_1.IMPORT_IN_P.feeState)
672
+ .context(importInP_1.IMPORT_IN_P.context)
673
+ .decodedUtxos(importInP_1.IMPORT_IN_P.utxos);
674
+ const tx = (await txBuilder.build());
675
+ const flareTransaction = tx.getFlareTransaction();
676
+ assert.strictEqual(utilsInstance.isTransactionOf(flareTransaction, 'invalidblockchainid'), false);
283
677
  });
284
678
  });
285
679
  });
286
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi90ZXN0L3VuaXQvbGliL3V0aWxzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsaURBQTBEO0FBQzFELG1EQUEyRDtBQUMzRCwrQ0FBaUM7QUFDakMsa0RBQStDO0FBRS9DLFFBQVEsQ0FBQyxPQUFPLEVBQUU7SUFDaEIsSUFBSSxLQUFZLENBQUM7SUFFakIsVUFBVSxDQUFDO1FBQ1QsS0FBSyxHQUFHLElBQUksYUFBSyxFQUFFLENBQUM7SUFDdEIsQ0FBQyxDQUFDLENBQUM7SUFFSCxRQUFRLENBQUMsV0FBVyxFQUFFO1FBQ3BCLEVBQUUsQ0FBQyxzRUFBc0UsRUFBRTtZQUN6RSxNQUFNLGVBQWUsR0FBRyxDQUFDLE9BQU8sRUFBRSxPQUFPLENBQUMsQ0FBQztZQUMzQyxNQUFNLGVBQWUsR0FBRyxDQUFDLE9BQU8sRUFBRSxPQUFPLEVBQUUsT0FBTyxDQUFDLENBQUM7WUFFcEQsTUFBTSxDQUFDLFdBQVcsQ0FBQyxLQUFLLENBQUMsU0FBUyxDQUFDLGVBQWUsRUFBRSxlQUFlLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQztRQUM5RSxDQUFDLENBQUMsQ0FBQztRQUVILEVBQUUsQ0FBQywyRUFBMkUsRUFBRTtZQUM5RSxNQUFNLGVBQWUsR0FBRyxDQUFDLE9BQU8sRUFBRSxPQUFPLENBQUMsQ0FBQztZQUMzQyxNQUFNLGVBQWUsR0FBRyxDQUFDLE9BQU8sRUFBRSxPQUFPLENBQUMsQ0FBQztZQUUzQyxNQUFNLENBQUMsV0FBVyxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUMsZUFBZSxFQUFFLGVBQWUsQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDO1FBQy9FLENBQUMsQ0FBQyxDQUFDO1FBRUgsRUFBRSxDQUFDLCtDQUErQyxFQUFFO1lBQ2xELE1BQU0sZUFBZSxHQUFhLEVBQUUsQ0FBQztZQUNyQyxNQUFNLGVBQWUsR0FBRyxDQUFDLE9BQU8sRUFBRSxPQUFPLENBQUMsQ0FBQztZQUUzQyxNQUFNLENBQUMsV0FBVyxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUMsZUFBZSxFQUFFLGVBQWUsQ0FBQyxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQzlFLENBQUMsQ0FBQyxDQUFDO1FBRUgsRUFBRSxDQUFDLDZFQUE2RSxFQUFFO1lBQ2hGLE1BQU0sZUFBZSxHQUFHLENBQUMsT0FBTyxDQUFDLENBQUM7WUFDbEMsTUFBTSxlQUFlLEdBQWEsRUFBRSxDQUFDO1lBRXJDLE1BQU0sQ0FBQyxXQUFXLENBQUMsS0FBSyxDQUFDLFNBQVMsQ0FBQyxlQUFlLEVBQUUsZUFBZSxDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFDL0UsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztJQUVILFFBQVEsQ0FBQyxnQkFBZ0IsRUFBRTtRQUN6QixFQUFFLENBQUMsOENBQThDLEVBQUU7WUFDakQsb0RBQW9EO1lBQ3BELE1BQU0sY0FBYyxHQUFHO2dCQUNyQixrRUFBa0U7Z0JBQ2xFLG9FQUFvRTthQUNyRSxDQUFDO1lBRUYsY0FBYyxDQUFDLE9BQU8sQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFO2dCQUM5Qix5REFBeUQ7Z0JBQ3pELGdGQUFnRjtnQkFDaEYsTUFBTSxNQUFNLEdBQUcsS0FBSyxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUMsQ0FBQztnQkFDMUMsNERBQTREO2dCQUM1RCxNQUFNLENBQUMsV0FBVyxDQUFDLE9BQU8sTUFBTSxFQUFFLFNBQVMsQ0FBQyxDQUFDO1lBQy9DLENBQUMsQ0FBQyxDQUFDO1FBQ0wsQ0FBQyxDQUFDLENBQUM7UUFFSCxFQUFFLENBQUMsb0NBQW9DLEVBQUU7WUFDdkMsTUFBTSxTQUFTLEdBQUc7Z0JBQ2hCLGtFQUFrRTtnQkFDbEUsbUVBQW1FO2FBQ3BFLENBQUM7WUFFRixNQUFNLE1BQU0sR0FBRyxLQUFLLENBQUMsY0FBYyxDQUFDLFNBQVMsQ0FBQyxDQUFDO1lBQy9DLE1BQU0sQ0FBQyxXQUFXLENBQUMsT0FBTyxNQUFNLEVBQUUsU0FBUyxDQUFDLENBQUM7UUFDL0MsQ0FBQyxDQUFDLENBQUM7UUFFSCxFQUFFLENBQUMsMENBQTBDLEVBQUU7WUFDN0MsTUFBTSxhQUFhLEdBQ2pCLG9JQUFvSSxDQUFDO1lBRXZJLE1BQU0sTUFBTSxHQUFHLEtBQUssQ0FBQyxjQUFjLENBQUMsYUFBYSxDQUFDLENBQUM7WUFDbkQsTUFBTSxDQUFDLFdBQVcsQ0FBQyxPQUFPLE1BQU0sRUFBRSxTQUFTLENBQUMsQ0FBQztRQUMvQyxDQUFDLENBQUMsQ0FBQztRQUVILEVBQUUsQ0FBQywyQ0FBMkMsRUFBRTtZQUM5QyxNQUFNLGdCQUFnQixHQUFHO2dCQUN2QixFQUFFO2dCQUNGLFNBQVM7Z0JBQ1QsS0FBSztnQkFDTCw4REFBOEQ7Z0JBQzlELGdEQUFnRDthQUNqRCxDQUFDO1lBRUYsZ0JBQWdCLENBQUMsT0FBTyxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUU7Z0JBQ2hDLE1BQU0sTUFBTSxHQUFHLEtBQUssQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLENBQUM7Z0JBQzFDLDZEQUE2RDtnQkFDN0QsTUFBTSxDQUFDLFdBQVcsQ0FBQyxPQUFPLE1BQU0sRUFBRSxTQUFTLENBQUMsQ0FBQztZQUMvQyxDQUFDLENBQUMsQ0FBQztRQUNMLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7SUFFSCxRQUFRLENBQUMscUJBQXFCLEVBQUU7UUFDOUIsRUFBRSxDQUFDLHVDQUF1QyxFQUFFO1lBQzFDLE1BQU0sV0FBVyxHQUFHLGtFQUFrRSxDQUFDO1lBQ3ZGLE1BQU0sTUFBTSxHQUFHLEtBQUssQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDLFdBQVcsQ0FBQyxDQUFDO1lBQ3pELE1BQU0sQ0FBQyxXQUFXLENBQUMsT0FBTyxNQUFNLEVBQUUsU0FBUyxDQUFDLENBQUM7UUFDL0MsQ0FBQyxDQUFDLENBQUM7UUFFSCxFQUFFLENBQUMsNkJBQTZCLEVBQUU7WUFDaEMsTUFBTSxNQUFNLEdBQUcsS0FBSyxDQUFDLHFCQUFxQixDQUFDLENBQUMsRUFBRSxDQUFDLENBQUM7WUFDaEQsTUFBTSxDQUFDLFdBQVcsQ0FBQyxNQUFNLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFDcEMsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztJQUVILFFBQVEsQ0FBQyxzQkFBc0IsRUFBRTtRQUMvQixFQUFFLENBQUMsa0NBQWtDLEVBQUU7WUFDckMsTUFBTSxDQUFDLE1BQU0sQ0FDWCxHQUFHLEVBQUUsQ0FBQyxLQUFLLENBQUMsb0JBQW9CLENBQUMsU0FBUyxDQUFDLEVBQzNDLDhCQUFtQixFQUNuQixzQ0FBc0MsQ0FDdkMsQ0FBQztRQUNKLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7SUFFSCxRQUFRLENBQUMsa0JBQWtCLEVBQUU7UUFDM0IsRUFBRSxDQUFDLGtDQUFrQyxFQUFFO1lBQ3JDLE1BQU0sQ0FBQyxNQUFNLENBQ1gsR0FBRyxFQUFFLENBQUMsS0FBSyxDQUFDLGdCQUFnQixDQUFDLGNBQWMsQ0FBQyxFQUM1Qyw4QkFBbUIsRUFDbkIsa0NBQWtDLENBQ25DLENBQUM7UUFDSixDQUFDLENBQUMsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0lBRUgsUUFBUSxDQUFDLGlCQUFpQixFQUFFO1FBQzFCLEVBQUUsQ0FBQyx5Q0FBeUMsRUFBRTtZQUM1QyxNQUFNLE9BQU8sR0FBRyxlQUFLLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDLE9BQXVCLENBQUM7WUFDMUQsTUFBTSxPQUFPLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxhQUFhLEVBQUUsTUFBTSxDQUFDLENBQUM7WUFDbkQsTUFBTSxVQUFVLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxrRUFBa0UsRUFBRSxLQUFLLENBQUMsQ0FBQztZQUUxRyxNQUFNLFNBQVMsR0FBRyxLQUFLLENBQUMsZUFBZSxDQUFDLE9BQU8sRUFBRSxPQUFPLEVBQUUsVUFBVSxDQUFDLENBQUM7WUFFdEUsTUFBTSxDQUFDLEVBQUUsQ0FBQyxTQUFTLFlBQVksTUFBTSxDQUFDLENBQUM7WUFDdkMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxTQUFTLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDO1FBQ2xDLENBQUMsQ0FBQyxDQUFDO1FBRUgsRUFBRSxDQUFDLDJEQUEyRCxFQUFFO1lBQzlELE1BQU0sT0FBTyxHQUFHLGVBQUssQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUMsT0FBdUIsQ0FBQztZQUMxRCxNQUFNLFFBQVEsR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLFdBQVcsRUFBRSxNQUFNLENBQUMsQ0FBQztZQUNsRCxNQUFNLFFBQVEsR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLFdBQVcsRUFBRSxNQUFNLENBQUMsQ0FBQztZQUNsRCxNQUFNLFVBQVUsR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLGtFQUFrRSxFQUFFLEtBQUssQ0FBQyxDQUFDO1lBRTFHLE1BQU0sSUFBSSxHQUFHLEtBQUssQ0FBQyxlQUFlLENBQUMsT0FBTyxFQUFFLFFBQVEsRUFBRSxVQUFVLENBQUMsQ0FBQztZQUNsRSxNQUFNLElBQUksR0FBRyxLQUFLLENBQUMsZUFBZSxDQUFDLE9BQU8sRUFBRSxRQUFRLEVBQUUsVUFBVSxDQUFDLENBQUM7WUFFbEUsTUFBTSxDQUFDLGtCQUFrQixDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsQ0FBQztRQUN4QyxDQUFDLENBQUMsQ0FBQztRQUVILEVBQUUsQ0FBQyw0Q0FBNEMsRUFBRTtZQUMvQyxNQUFNLE9BQU8sR0FBRyxlQUFLLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDLE9BQXVCLENBQUM7WUFDMUQsTUFBTSxPQUFPLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxhQUFhLEVBQUUsTUFBTSxDQUFDLENBQUM7WUFDbkQsTUFBTSxpQkFBaUIsR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxNQUFNLENBQUMsQ0FBQztZQUV6RCxNQUFNLENBQUMsTUFBTSxDQUFDLEdBQUcsRUFBRSxDQUFDLEtBQUssQ0FBQyxlQUFlLENBQUMsT0FBTyxFQUFFLE9BQU8sRUFBRSxpQkFBaUIsQ0FBQyxFQUFFLDRCQUE0QixDQUFDLENBQUM7UUFDaEgsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztJQUVILFFBQVEsQ0FBQyxpQkFBaUIsRUFBRTtRQUMxQixFQUFFLENBQUMsK0JBQStCLEVBQUU7WUFDbEMsTUFBTSxPQUFPLEdBQUcsZUFBSyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQyxPQUF1QixDQUFDO1lBQzFELE1BQU0sT0FBTyxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsYUFBYSxFQUFFLE1BQU0sQ0FBQyxDQUFDO1lBQ25ELE1BQU0sVUFBVSxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsa0VBQWtFLEVBQUUsS0FBSyxDQUFDLENBQUM7WUFFMUcsbUJBQW1CO1lBQ25CLE1BQU0sU0FBUyxHQUFHLEtBQUssQ0FBQyxlQUFlLENBQUMsT0FBTyxFQUFFLE9BQU8sRUFBRSxVQUFVLENBQUMsQ0FBQztZQUV0RSxpRUFBaUU7WUFDakUsb0RBQW9EO1lBQ3BELE1BQU0sU0FBUyxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxHQUFHLEdBQUcsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQywrQkFBK0I7WUFFNUYsMkVBQTJFO1lBQzNFLDZFQUE2RTtZQUM3RSx1RUFBdUU7WUFDdkUsTUFBTSxPQUFPLEdBQUcsS0FBSyxDQUFDLGVBQWUsQ0FBQyxPQUFPLEVBQUUsT0FBTyxFQUFFLFNBQVMsRUFBRSxTQUFTLENBQUMsQ0FBQztZQUM5RSxNQUFNLENBQUMsV0FBVyxDQUFDLE9BQU8sT0FBTyxFQUFFLFNBQVMsQ0FBQyxDQUFDO1lBQzlDLGlEQUFpRDtZQUNqRCxNQUFNLENBQUMsV0FBVyxDQUFDLE9BQU8sRUFBRSxLQUFLLENBQUMsQ0FBQztRQUNyQyxDQUFDLENBQUMsQ0FBQztRQUVILEVBQUUsQ0FBQywyQ0FBMkMsRUFBRTtZQUM5QyxNQUFNLE9BQU8sR0FBRyxlQUFLLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDLE9BQXVCLENBQUM7WUFDMUQsTUFBTSxPQUFPLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxhQUFhLEVBQUUsTUFBTSxDQUFDLENBQUM7WUFDbkQsTUFBTSxnQkFBZ0IsR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLG1CQUFtQixFQUFFLE1BQU0sQ0FBQyxDQUFDO1lBQ2xFLE1BQU0sU0FBUyxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxHQUFHLEdBQUcsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUM7WUFFNUQsMkRBQTJEO1lBQzNELHlEQUF5RDtZQUN6RCxNQUFNLE1BQU0sR0FBRyxLQUFLLENBQUMsZUFBZSxDQUFDLE9BQU8sRUFBRSxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsU0FBUyxDQUFDLENBQUM7WUFDcEYsTUFBTSxDQUFDLFdBQVcsQ0FBQyxNQUFNLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFDcEMsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztJQUVILFFBQVEsQ0FBQywyQkFBMkIsRUFBRTtRQUNwQyxFQUFFLENBQUMsMkNBQTJDLEVBQUU7WUFDOUMsTUFBTSxFQUFFLGlCQUFpQixFQUFFLEdBQUcsT0FBTyxDQUFDLHdCQUF3QixDQUFDLENBQUM7WUFDaEUsTUFBTSxDQUFDLFdBQVcsQ0FBQyxpQkFBaUIsRUFBRSxHQUFHLENBQUMsQ0FBQztRQUM3QyxDQUFDLENBQUMsQ0FBQztRQUVILEVBQUUsQ0FBQyx5Q0FBeUMsRUFBRTtZQUM1QyxNQUFNLEVBQUUsZUFBZSxFQUFFLEdBQUcsT0FBTyxDQUFDLHdCQUF3QixDQUFDLENBQUM7WUFDOUQsTUFBTSxDQUFDLFdBQVcsQ0FBQyxlQUFlLEVBQUUsR0FBRyxDQUFDLENBQUM7UUFDM0MsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztJQUVILFFBQVEsQ0FBQyxnQkFBZ0IsRUFBRTtRQUN6QixFQUFFLENBQUMsbUNBQW1DLEVBQUU7WUFDdEMsd0RBQXdEO1lBQ3hELE1BQU0sQ0FBQyxFQUFFLENBQUMsZ0JBQWdCLElBQUksS0FBSyxDQUFDLENBQUM7WUFDckMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxXQUFXLElBQUksS0FBSyxDQUFDLENBQUM7WUFDaEMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxpQkFBaUIsSUFBSSxLQUFLLENBQUMsQ0FBQztZQUN0QyxNQUFNLENBQUMsRUFBRSxDQUFDLGlCQUFpQixJQUFJLEtBQUssQ0FBQyxDQUFDO1FBQ3hDLENBQUMsQ0FBQyxDQUFDO1FBRUgsRUFBRSxDQUFDLHlDQUF5QyxFQUFFO1lBQzVDLDhEQUE4RDtZQUM5RCw2REFBNkQ7WUFDN0QsSUFBSSxDQUFDO2dCQUNILEtBQUssQ0FBQyxjQUFjLENBQUMsSUFBeUIsQ0FBQyxDQUFDO2dCQUNoRCxLQUFLLENBQUMsY0FBYyxDQUFDLFNBQThCLENBQUMsQ0FBQztZQUN2RCxDQUFDO1lBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztnQkFDZixxRUFBcUU7Z0JBQ3JFLE1BQU0sQ0FBQyxFQUFFLENBQUMsS0FBSyxZQUFZLEtBQUssQ0FBQyxDQUFDO1lBQ3BDLENBQUM7UUFDSCxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0lBRUgsUUFBUSxDQUFDLHNCQUFzQixFQUFFO1FBQy9CLEVBQUUsQ0FBQyxxQ0FBcUMsRUFBRTtZQUN4QyxNQUFNLFNBQVMsR0FBRyxPQUFPLENBQUMsNEJBQTRCLENBQUMsQ0FBQztZQUV4RCxNQUFNLENBQUMsV0FBVyxDQUFDLE9BQU8sU0FBUyxDQUFDLHVCQUF1QixFQUFFLFFBQVEsQ0FBQyxDQUFDO1lBQ3ZFLE1BQU0sQ0FBQyxXQUFXLENBQUMsT0FBTyxTQUFTLENBQUMsb0JBQW9CLEVBQUUsUUFBUSxDQUFDLENBQUM7WUFDcEUsTUFBTSxDQUFDLFdBQVcsQ0FBQyxPQUFPLFNBQVMsQ0FBQyw0QkFBNEIsRUFBRSxRQUFRLENBQUMsQ0FBQztZQUM1RSxNQUFNLENBQUMsV0FBVyxDQUFDLE9BQU8sU0FBUyxDQUFDLDhCQUE4QixFQUFFLFFBQVEsQ0FBQyxDQUFDO1lBQzlFLE1BQU0sQ0FBQyxXQUFXLENBQUMsT0FBTyxTQUFTLENBQUMsc0JBQXNCLEVBQUUsUUFBUSxDQUFDLENBQUM7WUFDdEUsTUFBTSxDQUFDLFdBQVcsQ0FBQyxPQUFPLFNBQVMsQ0FBQywyQkFBMkIsRUFBRSxRQUFRLENBQUMsQ0FBQztZQUMzRSxNQUFNLENBQUMsV0FBVyxDQUFDLE9BQU8sU0FBUyxDQUFDLDZCQUE2QixFQUFFLFFBQVEsQ0FBQyxDQUFDO1lBQzdFLE1BQU0sQ0FBQyxXQUFXLENBQUMsT0FBTyxTQUFTLENBQUMsdUJBQXVCLEVBQUUsUUFBUSxDQUFDLENBQUM7WUFDdkUsTUFBTSxDQUFDLEVBQUUsQ0FBQyxTQUFTLENBQUMsYUFBYSxZQUFZLE1BQU0sQ0FBQyxDQUFDO1lBQ3JELE1BQU0sQ0FBQyxFQUFFLENBQUMsU0FBUyxDQUFDLFNBQVMsWUFBWSxNQUFNLENBQUMsQ0FBQztRQUNuRCxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0lBRUgsUUFBUSxDQUFDLGdCQUFnQixFQUFFO1FBQ3pCLEVBQUUsQ0FBQyxnQ0FBZ0MsRUFBRTtZQUNuQyxNQUFNLElBQUksR0FBRyxhQUFhLENBQUM7WUFDM0IsTUFBTSxLQUFLLEdBQUcsS0FBSyxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUV4QyxNQUFNLENBQUMsRUFBRSxDQUFDLEtBQUssWUFBWSxVQUFVLENBQUMsQ0FBQztZQUN2QyxNQUFNLENBQUMsV0FBVyxDQUFDLEtBQUssQ0FBQyxhQUFhLENBQUMsS0FBSyxDQUFDLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFDdkQsQ0FBQyxDQUFDLENBQUM7UUFFSCxFQUFFLENBQUMsNkJBQTZCLEVBQUU7WUFDaEMsTUFBTSxJQUFJLEdBQUcsYUFBYSxDQUFDO1lBQzNCLE1BQU0sS0FBSyxHQUFHLEtBQUssQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLENBQUM7WUFFeEMsTUFBTSxDQUFDLFdBQVcsQ0FBQyxLQUFLLENBQUMsYUFBYSxDQUFDLEtBQUssQ0FBQyxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQ3ZELENBQUMsQ0FBQyxDQUFDO1FBRUgsRUFBRSxDQUFDLHNDQUFzQyxFQUFFO1lBQ3pDLE1BQU0sSUFBSSxHQUFHLFdBQVcsQ0FBQztZQUN6QixNQUFNLEtBQUssR0FBRyxLQUFLLENBQUMsZUFBZSxDQUFDLElBQUksQ0FBQyxDQUFDO1lBRTFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsS0FBSyxZQUFZLFVBQVUsQ0FBQyxDQUFDO1lBQ3ZDLE1BQU0sQ0FBQyxXQUFXLENBQUMsS0FBSyxDQUFDLGNBQWMsQ0FBQyxLQUFLLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQztRQUN4RCxDQUFDLENBQUMsQ0FBQztRQUVILEVBQUUsQ0FBQywyQ0FBMkMsRUFBRTtZQUM5QyxNQUFNLEdBQUcsR0FBRyxFQUFFLElBQUksRUFBRSxTQUFTLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxDQUFDO1lBQzlDLE1BQU0sS0FBSyxHQUFHLEtBQUssQ0FBQyxlQUFlLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDekMsTUFBTSxNQUFNLEdBQUcsS0FBSyxDQUFDLGNBQWMsQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUUzQyxNQUFNLENBQUMsV0FBVyxDQUFDLE1BQU0sRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7UUFDbEQsQ0FBQyxDQUFDLENBQUM7UUFFSCxFQUFFLENBQUMsZ0NBQWdDLEVBQUU7WUFDbkMsTUFBTSxhQUFhLEdBQUcsSUFBSSxVQUFVLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ25ELE1BQU0sS0FBSyxHQUFHLEtBQUssQ0FBQyxlQUFlLENBQUMsYUFBYSxDQUFDLENBQUM7WUFFbkQsTUFBTSxDQUFDLGVBQWUsQ0FBQyxLQUFLLEVBQUUsYUFBYSxDQUFDLENBQUM7UUFDL0MsQ0FBQyxDQUFDLENBQUM7UUFFSCxFQUFFLENBQUMsMENBQTBDLEVBQUU7WUFDN0MsTUFBTSxDQUFDLE1BQU0sQ0FBQyxHQUFHLEVBQUU7Z0JBQ2pCLDhEQUE4RDtnQkFDOUQsS0FBSyxDQUFDLGVBQWUsQ0FBQyxHQUFVLENBQUMsQ0FBQztZQUNwQyxDQUFDLEVBQUUscUJBQXFCLENBQUMsQ0FBQztRQUM1QixDQUFDLENBQUMsQ0FBQztRQUVILEVBQUUsQ0FBQyx5QkFBeUIsRUFBRTtZQUM1QixNQUFNLFVBQVUsR0FBRyxJQUFJLFVBQVUsQ0FBQyxFQUFFLENBQUMsQ0FBQztZQUN0QyxNQUFNLE1BQU0sR0FBRyxLQUFLLENBQUMsY0FBYyxDQUFDLFVBQVUsQ0FBQyxDQUFDO1lBRWhELE1BQU0sQ0FBQyxXQUFXLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBQ2pDLENBQUMsQ0FBQyxDQUFDO1FBRUgsRUFBRSxDQUFDLDJCQUEyQixFQUFFO1lBQzlCLE1BQU0sU0FBUyxHQUFHLElBQUksVUFBVSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQzVDLE1BQU0sU0FBUyxHQUFHLElBQUksVUFBVSxDQUFDLElBQUksQ0FBQyxDQUFDO1lBRXZDLE1BQU0sQ0FBQyxXQUFXLENBQUMsS0FBSyxDQUFDLGdCQUFnQixDQUFDLFNBQVMsQ0FBQyxFQUFFLElBQUksQ0FBQyxDQUFDO1lBQzVELE1BQU0sQ0FBQyxXQUFXLENBQUMsS0FBSyxDQUFDLGdCQUFnQixDQUFDLFNBQVMsQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDO1lBQzdELE1BQU0sQ0FBQyxXQUFXLENBQUMsS0FBSyxDQUFDLGdCQUFnQixDQUFDLFNBQVMsRUFBRSxJQUFJLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQztRQUNwRSxDQUFDLENBQUMsQ0FBQztRQUVILEVBQUUsQ0FBQywwQ0FBMEMsRUFBRTtZQUM3QyxNQUFNLFdBQVcsR0FBRyxtQkFBbUIsQ0FBQztZQUN4QyxNQUFNLEtBQUssR0FBRyxLQUFLLENBQUMsZUFBZSxDQUFDLFdBQVcsQ0FBQyxDQUFDO1lBQ2pELE1BQU0sTUFBTSxHQUFHLEtBQUssQ0FBQyxjQUFjLENBQUMsS0FBSyxDQUFDLENBQUM7WUFFM0MsTUFBTSxDQUFDLFdBQVcsQ0FBQyxNQUFNLEVBQUUsV0FBVyxDQUFDLENBQUM7UUFDMUMsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztBQUNMLENBQUMsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgY29pbnMsIEZsYXJlTmV0d29yayB9IGZyb20gJ0BiaXRnby1iZXRhL3N0YXRpY3MnO1xuaW1wb3J0IHsgTm90SW1wbGVtZW50ZWRFcnJvciB9IGZyb20gJ0BiaXRnby1iZXRhL3Nkay1jb3JlJztcbmltcG9ydCAqIGFzIGFzc2VydCBmcm9tICdhc3NlcnQnO1xuaW1wb3J0IHsgVXRpbHMgfSBmcm9tICcuLi8uLi8uLi9zcmMvbGliL3V0aWxzJztcblxuZGVzY3JpYmUoJ1V0aWxzJywgZnVuY3Rpb24gKCkge1xuICBsZXQgdXRpbHM6IFV0aWxzO1xuXG4gIGJlZm9yZUVhY2goZnVuY3Rpb24gKCkge1xuICAgIHV0aWxzID0gbmV3IFV0aWxzKCk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdpbmNsdWRlSW4nLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ3Nob3VsZCByZXR1cm4gdHJ1ZSB3aGVuIGFsbCB3YWxsZXQgYWRkcmVzc2VzIGFyZSBpbiBvdXRwdXQgYWRkcmVzc2VzJywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgd2FsbGV0QWRkcmVzc2VzID0gWydhZGRyMScsICdhZGRyMiddO1xuICAgICAgY29uc3Qgb3V0cHV0QWRkcmVzc2VzID0gWydhZGRyMScsICdhZGRyMicsICdhZGRyMyddO1xuXG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwodXRpbHMuaW5jbHVkZUluKHdhbGxldEFkZHJlc3Nlcywgb3V0cHV0QWRkcmVzc2VzKSwgdHJ1ZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJldHVybiBmYWxzZSB3aGVuIG5vdCBhbGwgd2FsbGV0IGFkZHJlc3NlcyBhcmUgaW4gb3V0cHV0IGFkZHJlc3NlcycsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHdhbGxldEFkZHJlc3NlcyA9IFsnYWRkcjEnLCAnYWRkcjInXTtcbiAgICAgIGNvbnN0IG91dHB1dEFkZHJlc3NlcyA9IFsnYWRkcjEnLCAnYWRkcjMnXTtcblxuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHV0aWxzLmluY2x1ZGVJbih3YWxsZXRBZGRyZXNzZXMsIG91dHB1dEFkZHJlc3NlcyksIGZhbHNlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmV0dXJuIHRydWUgZm9yIGVtcHR5IHdhbGxldCBhZGRyZXNzZXMnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB3YWxsZXRBZGRyZXNzZXM6IHN0cmluZ1tdID0gW107XG4gICAgICBjb25zdCBvdXRwdXRBZGRyZXNzZXMgPSBbJ2FkZHIxJywgJ2FkZHIyJ107XG5cbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCh1dGlscy5pbmNsdWRlSW4od2FsbGV0QWRkcmVzc2VzLCBvdXRwdXRBZGRyZXNzZXMpLCB0cnVlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmV0dXJuIGZhbHNlIHdoZW4gd2FsbGV0IGFkZHJlc3Mgbm90IGZvdW5kIGluIGVtcHR5IG91dHB1dCBhZGRyZXNzZXMnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB3YWxsZXRBZGRyZXNzZXMgPSBbJ2FkZHIxJ107XG4gICAgICBjb25zdCBvdXRwdXRBZGRyZXNzZXM6IHN0cmluZ1tdID0gW107XG5cbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCh1dGlscy5pbmNsdWRlSW4od2FsbGV0QWRkcmVzc2VzLCBvdXRwdXRBZGRyZXNzZXMpLCBmYWxzZSk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdpc1ZhbGlkQWRkcmVzcycsIGZ1bmN0aW9uICgpIHtcbiAgICBpdCgnc2hvdWxkIHZhbGlkYXRlIHNpbmdsZSB2YWxpZCBGbGFyZSBhZGRyZXNzZXMnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAvLyBGbGFyZSBhZGRyZXNzZXMgc3RhcnQgd2l0aCAnZmxhcmU6JyBvciAnQy1mbGFyZTonXG4gICAgICBjb25zdCB2YWxpZEFkZHJlc3NlcyA9IFtcbiAgICAgICAgJ2ZsYXJlMXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXE2ZjRhdmgnLFxuICAgICAgICAnQy1mbGFyZTFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxNmY0YXZoJyxcbiAgICAgIF07XG5cbiAgICAgIHZhbGlkQWRkcmVzc2VzLmZvckVhY2goKGFkZHIpID0+IHtcbiAgICAgICAgLy8gTm90ZTogVGhlIGN1cnJlbnQgaW1wbGVtZW50YXRpb24gdXNlcyByZWdleCB2YWxpZGF0aW9uXG4gICAgICAgIC8vIFRoaXMgdGVzdCB3aWxsIGJlIHVwZGF0ZWQgb25jZSBwcm9wZXIgRmxhcmUgYWRkcmVzcyB2YWxpZGF0aW9uIGlzIGltcGxlbWVudGVkXG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IHV0aWxzLmlzVmFsaWRBZGRyZXNzKGFkZHIpO1xuICAgICAgICAvLyBDdXJyZW50bHkgcmV0dXJucyBmYWxzZSBkdWUgdG8gcGxhY2Vob2xkZXIgaW1wbGVtZW50YXRpb25cbiAgICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHR5cGVvZiByZXN1bHQsICdib29sZWFuJyk7XG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdmFsaWRhdGUgYXJyYXkgb2YgYWRkcmVzc2VzJywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgYWRkcmVzc2VzID0gW1xuICAgICAgICAnZmxhcmUxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcTZmNGF2aCcsXG4gICAgICAgICdmbGFyZTFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYTZmNGF2aCcsXG4gICAgICBdO1xuXG4gICAgICBjb25zdCByZXN1bHQgPSB1dGlscy5pc1ZhbGlkQWRkcmVzcyhhZGRyZXNzZXMpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHR5cGVvZiByZXN1bHQsICdib29sZWFuJyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHZhbGlkYXRlIGFkZHJlc3NlcyBzZXBhcmF0ZWQgYnkgficsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGFkZHJlc3NTdHJpbmcgPVxuICAgICAgICAnZmxhcmUxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcTZmNGF2aH5mbGFyZTFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYTZmNGF2aCc7XG5cbiAgICAgIGNvbnN0IHJlc3VsdCA9IHV0aWxzLmlzVmFsaWRBZGRyZXNzKGFkZHJlc3NTdHJpbmcpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHR5cGVvZiByZXN1bHQsICdib29sZWFuJyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJlamVjdCBvYnZpb3VzbHkgaW52YWxpZCBhZGRyZXNzZXMnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBpbnZhbGlkQWRkcmVzc2VzID0gW1xuICAgICAgICAnJyxcbiAgICAgICAgJ2ludmFsaWQnLFxuICAgICAgICAnMTIzJyxcbiAgICAgICAgJ2JpdGNvaW4xcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcScsXG4gICAgICAgICdldGg6MHgxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwJyxcbiAgICAgIF07XG5cbiAgICAgIGludmFsaWRBZGRyZXNzZXMuZm9yRWFjaCgoYWRkcikgPT4ge1xuICAgICAgICBjb25zdCByZXN1bHQgPSB1dGlscy5pc1ZhbGlkQWRkcmVzcyhhZGRyKTtcbiAgICAgICAgLy8gQ3VycmVudCBpbXBsZW1lbnRhdGlvbiBtYXkgbm90IGNhdGNoIGFsbCBpbnZhbGlkIGFkZHJlc3Nlc1xuICAgICAgICBhc3NlcnQuc3RyaWN0RXF1YWwodHlwZW9mIHJlc3VsdCwgJ2Jvb2xlYW4nKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnaXNWYWxpZEFkZHJlc3NSZWdleCcsIGZ1bmN0aW9uICgpIHtcbiAgICBpdCgnc2hvdWxkIHRlc3QgYWRkcmVzcyBmb3JtYXQgd2l0aCByZWdleCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHRlc3RBZGRyZXNzID0gJ2ZsYXJlMXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXE2ZjRhdmgnO1xuICAgICAgY29uc3QgcmVzdWx0ID0gdXRpbHNbJ2lzVmFsaWRBZGRyZXNzUmVnZXgnXSh0ZXN0QWRkcmVzcyk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwodHlwZW9mIHJlc3VsdCwgJ2Jvb2xlYW4nKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmVqZWN0IGVtcHR5IHN0cmluZ3MnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCByZXN1bHQgPSB1dGlsc1snaXNWYWxpZEFkZHJlc3NSZWdleCddKCcnKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChyZXN1bHQsIGZhbHNlKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ2lzVmFsaWRUcmFuc2FjdGlvbklkJywgZnVuY3Rpb24gKCkge1xuICAgIGl0KCdzaG91bGQgdGhyb3cgTm90SW1wbGVtZW50ZWRFcnJvcicsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGFzc2VydC50aHJvd3MoXG4gICAgICAgICgpID0+IHV0aWxzLmlzVmFsaWRUcmFuc2FjdGlvbklkKCd0eGlkMTIzJyksXG4gICAgICAgIE5vdEltcGxlbWVudGVkRXJyb3IsXG4gICAgICAgICdpc1ZhbGlkVHJhbnNhY3Rpb25JZCBub3QgaW1wbGVtZW50ZWQnXG4gICAgICApO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnaXNWYWxpZFNpZ25hdHVyZScsIGZ1bmN0aW9uICgpIHtcbiAgICBpdCgnc2hvdWxkIHRocm93IE5vdEltcGxlbWVudGVkRXJyb3InLCBmdW5jdGlvbiAoKSB7XG4gICAgICBhc3NlcnQudGhyb3dzKFxuICAgICAgICAoKSA9PiB1dGlscy5pc1ZhbGlkU2lnbmF0dXJlKCdzaWduYXR1cmUxMjMnKSxcbiAgICAgICAgTm90SW1wbGVtZW50ZWRFcnJvcixcbiAgICAgICAgJ2lzVmFsaWRTaWduYXR1cmUgbm90IGltcGxlbWVudGVkJ1xuICAgICAgKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ2NyZWF0ZVNpZ25hdHVyZScsIGZ1bmN0aW9uICgpIHtcbiAgICBpdCgnc2hvdWxkIGNyZWF0ZSBzaWduYXR1cmUgdXNpbmcgc2VjcDI1NmsxJywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgbmV0d29yayA9IGNvaW5zLmdldCgnZmxycCcpLm5ldHdvcmsgYXMgRmxhcmVOZXR3b3JrO1xuICAgICAgY29uc3QgbWVzc2FnZSA9IEJ1ZmZlci5mcm9tKCdoZWxsbyB3b3JsZCcsICd1dGY4Jyk7XG4gICAgICBjb25zdCBwcml2YXRlS2V5ID0gQnVmZmVyLmZyb20oJzAxMjM0NTY3ODlhYmNkZWYwMTIzNDU2Nzg5YWJjZGVmMDEyMzQ1Njc4OWFiY2RlZjAxMjM0NTY3ODlhYmNkZWYnLCAnaGV4Jyk7XG5cbiAgICAgIGNvbnN0IHNpZ25hdHVyZSA9IHV0aWxzLmNyZWF0ZVNpZ25hdHVyZShuZXR3b3JrLCBtZXNzYWdlLCBwcml2YXRlS2V5KTtcblxuICAgICAgYXNzZXJ0Lm9rKHNpZ25hdHVyZSBpbnN0YW5jZW9mIEJ1ZmZlcik7XG4gICAgICBhc3NlcnQub2soc2lnbmF0dXJlLmxlbmd0aCA+IDApO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBjcmVhdGUgZGlmZmVyZW50IHNpZ25hdHVyZXMgZm9yIGRpZmZlcmVudCBtZXNzYWdlcycsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IG5ldHdvcmsgPSBjb2lucy5nZXQoJ2ZscnAnKS5uZXR3b3JrIGFzIEZsYXJlTmV0d29yaztcbiAgICAgIGNvbnN0IG1lc3NhZ2UxID0gQnVmZmVyLmZyb20oJ21lc3NhZ2UgMScsICd1dGY4Jyk7XG4gICAgICBjb25zdCBtZXNzYWdlMiA9IEJ1ZmZlci5mcm9tKCdtZXNzYWdlIDInLCAndXRmOCcpO1xuICAgICAgY29uc3QgcHJpdmF0ZUtleSA9IEJ1ZmZlci5mcm9tKCcwMTIzNDU2Nzg5YWJjZGVmMDEyMzQ1Njc4OWFiY2RlZjAxMjM0NTY3ODlhYmNkZWYwMTIzNDU2Nzg5YWJjZGVmJywgJ2hleCcpO1xuXG4gICAgICBjb25zdCBzaWcxID0gdXRpbHMuY3JlYXRlU2lnbmF0dXJlKG5ldHdvcmssIG1lc3NhZ2UxLCBwcml2YXRlS2V5KTtcbiAgICAgIGNvbnN0IHNpZzIgPSB1dGlscy5jcmVhdGVTaWduYXR1cmUobmV0d29yaywgbWVzc2FnZTIsIHByaXZhdGVLZXkpO1xuXG4gICAgICBhc3NlcnQubm90RGVlcFN0cmljdEVxdWFsKHNpZzEsIHNpZzIpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0aHJvdyBlcnJvciBmb3IgaW52YWxpZCBwcml2YXRlIGtleScsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IG5ldHdvcmsgPSBjb2lucy5nZXQoJ2ZscnAnKS5uZXR3b3JrIGFzIEZsYXJlTmV0d29yaztcbiAgICAgIGNvbnN0IG1lc3NhZ2UgPSBCdWZmZXIuZnJvbSgnaGVsbG8gd29ybGQnLCAndXRmOCcpO1xuICAgICAgY29uc3QgaW52YWxpZFByaXZhdGVLZXkgPSBCdWZmZXIuZnJvbSgnaW52YWxpZCcsICd1dGY4Jyk7XG5cbiAgICAgIGFzc2VydC50aHJvd3MoKCkgPT4gdXRpbHMuY3JlYXRlU2lnbmF0dXJlKG5ldHdvcmssIG1lc3NhZ2UsIGludmFsaWRQcml2YXRlS2V5KSwgL0ZhaWxlZCB0byBjcmVhdGUgc2lnbmF0dXJlLyk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCd2ZXJpZnlTaWduYXR1cmUnLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ3Nob3VsZCB2ZXJpZnkgdmFsaWQgc2lnbmF0dXJlJywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgbmV0d29yayA9IGNvaW5zLmdldCgnZmxycCcpLm5ldHdvcmsgYXMgRmxhcmVOZXR3b3JrO1xuICAgICAgY29uc3QgbWVzc2FnZSA9IEJ1ZmZlci5mcm9tKCdoZWxsbyB3b3JsZCcsICd1dGY4Jyk7XG4gICAgICBjb25zdCBwcml2YXRlS2V5ID0gQnVmZmVyLmZyb20oJzAxMjM0NTY3ODlhYmNkZWYwMTIzNDU2Nzg5YWJjZGVmMDEyMzQ1Njc4OWFiY2RlZjAxMjM0NTY3ODlhYmNkZWYnLCAnaGV4Jyk7XG5cbiAgICAgIC8vIENyZWF0ZSBzaWduYXR1cmVcbiAgICAgIGNvbnN0IHNpZ25hdHVyZSA9IHV0aWxzLmNyZWF0ZVNpZ25hdHVyZShuZXR3b3JrLCBtZXNzYWdlLCBwcml2YXRlS2V5KTtcblxuICAgICAgLy8gR2V0IHB1YmxpYyBrZXkgKHRoaXMgd291bGQgbm9ybWFsbHkgY29tZSBmcm9tIHRoZSBwcml2YXRlIGtleSlcbiAgICAgIC8vIEZvciB0ZXN0aW5nLCB3ZSdsbCB1c2UgYSBtb2NrIHB1YmxpYyBrZXkgYXBwcm9hY2hcbiAgICAgIGNvbnN0IHB1YmxpY0tleSA9IEJ1ZmZlci5mcm9tKCcwMicgKyAnMCcucmVwZWF0KDYyKSwgJ2hleCcpOyAvLyBDb21wcmVzc2VkIHB1YmxpYyBrZXkgZm9ybWF0XG5cbiAgICAgIC8vIE5vdGU6IFRoaXMgdGVzdCBtYXkgZmFpbCBpZiB0aGUgcHVibGljIGtleSBkb2Vzbid0IG1hdGNoIHRoZSBwcml2YXRlIGtleVxuICAgICAgLy8gSW4gYSByZWFsIGltcGxlbWVudGF0aW9uLCB5b3UnZCBkZXJpdmUgdGhlIHB1YmxpYyBrZXkgZnJvbSB0aGUgcHJpdmF0ZSBrZXlcbiAgICAgIC8vIFRoZSBtZXRob2QgcmV0dXJucyBmYWxzZSB3aGVuIHZlcmlmaWNhdGlvbiBmYWlscyBpbnN0ZWFkIG9mIHRocm93aW5nXG4gICAgICBjb25zdCBpc1ZhbGlkID0gdXRpbHMudmVyaWZ5U2lnbmF0dXJlKG5ldHdvcmssIG1lc3NhZ2UsIHNpZ25hdHVyZSwgcHVibGljS2V5KTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCh0eXBlb2YgaXNWYWxpZCwgJ2Jvb2xlYW4nKTtcbiAgICAgIC8vIFdpdGggbW9jayBwdWJsaWMga2V5LCB0aGlzIHNob3VsZCByZXR1cm4gZmFsc2VcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChpc1ZhbGlkLCBmYWxzZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJldHVybiBmYWxzZSBmb3IgaW52YWxpZCBzaWduYXR1cmUnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBuZXR3b3JrID0gY29pbnMuZ2V0KCdmbHJwJykubmV0d29yayBhcyBGbGFyZU5ldHdvcms7XG4gICAgICBjb25zdCBtZXNzYWdlID0gQnVmZmVyLmZyb20oJ2hlbGxvIHdvcmxkJywgJ3V0ZjgnKTtcbiAgICAgIGNvbnN0IGludmFsaWRTaWduYXR1cmUgPSBCdWZmZXIuZnJvbSgnaW52YWxpZCBzaWduYXR1cmUnLCAndXRmOCcpO1xuICAgICAgY29uc3QgcHVibGljS2V5ID0gQnVmZmVyLmZyb20oJzAyJyArICcwJy5yZXBlYXQoNjIpLCAnaGV4Jyk7XG5cbiAgICAgIC8vIFRoaXMgc2hvdWxkIHJldHVybiBmYWxzZSBkdWUgdG8gaW52YWxpZCBzaWduYXR1cmUgZm9ybWF0XG4gICAgICAvLyBUaGUgbWV0aG9kIGNhdGNoZXMgZXJyb3JzIGludGVybmFsbHkgYW5kIHJldHVybnMgZmFsc2VcbiAgICAgIGNvbnN0IHJlc3VsdCA9IHV0aWxzLnZlcmlmeVNpZ25hdHVyZShuZXR3b3JrLCBtZXNzYWdlLCBpbnZhbGlkU2lnbmF0dXJlLCBwdWJsaWNLZXkpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHJlc3VsdCwgZmFsc2UpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnYWRkcmVzcyBwYXJzaW5nIHV0aWxpdGllcycsIGZ1bmN0aW9uICgpIHtcbiAgICBpdCgnc2hvdWxkIGhhbmRsZSBhZGRyZXNzIHNlcGFyYXRvciBjb25zdGFudHMnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB7IEFERFJFU1NfU0VQQVJBVE9SIH0gPSByZXF1aXJlKCcuLi8uLi8uLi9zcmMvbGliL2lmYWNlJyk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoQUREUkVTU19TRVBBUkFUT1IsICd+Jyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGhhbmRsZSBpbnB1dCBzZXBhcmF0b3IgY29uc3RhbnRzJywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgeyBJTlBVVF9TRVBBUkFUT1IgfSA9IHJlcXVpcmUoJy4uLy4uLy4uL3NyYy9saWIvaWZhY2UnKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChJTlBVVF9TRVBBUkFUT1IsICc6Jyk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdlcnJvciBoYW5kbGluZycsIGZ1bmN0aW9uICgpIHtcbiAgICBpdCgnc2hvdWxkIHByb3Blcmx5IGV4dGVuZCBiYXNlIHV0aWxzJywgZnVuY3Rpb24gKCkge1xuICAgICAgLy8gVGVzdCB0aGF0IHV0aWxzIGNsYXNzIGV4aXN0cyBhbmQgaGFzIGV4cGVjdGVkIG1ldGhvZHNcbiAgICAgIGFzc2VydC5vaygnaXNWYWxpZEFkZHJlc3MnIGluIHV0aWxzKTtcbiAgICAgIGFzc2VydC5vaygnaW5jbHVkZUluJyBpbiB1dGlscyk7XG4gICAgICBhc3NlcnQub2soJ2NyZWF0ZVNpZ25hdHVyZScgaW4gdXRpbHMpO1xuICAgICAgYXNzZXJ0Lm9rKCd2ZXJpZnlTaWduYXR1cmUnIGluIHV0aWxzKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgaGFuZGxlIHBhcnNpbmcgZXJyb3JzIGdyYWNlZnVsbHknLCBmdW5jdGlvbiAoKSB7XG4gICAgICAvLyBUZXN0IHRoYXQgdXRpbHMgY2FuIGhhbmRsZSBtYWxmb3JtZWQgaW5wdXQgd2l0aG91dCBjcmFzaGluZ1xuICAgICAgLy8gTm90ZTogVGhlc2UgbWF5IHRocm93IGVycm9ycywgd2hpY2ggaXMgYWNjZXB0YWJsZSBiZWhhdmlvclxuICAgICAgdHJ5IHtcbiAgICAgICAgdXRpbHMuaXNWYWxpZEFkZHJlc3MobnVsbCBhcyB1bmtub3duIGFzIHN0cmluZyk7XG4gICAgICAgIHV0aWxzLmlzVmFsaWRBZGRyZXNzKHVuZGVmaW5lZCBhcyB1bmtub3duIGFzIHN0cmluZyk7XG4gICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAvLyBFeHBlY3RlZCBiZWhhdmlvciAtIHV0aWxzIHNob3VsZCBoYW5kbGUgb3IgdGhyb3cgbWVhbmluZ2Z1bCBlcnJvcnNcbiAgICAgICAgYXNzZXJ0Lm9rKGVycm9yIGluc3RhbmNlb2YgRXJyb3IpO1xuICAgICAgfVxuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnY29uc3RhbnRzIHZhbGlkYXRpb24nLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ3Nob3VsZCBoYXZlIGNvcnJlY3QgY29uc3RhbnQgdmFsdWVzJywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgY29uc3RhbnRzID0gcmVxdWlyZSgnLi4vLi4vLi4vc3JjL2xpYi9jb25zdGFudHMnKTtcblxuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHR5cGVvZiBjb25zdGFudHMuREVDT0RFRF9CTE9DS19JRF9MRU5HVEgsICdudW1iZXInKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCh0eXBlb2YgY29uc3RhbnRzLlNIT1JUX1BVQl9LRVlfTEVOR1RILCAnbnVtYmVyJyk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwodHlwZW9mIGNvbnN0YW50cy5DT01QUkVTU0VEX1BVQkxJQ19LRVlfTEVOR1RILCAnbnVtYmVyJyk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwodHlwZW9mIGNvbnN0YW50cy5VTkNPTVBSRVNTRURfUFVCTElDX0tFWV9MRU5HVEgsICdudW1iZXInKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCh0eXBlb2YgY29uc3RhbnRzLlJBV19QUklWQVRFX0tFWV9MRU5HVEgsICdudW1iZXInKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCh0eXBlb2YgY29uc3RhbnRzLlNVRkZJWEVEX1BSSVZBVEVfS0VZX0xFTkdUSCwgJ251bWJlcicpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHR5cGVvZiBjb25zdGFudHMuUFJJVkFURV9LRVlfQ09NUFJFU1NFRF9TVUZGSVgsICdzdHJpbmcnKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCh0eXBlb2YgY29uc3RhbnRzLk9VVFBVVF9JTkRFWF9IRVhfTEVOR1RILCAnbnVtYmVyJyk7XG4gICAgICBhc3NlcnQub2soY29uc3RhbnRzLkFERFJFU1NfUkVHRVggaW5zdGFuY2VvZiBSZWdFeHApO1xuICAgICAgYXNzZXJ0Lm9rKGNvbnN0YW50cy5IRVhfUkVHRVggaW5zdGFuY2VvZiBSZWdFeHApO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnTWVtbyBVdGlsaXRpZXMnLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ3Nob3VsZCBjb252ZXJ0IHN0cmluZyB0byBieXRlcycsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHRleHQgPSAnSGVsbG8gRmxhcmUnO1xuICAgICAgY29uc3QgYnl0ZXMgPSB1dGlscy5zdHJpbmdUb0J5dGVzKHRleHQpO1xuXG4gICAgICBhc3NlcnQub2soYnl0ZXMgaW5zdGFuY2VvZiBVaW50OEFycmF5KTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCh1dGlscy5ieXRlc1RvU3RyaW5nKGJ5dGVzKSwgdGV4dCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGhhbmRsZSBVVEYtOCBzdHJpbmdzJywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgdGV4dCA9ICdIZWxsbyDkuJbnlYwg8J+MjSc7XG4gICAgICBjb25zdCBieXRlcyA9IHV0aWxzLnN0cmluZ1RvQnl0ZXModGV4dCk7XG5cbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCh1dGlscy5ieXRlc1RvU3RyaW5nKGJ5dGVzKSwgdGV4dCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGNyZWF0ZSBtZW1vIGJ5dGVzIGZyb20gc3RyaW5nJywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgdGV4dCA9ICdNZW1vIHRleHQnO1xuICAgICAgY29uc3QgYnl0ZXMgPSB1dGlscy5jcmVhdGVNZW1vQnl0ZXModGV4dCk7XG5cbiAgICAgIGFzc2VydC5vayhieXRlcyBpbnN0YW5jZW9mIFVpbnQ4QXJyYXkpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHV0aWxzLnBhcnNlTWVtb0J5dGVzKGJ5dGVzKSwgdGV4dCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGNyZWF0ZSBtZW1vIGJ5dGVzIGZyb20gSlNPTiBvYmplY3QnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBvYmogPSB7IHR5cGU6ICdwYXltZW50JywgYW1vdW50OiAxMDAwIH07XG4gICAgICBjb25zdCBieXRlcyA9IHV0aWxzLmNyZWF0ZU1lbW9CeXRlcyhvYmopO1xuICAgICAgY29uc3QgcGFyc2VkID0gdXRpbHMucGFyc2VNZW1vQnl0ZXMoYnl0ZXMpO1xuXG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwocGFyc2VkLCBKU09OLnN0cmluZ2lmeShvYmopKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgaGFuZGxlIFVpbnQ4QXJyYXkgaW5wdXQnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBvcmlnaW5hbEJ5dGVzID0gbmV3IFVpbnQ4QXJyYXkoWzEsIDIsIDMsIDRdKTtcbiAgICAgIGNvbnN0IGJ5dGVzID0gdXRpbHMuY3JlYXRlTWVtb0J5dGVzKG9yaWdpbmFsQnl0ZXMpO1xuXG4gICAgICBhc3NlcnQuZGVlcFN0cmljdEVxdWFsKGJ5dGVzLCBvcmlnaW5hbEJ5dGVzKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdGhyb3cgZXJyb3IgZm9yIGludmFsaWQgbWVtbyB0eXBlJywgZnVuY3Rpb24gKCkge1xuICAgICAgYXNzZXJ0LnRocm93cygoKSA9PiB7XG4gICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZXhwbGljaXQtYW55XG4gICAgICAgIHV0aWxzLmNyZWF0ZU1lbW9CeXRlcygxMjMgYXMgYW55KTtcbiAgICAgIH0sIC9JbnZhbGlkIG1lbW8gZm9ybWF0Lyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHBhcnNlIGVtcHR5IG1lbW8nLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBlbXB0eUJ5dGVzID0gbmV3IFVpbnQ4QXJyYXkoW10pO1xuICAgICAgY29uc3QgcGFyc2VkID0gdXRpbHMucGFyc2VNZW1vQnl0ZXMoZW1wdHlCeXRlcyk7XG5cbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChwYXJzZWQsICcnKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdmFsaWRhdGUgbWVtbyBzaXplJywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgc21hbGxNZW1vID0gbmV3IFVpbnQ4QXJyYXkoWzEsIDIsIDNdKTtcbiAgICAgIGNvbnN0IGxhcmdlTWVtbyA9IG5ldyBVaW50OEFycmF5KDUwMDApO1xuXG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwodXRpbHMudmFsaWRhdGVNZW1vU2l6ZShzbWFsbE1lbW8pLCB0cnVlKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCh1dGlscy52YWxpZGF0ZU1lbW9TaXplKGxhcmdlTWVtbyksIGZhbHNlKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCh1dGlscy52YWxpZGF0ZU1lbW9TaXplKGxhcmdlTWVtbywgNjAwMCksIHRydWUpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBoYW5kbGUgc3BlY2lhbCBjaGFyYWN0ZXJzIGluIG1lbW8nLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBzcGVjaWFsVGV4dCA9ICdTcGVjaWFsOiBcXG5cXHRcXHJcXDAnO1xuICAgICAgY29uc3QgYnl0ZXMgPSB1dGlscy5jcmVhdGVNZW1vQnl0ZXMoc3BlY2lhbFRleHQpO1xuICAgICAgY29uc3QgcGFyc2VkID0gdXRpbHMucGFyc2VNZW1vQnl0ZXMoYnl0ZXMpO1xuXG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwocGFyc2VkLCBzcGVjaWFsVGV4dCk7XG4gICAgfSk7XG4gIH0pO1xufSk7XG4iXX0=
680
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi90ZXN0L3VuaXQvbGliL3V0aWxzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsaURBQTBEO0FBQzFELCtDQUFpQztBQUNqQyxrREFBK0M7QUFDL0MscURBT2lDO0FBQ2pDLHFEQUE0QztBQUM1Qyx5RUFBd0U7QUFDeEUseUVBQXdFO0FBQ3hFLHlFQUF3RTtBQUN4RSx5RUFBd0U7QUFDeEUsMENBQTBFO0FBQzFFLG1EQUFpRTtBQUVqRSxRQUFRLENBQUMsT0FBTyxFQUFFO0lBQ2hCLElBQUksS0FBWSxDQUFDO0lBQ2pCLE1BQU0sT0FBTyxHQUFHLGVBQUssQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUMsT0FBdUIsQ0FBQztJQUUxRCxVQUFVLENBQUM7UUFDVCxLQUFLLEdBQUcsSUFBSSxhQUFLLEVBQUUsQ0FBQztJQUN0QixDQUFDLENBQUMsQ0FBQztJQUVILFFBQVEsQ0FBQyxlQUFlLEVBQUU7UUFDeEIsTUFBTSxPQUFPLEdBQUcsbURBQW1ELENBQUM7UUFFcEUsRUFBRSxDQUFDLCtDQUErQyxFQUFFO1lBQ2xELE1BQU0sV0FBVyxHQUFHO2dCQUNsQixRQUFRLEVBQUUsQ0FBQztnQkFDWCxNQUFNLEVBQUUsVUFBVTtnQkFDbEIsSUFBSSxFQUFFLG9EQUFvRDtnQkFDMUQsU0FBUyxFQUFFLENBQUM7Z0JBQ1osU0FBUyxFQUFFO29CQUNULGlEQUFpRDtvQkFDakQsaURBQWlEO29CQUNqRCxpREFBaUQ7aUJBQ2xEO2dCQUNELFNBQVMsRUFBRSxHQUFHO2dCQUNkLFFBQVEsRUFBRSxHQUFHO2FBQ2QsQ0FBQztZQUVGLE1BQU0sYUFBYSxHQUFHLEtBQUssQ0FBQyxhQUFhLENBQUMsV0FBVyxFQUFFLE9BQU8sQ0FBQyxDQUFDO1lBRWhFLE1BQU0sQ0FBQyxFQUFFLENBQUMsYUFBYSxZQUFZLGNBQUks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QztpQkFDNUIsWUFBWSxDQUFDLHVCQUFXLENBQUMsS0FBSyxDQUFDLENBQUM7WUFFbkMsTUFBTSxFQUFFLEdBQUcsQ0FBQyxNQUFNLFNBQVMsQ0FBQyxLQUFLLEVBQUUsQ0FBZ0IsQ0FBQztZQUNwRCxNQUFNLGdCQUFnQixHQUFHLEVBQUUsQ0FBQyxtQkFBbUIsRUFBRSxDQUFDO1lBRWxELE1BQU0sQ0FBQyxXQUFXLENBQUMsYUFBYSxDQUFDLGVBQWUsQ0FBQyxnQkFBZ0IsRUFBRSxxQkFBcUIsQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDO1FBQ3BHLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGNvaW5zLCBGbGFyZU5ldHdvcmsgfSBmcm9tICdAYml0Z28tYmV0YS9zdGF0aWNzJztcbmltcG9ydCAqIGFzIGFzc2VydCBmcm9tICdhc3NlcnQnO1xuaW1wb3J0IHsgVXRpbHMgfSBmcm9tICcuLi8uLi8uLi9zcmMvbGliL3V0aWxzJztcbmltcG9ydCB7XG4gIFNFRURfQUNDT1VOVCxcbiAgQUNDT1VOVF8xLFxuICBBQ0NPVU5UXzIsXG4gIEFDQ09VTlRfMyxcbiAgSU5WQUxJRF9TSE9SVF9LRVlQQUlSX0tFWSxcbiAgSU5WQUxJRF9MT05HX0tFWVBBSVJfUFJWLFxufSBmcm9tICcuLi8uLi9yZXNvdXJjZXMvYWNjb3VudCc7XG5pbXBvcnQgeyBlY2MgfSBmcm9tICdAYml0Z28tYmV0YS9zZWNwMjU2azEnO1xuaW1wb3J0IHsgRVhQT1JUX0lOX0MgfSBmcm9tICcuLi8uLi9yZXNvdXJjZXMvdHJhbnNhY3Rpb25EYXRhL2V4cG9ydEluQyc7XG5pbXBvcnQgeyBJTVBPUlRfSU5fUCB9IGZyb20gJy4uLy4uL3Jlc291cmNlcy90cmFuc2FjdGlvbkRhdGEvaW1wb3J0SW5QJztcbmltcG9ydCB7IEVYUE9SVF9JTl9QIH0gZnJvbSAnLi4vLi4vcmVzb3VyY2VzL3RyYW5zYWN0aW9uRGF0YS9leHBvcnRJblAnO1xuaW1wb3J0IHsgSU1QT1JUX0lOX0MgfSBmcm9tICcuLi8uLi9yZXNvdXJjZXMvdHJhbnNhY3Rpb25EYXRhL2ltcG9ydEluQyc7XG5pbXBvcnQgeyBUcmFuc2FjdGlvbkJ1aWxkZXJGYWN0b3J5LCBUcmFuc2FjdGlvbiB9IGZyb20gJy4uLy4uLy4uL3NyYy9saWInO1xuaW1wb3J0IHsgc2VjcDI1NmsxLCBBZGRyZXNzLCBVdHhvIH0gZnJvbSAnQGZsYXJlbmV0d29yay9mbGFyZWpzJztcblxuZGVzY3JpYmUoJ1V0aWxzJywgZnVuY3Rpb24gKCkge1xuICBsZXQgdXRpbHM6IFV0aWxzO1xuICBjb25zdCBuZXR3b3JrID0gY29pbnMuZ2V0KCdmbHJwJykubmV0d29yayBhcyBGbGFyZU5ldHdvcms7XG5cbiAgYmVmb3JlRWFjaChmdW5jdGlvbiAoKSB7XG4gICAgdXRpbHMgPSBuZXcgVXRpbHMoKTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ2RlY29kZWRUb1V0eG8nLCBmdW5jdGlvbiAoKSB7XG4gICAgY29uc3QgYXNzZXRJZCA9ICdmeE1BS3BCUVFwRmVkclVoV01zRFlmQ1VKeGRVdzRtbmVUY3pLQnpOZzNyYzJKVXViJztcblxuICAgIGl0KCdzaG91bGQgY29udmVydCBEZWNvZGVkVXR4b09iaiB0byBGbGFyZUpTIFV0eG8nLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBkZWNvZGVkVXR4byA9IHtcbiAgICAgICAgb3V0cHV0SUQ6IDcsXG4gICAgICAgIGFtb3VudDogJzUwMDAwMDAwJyxcbiAgICAgICAgdHhpZDogJzJYSjFNcHRwbUJXVkZTekN6NDRqYXVHTG9vb1NGU2haSk04YXlrU0wxZGZWSGVoRmpuJyxcbiAgICAgICAgdGhyZXNob2xkOiAyLFxuICAgICAgICBhZGRyZXNzZXM6IFtcbiAgICAgICAgICAnUC1jb3N0d28xeHY1bXVsZ3BlNWx0NHRueDJudG55bHdlNzlhenU5dnBqYTZsdXQnLFxuICAgICAgICAgICdQLWNvc3R3bzEwNmdjNWg1cXN3aHllOGUwcG10aHE0d3pmMGVrdjVxcHBzcnZwdScsXG4gICAgICAgICAgJ1AtY29zdHdvMWN1ZXlnZDdmZDM3ZzU2czQ5azNyc2hxYWtocDZrOHUzYWR6dDZtJyxcbiAgICAgICAgXSxcbiAgICAgICAgb3V0cHV0aWR4OiAnMCcsXG4gICAgICAgIGxvY2t0aW1lOiAnMCcsXG4gICAgICB9O1xuXG4gICAgICBjb25zdCBjb252ZXJ0ZWRVdHhvID0gdXRpbHMuZGVjb2RlZFRvVXR4byhkZWNvZGVkVXR4bywgYXNzZXRJZCk7XG5cbiAgICAgIGFzc2VydC5vayhjb252ZXJ0ZWRVdHhvIGluc3RhbmNlb2YgVXR4byk7XG4gICAgICBhc3NlcnQub2soY29udmVydGVkVXR4by51dHhvSWQsICd1dHhvSWQgc2hvdWxkIGV4aXN0Jyk7XG4gICAgICBhc3NlcnQub2soY29udmVydGVkVXR4by5hc3NldElkLCAnYXNzZXRJZCBzaG91bGQgZXhpc3QnKTtcbiAgICAgIGFzc2VydC5vayhjb252ZXJ0ZWRVdHhvLm91dHB1dCwgJ291dHB1dCBzaG91bGQgZXhpc3QnKTtcblxuICAgICAgY29uc3QgZXhwZWN0ZWRUeElkSGV4ID0gJ2M4N2IwNDU1ZGU3YmExYTdhM2NhNTA4ZjJkZjhkOWY1NDQ4OGI0ODZhODYwMGFhMjA3MjI5Njc4ZWUxM2JiODQnO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKEJ1ZmZlci5mcm9tKGNvbnZlcnRlZFV0eG8udXR4b0lkLnR4SUQudG9CeXRlcygpKS50b1N0cmluZygnaGV4JyksIGV4cGVjdGVkVHhJZEhleCk7XG5cbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChOdW1iZXIoY29udmVydGVkVXR4by51dHhvSWQub3V0cHV0SWR4LnZhbHVlKCkpLCAwKTtcblxuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKChjb252ZXJ0ZWRVdHhvLm91dHB1dCBhcyBhbnkpLmFtb3VudCgpLnRvU3RyaW5nKCksICc1MDAwMDAwMCcpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBjb252ZXJ0IGFycmF5IG9mIERlY29kZWRVdHhvT2JqIHRvIEZsYXJlSlMgVXR4byBhcnJheScsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGRlY29kZWRVdHhvcyA9IFtcbiAgICAgICAge1xuICAgICAgICAgIG91dHB1dElEOiA3LFxuICAgICAgICAgIGFtb3VudDogJzUwMDAwMDAwJyxcbiAgICAgICAgICB0eGlkOiAnMlhKMU1wdHBtQldWRlN6Q3o0NGphdUdMb29vU0ZTaFpKTThheWtTTDFkZlZIZWhGam4nLFxuICAgICAgICAgIHRocmVzaG9sZDogMixcbiAgICAgICAgICBhZGRyZXNzZXM6IFtcbiAgICAgICAgICAgICdQLWNvc3R3bzF4djVtdWxncGU1bHQ0dG54Mm50bnlsd2U3OWF6dTl2cGphNmx1dCcsXG4gICAgICAgICAgICAnUC1jb3N0d28xMDZnYzVoNXFzd2h5ZThlMHBtdGhxNHd6ZjBla3Y1cXBwc3J2cHUnLFxuICAgICAgICAgICAgJ1AtY29zdHdvMWN1ZXlnZDdmZDM3ZzU2czQ5azNyc2hxYWtocDZrOHUzYWR6dDZtJyxcbiAgICAgICAgICBdLFxuICAgICAgICAgIG91dHB1dGlkeDogJzAnLFxuICAgICAgICAgIGxvY2t0aW1lOiAnMCcsXG4gICAgICAgIH0sXG4gICAgICBdO1xuXG4gICAgICBjb25zdCBjb252ZXJ0ZWRVdHhvcyA9IHV0aWxzLmRlY29kZWRUb1V0eG9zKGRlY29kZWRVdHhvcywgYXNzZXRJZCk7XG5cbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChjb252ZXJ0ZWRVdHhvcy5sZW5ndGgsIDEpO1xuICAgICAgYXNzZXJ0Lm9rKGNvbnZlcnRlZFV0eG9zWzBdIGluc3RhbmNlb2YgVXR4byk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoKGNvbnZlcnRlZFV0eG9zWzBdLm91dHB1dCBhcyBhbnkpLmFtb3VudCgpLnRvU3RyaW5nKCksICc1MDAwMDAwMCcpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBoYW5kbGUgbG9ja3RpbWUgY29ycmVjdGx5JywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgZGVjb2RlZFV0eG8gPSB7XG4gICAgICAgIG91dHB1dElEOiA3LFxuICAgICAgICBhbW91bnQ6ICcxMDAwMDAwMDAnLFxuICAgICAgICB0eGlkOiAnMlhKMU1wdHBtQldWRlN6Q3o0NGphdUdMb29vU0ZTaFpKTThheWtTTDFkZlZIZWhGam4nLFxuICAgICAgICB0aHJlc2hvbGQ6IDIsXG4gICAgICAgIGFkZHJlc3NlczogWydQLWNvc3R3bzF4djVtdWxncGU1bHQ0dG54Mm50bnlsd2U3OWF6dTl2cGphNmx1dCddLFxuICAgICAgICBvdXRwdXRpZHg6ICcxJyxcbiAgICAgICAgbG9ja3RpbWU6ICcxNzA0MDY3MjAwJyxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IGNvbnZlcnRlZFV0eG8gPSB1dGlscy5kZWNvZGVkVG9VdHhvKGRlY29kZWRVdHhvLCBhc3NldElkKTtcbiAgICAgIGNvbnN0IG91dHB1dE93bmVycyA9IGNvbnZlcnRlZFV0eG8uZ2V0T3V0cHV0T3duZXJzKCk7XG5cbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChvdXRwdXRPd25lcnMubG9ja3RpbWUudmFsdWUoKS50b1N0cmluZygpLCAnMTcwNDA2NzIwMCcpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnaW5jbHVkZUluJywgZnVuY3Rpb24gKCkge1xuICAgIGl0KCdzaG91bGQgcmV0dXJuIHRydWUgd2hlbiBhbGwgd2FsbGV0IGFkZHJlc3NlcyBhcmUgaW4gVVRYTyBvdXRwdXQgYWRkcmVzc2VzJywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgd2FsbGV0QWRkcmVzc2VzID0gW0VYUE9SVF9JTl9DLnBBZGRyZXNzZXNbMF0sIEVYUE9SVF9JTl9DLnBBZGRyZXNzZXNbMV1dO1xuICAgICAgY29uc3QgdXR4b091dHB1dEFkZHJlc3NlcyA9IFsuLi5FWFBPUlRfSU5fQy5wQWRkcmVzc2VzXTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCh1dGlscy5pbmNsdWRlSW4od2FsbGV0QWRkcmVzc2VzLCB1dHhvT3V0cHV0QWRkcmVzc2VzKSwgdHJ1ZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJldHVybiBmYWxzZSB3aGVuIHNvbWUgd2FsbGV0IGFkZHJlc3NlcyBhcmUgbm90IGluIFVUWE8gb3V0cHV0IGFkZHJlc3NlcycsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHdhbGxldEFkZHJlc3NlcyA9IFtFWFBPUlRfSU5fQy5wQWRkcmVzc2VzWzBdLCBBQ0NPVU5UXzMuYWRkcmVzc107XG4gICAgICBjb25zdCB1dHhvT3V0cHV0QWRkcmVzc2VzID0gW0VYUE9SVF9JTl9DLnBBZGRyZXNzZXNbMF0sIEVYUE9SVF9JTl9DLnBBZGRyZXNzZXNbMV1dO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHV0aWxzLmluY2x1ZGVJbih3YWxsZXRBZGRyZXNzZXMsIHV0eG9PdXRwdXRBZGRyZXNzZXMpLCBmYWxzZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJldHVybiB0cnVlIGZvciBlbXB0eSB3YWxsZXQgYWRkcmVzc2VzJywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgd2FsbGV0QWRkcmVzc2VzOiBzdHJpbmdbXSA9IFtdO1xuICAgICAgY29uc3QgdXR4b091dHB1dEFkZHJlc3NlcyA9IFtFWFBPUlRfSU5fQy5wQWRkcmVzc2VzWzBdXTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCh1dGlscy5pbmNsdWRlSW4od2FsbGV0QWRkcmVzc2VzLCB1dHhvT3V0cHV0QWRkcmVzc2VzKSwgdHJ1ZSk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdpc1ZhbGlkQWRkcmVzcycsIGZ1bmN0aW9uICgpIHtcbiAgICBpdCgnc2hvdWxkIHJldHVybiB0cnVlIGZvciB2YWxpZCBtYWlubmV0IFAtY2hhaW4gYWRkcmVzcycsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCh1dGlscy5pc1ZhbGlkQWRkcmVzcyhTRUVEX0FDQ09VTlQuYWRkcmVzc01haW5uZXQpLCB0cnVlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmV0dXJuIHRydWUgZm9yIHZhbGlkIHRlc3RuZXQgUC1jaGFpbiBhZGRyZXNzJywgZnVuY3Rpb24gKCkge1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHV0aWxzLmlzVmFsaWRBZGRyZXNzKFNFRURfQUNDT1VOVC5hZGRyZXNzVGVzdG5ldCksIHRydWUpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCByZXR1cm4gdHJ1ZSBmb3IgdmFsaWQgTm9kZUlEIGFkZHJlc3MnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwodXRpbHMuaXNWYWxpZEFkZHJlc3MoJ05vZGVJRC1hYmMxMjN4eXonKSwgdHJ1ZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJldHVybiB0cnVlIGZvciBhcnJheSBvZiB2YWxpZCBhZGRyZXNzZXMnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwodXRpbHMuaXNWYWxpZEFkZHJlc3MoRVhQT1JUX0lOX0MucEFkZHJlc3NlcyksIHRydWUpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCByZXR1cm4gdHJ1ZSBmb3IgdGlsZGUtc2VwYXJhdGVkIGFkZHJlc3NlcycsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGNvbWJpbmVkID0gRVhQT1JUX0lOX0MucEFkZHJlc3Nlcy5qb2luKCd+Jyk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwodXRpbHMuaXNWYWxpZEFkZHJlc3MoY29tYmluZWQpLCB0cnVlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmV0dXJuIGZhbHNlIGZvciBpbnZhbGlkIGFkZHJlc3MgZm9ybWF0JywgZnVuY3Rpb24gKCkge1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHV0aWxzLmlzVmFsaWRBZGRyZXNzKCdpbnZhbGlkJyksIGZhbHNlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmV0dXJuIGZhbHNlIGZvciBhZGRyZXNzIHdpdGhvdXQgcHJlZml4JywgZnVuY3Rpb24gKCkge1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHV0aWxzLmlzVmFsaWRBZGRyZXNzKCdmbGFyZTFhYmMxMjMnKSwgZmFsc2UpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnaXNWYWxpZEJsb2NrSWQnLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ3Nob3VsZCByZXR1cm4gdHJ1ZSBmb3IgdmFsaWQgMzItYnl0ZSBoZXggYmxvY2sgSUQnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwodXRpbHMuaXNWYWxpZEJsb2NrSWQoU0VFRF9BQ0NPVU5ULnByaXZhdGVLZXkpLCB0cnVlKTsgLy8gNjQgaGV4IGNoYXJzID0gMzIgYnl0ZXNcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmV0dXJuIGZhbHNlIGZvciBpbnZhbGlkIGxlbmd0aCBibG9jayBJRCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCh1dGlscy5pc1ZhbGlkQmxvY2tJZChJTlZBTElEX1NIT1JUX0tFWVBBSVJfS0VZKSwgZmFsc2UpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCByZXR1cm4gZmFsc2UgZm9yIGVtcHR5IGJsb2NrIElEJywgZnVuY3Rpb24gKCkge1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHV0aWxzLmlzVmFsaWRCbG9ja0lkKCcnKSwgZmFsc2UpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnaXNWYWxpZFB1YmxpY0tleScsIGZ1bmN0aW9uICgpIHtcbiAgICBpdCgnc2hvdWxkIHJldHVybiB0cnVlIGZvciB2YWxpZCBjb21wcmVzc2VkIHB1YmxpYyBrZXkgc3RhcnRpbmcgd2l0aCAwMycsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCh1dGlscy5pc1ZhbGlkUHVibGljS2V5KFNFRURfQUNDT1VOVC5wdWJsaWNLZXkpLCB0cnVlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmV0dXJuIHRydWUgZm9yIHZhbGlkIGNvbXByZXNzZWQgcHVibGljIGtleSBzdGFydGluZyB3aXRoIDAyJywgZnVuY3Rpb24gKCkge1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHV0aWxzLmlzVmFsaWRQdWJsaWNLZXkoQUNDT1VOVF8xLnB1YmxpY0tleSksIHRydWUpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCByZXR1cm4gdHJ1ZSBmb3IgYW5vdGhlciB2YWxpZCBjb21wcmVzc2VkIHB1YmxpYyBrZXknLCBmdW5jdGlvbiAoKSB7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwodXRpbHMuaXNWYWxpZFB1YmxpY0tleShBQ0NPVU5UXzIucHVibGljS2V5KSwgdHJ1ZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJldHVybiB0cnVlIGZvciB2YWxpZCB4cHViJywgZnVuY3Rpb24gKCkge1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHV0aWxzLmlzVmFsaWRQdWJsaWNLZXkoU0VFRF9BQ0NPVU5ULnhQdWJsaWNLZXkpLCB0cnVlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmV0dXJuIHRydWUgZm9yIEFDQ09VTlRfMSB4cHViJywgZnVuY3Rpb24gKCkge1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHV0aWxzLmlzVmFsaWRQdWJsaWNLZXkoQUNDT1VOVF8xLnhQdWJsaWNLZXkpLCB0cnVlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmV0dXJuIGZhbHNlIGZvciBpbnZhbGlkIHNob3J0IHB1YmxpYyBrZXknLCBmdW5jdGlvbiAoKSB7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwodXRpbHMuaXNWYWxpZFB1YmxpY0tleShJTlZBTElEX1NIT1JUX0tFWVBBSVJfS0VZKSwgZmFsc2UpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCByZXR1cm4gZmFsc2UgZm9yIGNvbXByZXNzZWQga2V5IHdpdGggd3JvbmcgcHJlZml4JywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgaW52YWxpZEtleSA9ICcwNScgKyBTRUVEX0FDQ09VTlQucHJpdmF0ZUtleTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCh1dGlscy5pc1ZhbGlkUHVibGljS2V5KGludmFsaWRLZXkpLCBmYWxzZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJldHVybiBmYWxzZSBmb3Igbm9uLWhleCBwdWJsaWMga2V5JywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgaW52YWxpZEtleSA9ICd6eicgKyBTRUVEX0FDQ09VTlQucHJpdmF0ZUtleTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCh1dGlscy5pc1ZhbGlkUHVibGljS2V5KGludmFsaWRLZXkpLCBmYWxzZSk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdpc1ZhbGlkUHJpdmF0ZUtleScsIGZ1bmN0aW9uICgpIHtcbiAgICBpdCgnc2hvdWxkIHJldHVybiB0cnVlIGZvciB2YWxpZCA2NC1jaGFyIGhleCBwcml2YXRlIGtleScsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCh1dGlscy5pc1ZhbGlkUHJpdmF0ZUtleShTRUVEX0FDQ09VTlQucHJpdmF0ZUtleSksIHRydWUpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCByZXR1cm4gdHJ1ZSBmb3IgQUNDT1VOVF8xIHByaXZhdGUga2V5JywgZnVuY3Rpb24gKCkge1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHV0aWxzLmlzVmFsaWRQcml2YXRlS2V5KEFDQ09VTlRfMS5wcml2YXRlS2V5KSwgdHJ1ZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJldHVybiB0cnVlIGZvciBBQ0NPVU5UXzIgcHJpdmF0ZSBrZXknLCBmdW5jdGlvbiAoKSB7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwodXRpbHMuaXNWYWxpZFByaXZhdGVLZXkoQUNDT1VOVF8yLnByaXZhdGVLZXkpLCB0cnVlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmV0dXJuIHRydWUgZm9yIHZhbGlkIHhwcnYnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwodXRpbHMuaXNWYWxpZFByaXZhdGVLZXkoU0VFRF9BQ0NPVU5ULnhQcml2YXRlS2V5KSwgdHJ1ZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJldHVybiB0cnVlIGZvciA2Ni1jaGFyIHByaXZhdGUga2V5IGVuZGluZyB3aXRoIDAxJywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgZXh0ZW5kZWRLZXkgPSBTRUVEX0FDQ09VTlQucHJpdmF0ZUtleSArICcwMSc7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwodXRpbHMuaXNWYWxpZFByaXZhdGVLZXkoZXh0ZW5kZWRLZXkpLCB0cnVlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmV0dXJuIGZhbHNlIGZvciA2Ni1jaGFyIHByaXZhdGUga2V5IG5vdCBlbmRpbmcgd2l0aCAwMScsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCh1dGlscy5pc1ZhbGlkUHJpdmF0ZUtleShJTlZBTElEX0xPTkdfS0VZUEFJUl9QUlYpLCBmYWxzZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJldHVybiBmYWxzZSBmb3IgaW52YWxpZCBzaG9ydCBwcml2YXRlIGtleScsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCh1dGlscy5pc1ZhbGlkUHJpdmF0ZUtleShJTlZBTElEX1NIT1JUX0tFWVBBSVJfS0VZKSwgZmFsc2UpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCByZXR1cm4gZmFsc2UgZm9yIG5vbi1oZXggcHJpdmF0ZSBrZXknLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBpbnZhbGlkS2V5ID0gJ3p6JyArIFNFRURfQUNDT1VOVC5wcml2YXRlS2V5LnNsaWNlKDIpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHV0aWxzLmlzVmFsaWRQcml2YXRlS2V5KGludmFsaWRLZXkpLCBmYWxzZSk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdhbGxIZXhDaGFycycsIGZ1bmN0aW9uICgpIHtcbiAgICBpdCgnc2hvdWxkIHJldHVybiB0cnVlIGZvciB2YWxpZCBwcml2YXRlIGtleSBoZXgnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwodXRpbHMuYWxsSGV4Q2hhcnMoU0VFRF9BQ0NPVU5ULnByaXZhdGVLZXkpLCB0cnVlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmV0dXJuIHRydWUgZm9yIHZhbGlkIHB1YmxpYyBrZXkgaGV4JywgZnVuY3Rpb24gKCkge1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHV0aWxzLmFsbEhleENoYXJzKFNFRURfQUNDT1VOVC5wdWJsaWNLZXkpLCB0cnVlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmV0dXJuIHRydWUgZm9yIGhleCBzdHJpbmcgd2l0aCAweCBwcmVmaXgnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwodXRpbHMuYWxsSGV4Q2hhcnMoRVhQT1JUX0lOX0MuY0hleEFkZHJlc3MpLCB0cnVlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmV0dXJuIHRydWUgZm9yIHZhbGlkIHNpZ25hdHVyZSBoZXgnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwodXRpbHMuYWxsSGV4Q2hhcnMoU0VFRF9BQ0NPVU5ULnNpZ25hdHVyZSksIHRydWUpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCByZXR1cm4gZmFsc2UgZm9yIG5vbi1oZXggY2hhcmFjdGVycycsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCh1dGlscy5hbGxIZXhDaGFycygnZ2hpamtsJyksIGZhbHNlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmV0dXJuIGZhbHNlIGZvciBlbXB0eSBzdHJpbmcnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwodXRpbHMuYWxsSGV4Q2hhcnMoJycpLCBmYWxzZSk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdjcmVhdGVTaWduYXR1cmUgYW5kIHZlcmlmeVNpZ25hdHVyZScsIGZ1bmN0aW9uICgpIHtcbiAgICBpdCgnc2hvdWxkIGNyZWF0ZSBhIHZhbGlkIDY1LWJ5dGUgc2lnbmF0dXJlJywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgbWVzc2FnZSA9IEJ1ZmZlci5mcm9tKFNFRURfQUNDT1VOVC5tZXNzYWdlLCAndXRmOCcpO1xuICAgICAgY29uc3QgcHJpdmF0ZUtleSA9IEJ1ZmZlci5mcm9tKFNFRURfQUNDT1VOVC5wcml2YXRlS2V5LCAnaGV4Jyk7XG5cbiAgICAgIGNvbnN0IHNpZ25hdHVyZSA9IHV0aWxzLmNyZWF0ZVNpZ25hdHVyZShuZXR3b3JrLCBtZXNzYWdlLCBwcml2YXRlS2V5KTtcblxuICAgICAgYXNzZXJ0Lm9rKHNpZ25hdHVyZSBpbnN0YW5jZW9mIEJ1ZmZlcik7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoc2lnbmF0dXJlLmxlbmd0aCwgNjUpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB2ZXJpZnkgYSB2YWxpZCBzaWduYXR1cmUnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBtZXNzYWdlID0gQnVmZmVyLmZyb20oU0VFRF9BQ0NPVU5ULm1lc3NhZ2UsICd1dGY4Jyk7XG4gICAgICBjb25zdCBwcml2YXRlS2V5ID0gQnVmZmVyLmZyb20oU0VFRF9BQ0NPVU5ULnByaXZhdGVLZXksICdoZXgnKTtcbiAgICAgIGNvbnN0IHB1YmxpY0tleSA9IEJ1ZmZlci5mcm9tKFNFRURfQUNDT1VOVC5wdWJsaWNLZXksICdoZXgnKTtcblxuICAgICAgY29uc3Qgc2lnbmF0dXJlID0gdXRpbHMuY3JlYXRlU2lnbmF0dXJlKG5ldHdvcmssIG1lc3NhZ2UsIHByaXZhdGVLZXkpO1xuICAgICAgY29uc3Qgc2lnT25seSA9IHNpZ25hdHVyZS5zbGljZSgwLCA2NCk7XG5cbiAgICAgIGNvbnN0IG1lc3NhZ2VIYXNoID0gdXRpbHMuc2hhMjU2KG1lc3NhZ2UpO1xuICAgICAgY29uc3QgaXNWYWxpZCA9IHV0aWxzLnZlcmlmeVNpZ25hdHVyZShtZXNzYWdlSGFzaCwgc2lnT25seSwgcHVibGljS2V5KTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChpc1ZhbGlkLCB0cnVlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmV0dXJuIGZhbHNlIGZvciBpbnZhbGlkIHNpZ25hdHVyZScsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IG1lc3NhZ2UgPSBCdWZmZXIuZnJvbShTRUVEX0FDQ09VTlQubWVzc2FnZSwgJ3V0ZjgnKTtcbiAgICAgIGNvbnN0IHB1YmxpY0tleSA9IEJ1ZmZlci5mcm9tKFNFRURfQUNDT1VOVC5wdWJsaWNLZXksICdoZXgnKTtcbiAgICAgIGNvbnN0IGludmFsaWRTaWduYXR1cmUgPSBCdWZmZXIuYWxsb2MoNjQpO1xuXG4gICAgICBjb25zdCBtZXNzYWdlSGFzaCA9IHV0aWxzLnNoYTI1NihtZXNzYWdlKTtcbiAgICAgIGNvbnN0IGlzVmFsaWQgPSB1dGlscy52ZXJpZnlTaWduYXR1cmUobWVzc2FnZUhhc2gsIGludmFsaWRTaWduYXR1cmUsIHB1YmxpY0tleSk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoaXNWYWxpZCwgZmFsc2UpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBjcmVhdGUgc2lnbmF0dXJlIHdpdGggQUNDT1VOVF8xIGtleXMnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBtZXNzYWdlID0gQnVmZmVyLmZyb20oU0VFRF9BQ0NPVU5ULm1lc3NhZ2UsICd1dGY4Jyk7XG4gICAgICBjb25zdCBwcml2YXRlS2V5ID0gQnVmZmVyLmZyb20oQUNDT1VOVF8xLnByaXZhdGVLZXksICdoZXgnKTtcblxuICAgICAgY29uc3Qgc2lnbmF0dXJlID0gdXRpbHMuY3JlYXRlU2lnbmF0dXJlKG5ldHdvcmssIG1lc3NhZ2UsIHByaXZhdGVLZXkpO1xuXG4gICAgICBhc3NlcnQub2soc2lnbmF0dXJlIGluc3RhbmNlb2YgQnVmZmVyKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChzaWduYXR1cmUubGVuZ3RoLCA2NSk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdjcmVhdGVOZXdTaWcnLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ3Nob3VsZCBjcmVhdGUgYSBzaWduYXR1cmUgZnJvbSB2YWxpZCBzaWduYXR1cmUgaGV4IHN0cmluZycsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHNpZyA9IHV0aWxzLmNyZWF0ZU5ld1NpZyhTRUVEX0FDQ09VTlQuc2lnbmF0dXJlKTtcbiAgICAgIGFzc2VydC5vayhzaWcpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBjcmVhdGUgYSBzaWduYXR1cmUgZnJvbSBleHBvcnQgc2lnbmF0dXJlIGhleCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHNpZ0hleCA9IHV0aWxzLnJlbW92ZUhleFByZWZpeChFWFBPUlRfSU5fQy5zaWduYXR1cmVbMF0pO1xuICAgICAgY29uc3Qgc2lnID0gdXRpbHMuY3JlYXRlTmV3U2lnKHNpZ0hleCk7XG4gICAgICBhc3NlcnQub2soc2lnKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcGFkIHNob3J0IGhleCBzdHJpbmdzJywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgc2lnSGV4ID0gSU5WQUxJRF9TSE9SVF9LRVlQQUlSX0tFWTtcbiAgICAgIGNvbnN0IHNpZyA9IHV0aWxzLmNyZWF0ZU5ld1NpZyhzaWdIZXgpO1xuICAgICAgYXNzZXJ0Lm9rKHNpZyk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdjcmVhdGVFbXB0eVNpZ1dpdGhBZGRyZXNzIGFuZCBnZXRBZGRyZXNzRnJvbUVtcHR5U2lnJywgZnVuY3Rpb24gKCkge1xuICAgIGl0KCdzaG91bGQgY3JlYXRlIGVtcHR5IHNpZ25hdHVyZSB3aXRoIGVtYmVkZGVkIEMtY2hhaW4gYWRkcmVzcycsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGFkZHJlc3NIZXggPSB1dGlscy5yZW1vdmVIZXhQcmVmaXgoRVhQT1JUX0lOX0MuY0hleEFkZHJlc3MpO1xuICAgICAgY29uc3Qgc2lnID0gdXRpbHMuY3JlYXRlRW1wdHlTaWdXaXRoQWRkcmVzcyhhZGRyZXNzSGV4KTtcbiAgICAgIGFzc2VydC5vayhzaWcpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBleHRyYWN0IGVtYmVkZGVkIGFkZHJlc3MgZnJvbSBlbXB0eSBzaWduYXR1cmUnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBhZGRyZXNzSGV4ID0gdXRpbHMucmVtb3ZlSGV4UHJlZml4KEVYUE9SVF9JTl9DLmNIZXhBZGRyZXNzKS50b0xvd2VyQ2FzZSgpO1xuICAgICAgY29uc3Qgc2lnID0gdXRpbHMuY3JlYXRlRW1wdHlTaWdXaXRoQWRkcmVzcyhhZGRyZXNzSGV4KTtcblxuICAgICAgLy8gR2V0IHNpZ25hdHVyZSBieXRlcyBhbmQgY29udmVydCB0byBoZXhcbiAgICAgIGNvbnN0IHNpZ0J5dGVzID0gc2lnLnRvQnl0ZXMoKTtcbiAgICAgIGNvbnN0IHNpZ0hleCA9IEJ1ZmZlci5mcm9tKHNpZ0J5dGVzKS50b1N0cmluZygnaGV4Jyk7XG5cbiAgICAgIGNvbnN0IGV4dHJhY3RlZEFkZHJlc3MgPSB1dGlscy5nZXRBZGRyZXNzRnJvbUVtcHR5U2lnKHNpZ0hleCk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoZXh0cmFjdGVkQWRkcmVzcywgYWRkcmVzc0hleCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGhhbmRsZSAweCBwcmVmaXhlZCBhZGRyZXNzJywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgc2lnID0gdXRpbHMuY3JlYXRlRW1wdHlTaWdXaXRoQWRkcmVzcyhFWFBPUlRfSU5fQy5jSGV4QWRkcmVzcyk7XG4gICAgICBhc3NlcnQub2soc2lnKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmV0dXJuIGVtcHR5IHN0cmluZyBmb3Igc2hvcnQgc2lnbmF0dXJlJywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgc2hvcnRTaWcgPSBTRUVEX0FDQ09VTlQucHJpdmF0ZUtleTsgLy8gNjQgY2hhcnMsIGxlc3MgdGhhbiAxMzBcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCh1dGlscy5nZXRBZGRyZXNzRnJvbUVtcHR5U2lnKHNob3J0U2lnKSwgJycpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnc2hhMjU2JywgZnVuY3Rpb24gKCkge1xuICAgIGl0KCdzaG91bGQgY29tcHV0ZSBTSEEyNTYgaGFzaCBvZiBtZXNzYWdlJywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgZGF0YSA9IEJ1ZmZlci5mcm9tKFNFRURfQUNDT1VOVC5tZXNzYWdlLCAndXRmOCcpO1xuICAgICAgY29uc3QgaGFzaCA9IHV0aWxzLnNoYTI1NihkYXRhKTtcblxuICAgICAgYXNzZXJ0Lm9rKGhhc2ggaW5zdGFuY2VvZiBCdWZmZXIpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKGhhc2gubGVuZ3RoLCAzMik7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHByb2R1Y2UgY29uc2lzdGVudCBoYXNoIGZvciBzYW1lIGlucHV0JywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgZGF0YSA9IEJ1ZmZlci5mcm9tKFNFRURfQUNDT1VOVC5tZXNzYWdlLCAndXRmOCcpO1xuICAgICAgY29uc3QgaGFzaDEgPSB1dGlscy5zaGEyNTYoZGF0YSk7XG4gICAgICBjb25zdCBoYXNoMiA9IHV0aWxzLnNoYTI1NihkYXRhKTtcblxuICAgICAgYXNzZXJ0LmRlZXBTdHJpY3RFcXVhbChoYXNoMSwgaGFzaDIpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBwcm9kdWNlIGRpZmZlcmVudCBoYXNoIGZvciBkaWZmZXJlbnQgaW5wdXQnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBkYXRhMSA9IEJ1ZmZlci5mcm9tKFNFRURfQUNDT1VOVC5tZXNzYWdlLCAndXRmOCcpO1xuICAgICAgY29uc3QgZGF0YTIgPSBCdWZmZXIuZnJvbShTRUVEX0FDQ09VTlQucHJpdmF0ZUtleSwgJ3V0ZjgnKTtcbiAgICAgIGNvbnN0IGhhc2gxID0gdXRpbHMuc2hhMjU2KGRhdGExKTtcbiAgICAgIGNvbnN0IGhhc2gyID0gdXRpbHMuc2hhMjU2KGRhdGEyKTtcblxuICAgICAgYXNzZXJ0Lm5vdERlZXBTdHJpY3RFcXVhbChoYXNoMSwgaGFzaDIpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgndmFsaWRhdGVSYXdUcmFuc2FjdGlvbicsIGZ1bmN0aW9uICgpIHtcbiAgICBpdCgnc2hvdWxkIG5vdCB0aHJvdyBmb3IgdmFsaWQgdW5zaWduZWQgaGV4IHRyYW5zYWN0aW9uJywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgcmF3VHggPSB1dGlscy5yZW1vdmVIZXhQcmVmaXgoRVhQT1JUX0lOX0MudW5zaWduZWRIZXgpO1xuICAgICAgYXNzZXJ0LmRvZXNOb3RUaHJvdygoKSA9PiB1dGlscy52YWxpZGF0ZVJhd1RyYW5zYWN0aW9uKHJhd1R4KSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIG5vdCB0aHJvdyBmb3IgdmFsaWQgc2lnbmVkIGhleCB0cmFuc2FjdGlvbicsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHJhd1R4ID0gdXRpbHMucmVtb3ZlSGV4UHJlZml4KEVYUE9SVF9JTl9DLnNpZ25lZEhleCk7XG4gICAgICBhc3NlcnQuZG9lc05vdFRocm93KCgpID0+IHV0aWxzLnZhbGlkYXRlUmF3VHJhbnNhY3Rpb24ocmF3VHgpKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgbm90IHRocm93IGZvciBpbXBvcnQgdHJhbnNhY3Rpb24gaGV4JywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgcmF3VHggPSB1dGlscy5yZW1vdmVIZXhQcmVmaXgoSU1QT1JUX0lOX1AudW5zaWduZWRIZXgpO1xuICAgICAgYXNzZXJ0LmRvZXNOb3RUaHJvdygoKSA9PiB1dGlscy52YWxpZGF0ZVJhd1RyYW5zYWN0aW9uKHJhd1R4KSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHRocm93IGZvciBlbXB0eSB0cmFuc2FjdGlvbicsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGFzc2VydC50aHJvd3MoKCkgPT4gdXRpbHMudmFsaWRhdGVSYXdUcmFuc2FjdGlvbignJyksIC9SYXcgdHJhbnNhY3Rpb24gaXMgZW1wdHkvKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdGhyb3cgZm9yIG5vbi1oZXggdHJhbnNhY3Rpb24nLCBmdW5jdGlvbiAoKSB7XG4gICAgICBhc3NlcnQudGhyb3dzKCgpID0+IHV0aWxzLnZhbGlkYXRlUmF3VHJhbnNhY3Rpb24oJ3h5ejEyMycpLCAvUmF3IHRyYW5zYWN0aW9uIGlzIG5vdCBoZXggc3RyaW5nLyk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdyZW1vdmVIZXhQcmVmaXgnLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ3Nob3VsZCByZW1vdmUgMHggcHJlZml4IGZyb20gQy1jaGFpbiBhZGRyZXNzJywgZnVuY3Rpb24gKCkge1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHV0aWxzLnJlbW92ZUhleFByZWZpeChFWFBPUlRfSU5fQy5jSGV4QWRkcmVzcyksIEVYUE9SVF9JTl9DLmNIZXhBZGRyZXNzLnNsaWNlKDIpKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmVtb3ZlIDB4IHByZWZpeCBmcm9tIHVuc2lnbmVkIGhleCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCh1dGlscy5yZW1vdmVIZXhQcmVmaXgoRVhQT1JUX0lOX0MudW5zaWduZWRIZXgpLCBFWFBPUlRfSU5fQy51bnNpZ25lZEhleC5zbGljZSgyKSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJldHVybiBzdHJpbmcgdW5jaGFuZ2VkIGlmIG5vIHByZWZpeCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCh1dGlscy5yZW1vdmVIZXhQcmVmaXgoU0VFRF9BQ0NPVU5ULnByaXZhdGVLZXkpLCBTRUVEX0FDQ09VTlQucHJpdmF0ZUtleSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGhhbmRsZSBlbXB0eSBzdHJpbmcnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwodXRpbHMucmVtb3ZlSGV4UHJlZml4KCcnKSwgJycpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnb3V0cHV0aWR4TnVtYmVyVG9CdWZmZXIgYW5kIG91dHB1dGlkeEJ1ZmZlclRvTnVtYmVyJywgZnVuY3Rpb24gKCkge1xuICAgIGl0KCdzaG91bGQgaGFuZGxlIG5vbmNlIHZhbHVlJywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgbm9uY2VTdHIgPSBFWFBPUlRfSU5fQy5ub25jZS50b1N0cmluZygpO1xuICAgICAgY29uc3QgYnVmZmVyID0gdXRpbHMub3V0cHV0aWR4TnVtYmVyVG9CdWZmZXIobm9uY2VTdHIpO1xuICAgICAgY29uc3QgcmVzdWx0ID0gdXRpbHMub3V0cHV0aWR4QnVmZmVyVG9OdW1iZXIoYnVmZmVyKTtcblxuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHJlc3VsdCwgbm9uY2VTdHIpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBwcm9kdWNlIDQtYnl0ZSBidWZmZXInLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBidWZmZXIgPSB1dGlscy5vdXRwdXRpZHhOdW1iZXJUb0J1ZmZlcignMjU1Jyk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoYnVmZmVyLmxlbmd0aCwgNCk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdhZGRyZXNzVG9TdHJpbmcnLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ3Nob3VsZCBjb252ZXJ0IGFkZHJlc3MgYnVmZmVyIHRvIG1haW5uZXQgYmVjaDMyIHN0cmluZycsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGFkZHJlc3MgPSBTRUVEX0FDQ09VTlQuYWRkcmVzc01haW5uZXQ7XG4gICAgICBjb25zdCBhZGRyZXNzQnVmZmVyID0gdXRpbHMucGFyc2VBZGRyZXNzKGFkZHJlc3MpO1xuICAgICAgY29uc3QgcmVzdWx0ID0gdXRpbHMuYWRkcmVzc1RvU3RyaW5nKCdmbGFyZScsICdQJywgYWRkcmVzc0J1ZmZlcik7XG5cbiAgICAgIGFzc2VydC5vayhyZXN1bHQuc3RhcnRzV2l0aCgnUC0nKSk7XG4gICAgICBhc3NlcnQub2socmVzdWx0LmluY2x1ZGVzKCdmbGFyZScpKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgY29udmVydCBhZGRyZXNzIGJ1ZmZlciB0byB0ZXN0bmV0IGJlY2gzMiBzdHJpbmcnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBhZGRyZXNzID0gU0VFRF9BQ0NPVU5ULmFkZHJlc3NUZXN0bmV0O1xuICAgICAgY29uc3QgYWRkcmVzc0J1ZmZlciA9IHV0aWxzLnBhcnNlQWRkcmVzcyhhZGRyZXNzKTtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IHV0aWxzLmFkZHJlc3NUb1N0cmluZygnY29zdHdvJywgJ1AnLCBhZGRyZXNzQnVmZmVyKTtcblxuICAgICAgYXNzZXJ0Lm9rKHJlc3VsdC5zdGFydHNXaXRoKCdQLScpKTtcbiAgICAgIGFzc2VydC5vayhyZXN1bHQuaW5jbHVkZXMoJ2Nvc3R3bycpKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ2NiNThFbmNvZGUgYW5kIGNiNThEZWNvZGUnLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ3Nob3VsZCBlbmNvZGUgYW5kIGRlY29kZSB0YXJnZXQgY2hhaW4gSUQgY29ycmVjdGx5JywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgZW5jb2RlZCA9IEVYUE9SVF9JTl9DLnRhcmdldENoYWluSWQ7XG4gICAgICBjb25zdCBkZWNvZGVkID0gdXRpbHMuY2I1OERlY29kZShlbmNvZGVkKTtcbiAgICAgIGNvbnN0IHJlRW5jb2RlZCA9IHV0aWxzLmNiNThFbmNvZGUoZGVjb2RlZCk7XG5cbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChyZUVuY29kZWQsIGVuY29kZWQpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBlbmNvZGUgYW5kIGRlY29kZSBzb3VyY2UgY2hhaW4gSUQgY29ycmVjdGx5JywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgZW5jb2RlZCA9IElNUE9SVF9JTl9QLnNvdXJjZUNoYWluSWQ7XG4gICAgICBjb25zdCBkZWNvZGVkID0gdXRpbHMuY2I1OERlY29kZShlbmNvZGVkKTtcbiAgICAgIGNvbnN0IHJlRW5jb2RlZCA9IHV0aWxzLmNiNThFbmNvZGUoZGVjb2RlZCk7XG5cbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChyZUVuY29kZWQsIGVuY29kZWQpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0aHJvdyBmb3IgaW52YWxpZCBjaGVja3N1bScsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGFzc2VydC50aHJvd3MoKCkgPT4gdXRpbHMuY2I1OERlY29kZSgnMTExMTExMTExMTExMScpLCAvSW52YWxpZCBjaGVja3N1bS8pO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgncGFyc2VBZGRyZXNzIGFuZCBzdHJpbmdUb0FkZHJlc3MnLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ3Nob3VsZCBwYXJzZSBoZXggYWRkcmVzcyB3aXRoIDB4IHByZWZpeCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGJ1ZmZlciA9IHV0aWxzLnBhcnNlQWRkcmVzcyhFWFBPUlRfSU5fQy5jSGV4QWRkcmVzcyk7XG5cbiAgICAgIGFzc2VydC5vayhidWZmZXIgaW5zdGFuY2VvZiBCdWZmZXIpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKGJ1ZmZlci5sZW5ndGgsIDIwKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcGFyc2UgbWFpbm5ldCBiZWNoMzIgYWRkcmVzcycsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGJ1ZmZlciA9IHV0aWxzLnBhcnNlQWRkcmVzcyhTRUVEX0FDQ09VTlQuYWRkcmVzc01haW5uZXQpO1xuXG4gICAgICBhc3NlcnQub2soYnVmZmVyIGluc3RhbmNlb2YgQnVmZmVyKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChidWZmZXIubGVuZ3RoLCAyMCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHBhcnNlIHRlc3RuZXQgYmVjaDMyIGFkZHJlc3MnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBidWZmZXIgPSB1dGlscy5wYXJzZUFkZHJlc3MoU0VFRF9BQ0NPVU5ULmFkZHJlc3NUZXN0bmV0KTtcblxuICAgICAgYXNzZXJ0Lm9rKGJ1ZmZlciBpbnN0YW5jZW9mIEJ1ZmZlcik7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoYnVmZmVyLmxlbmd0aCwgMjApO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBwYXJzZSBQLWNoYWluIGFkZHJlc3NlcyBmcm9tIGV4cG9ydCBkYXRhJywgZnVuY3Rpb24gKCkge1xuICAgICAgRVhQT1JUX0lOX0MucEFkZHJlc3Nlcy5mb3JFYWNoKChhZGRyZXNzKSA9PiB7XG4gICAgICAgIGNvbnN0IGJ1ZmZlciA9IHV0aWxzLnBhcnNlQWRkcmVzcyhhZGRyZXNzKTtcbiAgICAgICAgYXNzZXJ0Lm9rKGJ1ZmZlciBpbnN0YW5jZW9mIEJ1ZmZlcik7XG4gICAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChidWZmZXIubGVuZ3RoLCAyMCk7XG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdGhyb3cgZm9yIGFkZHJlc3Mgd2l0aG91dCBkYXNoIHNlcGFyYXRvcicsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGFzc2VydC50aHJvd3MoKCkgPT4gdXRpbHMucGFyc2VBZGRyZXNzKCdmbGFyZTFhYmMnKSwgL1ZhbGlkIGFkZHJlc3Mgc2hvdWxkIGluY2x1ZGUgLS8pO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0aHJvdyBmb3IgaW52YWxpZCBIUlAnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBhc3NlcnQudGhyb3dzKCgpID0+IHV0aWxzLnBhcnNlQWRkcmVzcygnUC1pbnZhbGlkMXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxNWV2em15JyksIC9JbnZhbGlkIEhSUC8pO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnZmxhcmVJZFN0cmluZycsIGZ1bmN0aW9uICgpIHtcbiAgICBpdCgnc2hvdWxkIGNyZWF0ZSBJZCBmcm9tIHByaXZhdGUga2V5IGhleCBzdHJpbmcnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBpZCA9IHV0aWxzLmZsYXJlSWRTdHJpbmcoU0VFRF9BQ0NPVU5ULnByaXZhdGVLZXkpO1xuICAgICAgYXNzZXJ0Lm9rKGlkKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgY3JlYXRlIElkIGZyb20gYXNzZXQgSUQgaGV4JywgZnVuY3Rpb24gKCkge1xuICAgICAgLy8gQXNzZXQgSUQgaXMgdHlwaWNhbGx5IDMyIGJ5dGVzICg2NCBoZXggY2hhcnMpXG4gICAgICBjb25zdCBhc3NldElkSGV4ID0gU0VFRF9BQ0NPVU5ULnByaXZhdGVLZXk7IC8vIFVzaW5nIGFzIGEgMzItYnl0ZSBoZXhcbiAgICAgIGNvbnN0IGlkID0gdXRpbHMuZmxhcmVJZFN0cmluZyhhc3NldElkSGV4KTtcbiAgICAgIGFzc2VydC5vayhpZCk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdyZWNvdmVyeVNpZ25hdHVyZScsIGZ1bmN0aW9uICgpIHtcbiAgICBpdCgnc2hvdWxkIHJlY292ZXIgcHVibGljIGtleSBmcm9tIHZhbGlkIHNpZ25hdHVyZScsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IG1lc3NhZ2UgPSBCdWZmZXIuZnJvbShTRUVEX0FDQ09VTlQubWVzc2FnZSwgJ3V0ZjgnKTtcbiAgICAgIGNvbnN0IHByaXZhdGVLZXkgPSBCdWZmZXIuZnJvbShTRUVEX0FDQ09VTlQucHJpdmF0ZUtleSwgJ2hleCcpO1xuXG4gICAgICAvLyBDcmVhdGUgc2lnbmF0dXJlIHVzaW5nIHRoZSBzYW1lIHByaXZhdGUga2V5IChjcmVhdGVTaWduYXR1cmUgaGFzaGVzIHRoZSBtZXNzYWdlIGludGVybmFsbHkpXG4gICAgICBjb25zdCBzaWduYXR1cmUgPSB1dGlscy5jcmVhdGVTaWduYXR1cmUobmV0d29yaywgbWVzc2FnZSwgcHJpdmF0ZUtleSk7XG5cbiAgICAgIC8vIFJlY292ZXIgcHVibGljIGtleSAtIHBhc3MgdGhlIGhhc2hlZCBtZXNzYWdlIHNpbmNlIHJlY292ZXJ5U2lnbmF0dXJlIGV4cGVjdHMgcHJlLWhhc2hlZFxuICAgICAgY29uc3QgbWVzc2FnZUhhc2ggPSB1dGlscy5zaGEyNTYobWVzc2FnZSk7XG4gICAgICBjb25zdCByZWNvdmVyZWRQdWJLZXkgPSB1dGlscy5yZWNvdmVyeVNpZ25hdHVyZShtZXNzYWdlSGFzaCwgc2lnbmF0dXJlKTtcblxuICAgICAgYXNzZXJ0Lm9rKHJlY292ZXJlZFB1YktleSBpbnN0YW5jZW9mIEJ1ZmZlcik7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwocmVjb3ZlcmVkUHViS2V5Lmxlbmd0aCwgMzMpOyAvLyBTaG91bGQgYmUgY29tcHJlc3NlZCBwdWJsaWMga2V5ICgzMyBieXRlcylcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmVjb3ZlciBzYW1lIHB1YmxpYyBrZXkgZm9yIHNhbWUgbWVzc2FnZSBhbmQgc2lnbmF0dXJlJywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgbWVzc2FnZSA9IEJ1ZmZlci5mcm9tKFNFRURfQUNDT1VOVC5tZXNzYWdlLCAndXRmOCcpO1xuICAgICAgY29uc3QgcHJpdmF0ZUtleSA9IEJ1ZmZlci5mcm9tKFNFRURfQUNDT1VOVC5wcml2YXRlS2V5LCAnaGV4Jyk7XG4gICAgICBjb25zdCBzaWduYXR1cmUgPSB1dGlscy5jcmVhdGVTaWduYXR1cmUobmV0d29yaywgbWVzc2FnZSwgcHJpdmF0ZUtleSk7XG5cbiAgICAgIGNvbnN0IG1lc3NhZ2VIYXNoID0gdXRpbHMuc2hhMjU2KG1lc3NhZ2UpO1xuICAgICAgY29uc3QgcHViS2V5MSA9IHV0aWxzLnJlY292ZXJ5U2lnbmF0dXJlKG1lc3NhZ2VIYXNoLCBzaWduYXR1cmUpO1xuICAgICAgY29uc3QgcHViS2V5MiA9IHV0aWxzLnJlY292ZXJ5U2lnbmF0dXJlKG1lc3NhZ2VIYXNoLCBzaWduYXR1cmUpO1xuXG4gICAgICBhc3NlcnQuZGVlcFN0cmljdEVxdWFsKHB1YktleTEsIHB1YktleTIpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCByZWNvdmVyIHB1YmxpYyBrZXkgdGhhdCBtYXRjaGVzIG9yaWdpbmFsIGtleScsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IG1lc3NhZ2UgPSBCdWZmZXIuZnJvbShTRUVEX0FDQ09VTlQubWVzc2FnZSwgJ3V0ZjgnKTtcbiAgICAgIGNvbnN0IHByaXZhdGVLZXkgPSBCdWZmZXIuZnJvbShTRUVEX0FDQ09VTlQucHJpdmF0ZUtleSwgJ2hleCcpO1xuXG4gICAgICAvLyBHZXQgb3JpZ2luYWwgcHVibGljIGtleVxuICAgICAgY29uc3Qgb3JpZ2luYWxQdWJLZXkgPSBCdWZmZXIuZnJvbShlY2MucG9pbnRGcm9tU2NhbGFyKHByaXZhdGVLZXksIHRydWUpIGFzIFVpbnQ4QXJyYXkpO1xuXG4gICAgICAvLyBDcmVhdGUgc2lnbmF0dXJlIGFuZCByZWNvdmVyIHB1YmxpYyBrZXlcbiAgICAgIGNvbnN0IHNpZ25hdHVyZSA9IHV0aWxzLmNyZWF0ZVNpZ25hdHVyZShuZXR3b3JrLCBtZXNzYWdlLCBwcml2YXRlS2V5KTtcbiAgICAgIGNvbnN0IG1lc3NhZ2VIYXNoID0gdXRpbHMuc2hhMjU2KG1lc3NhZ2UpO1xuICAgICAgY29uc3QgcmVjb3ZlcmVkUHViS2V5ID0gdXRpbHMucmVjb3ZlcnlTaWduYXR1cmUobWVzc2FnZUhhc2gsIHNpZ25hdHVyZSk7XG5cbiAgICAgIC8vIENvbnZlcnQgYm90aCB0byBoZXggc3RyaW5ncyBmb3IgY29tcGFyaXNvblxuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHJlY292ZXJlZFB1YktleS50b1N0cmluZygnaGV4JyksIG9yaWdpbmFsUHViS2V5LnRvU3RyaW5nKCdoZXgnKSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJlY292ZXIgcHVibGljIGtleSB1c2luZyBBQ0NPVU5UXzEga2V5cycsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IG1lc3NhZ2UgPSBCdWZmZXIuZnJvbShTRUVEX0FDQ09VTlQubWVzc2FnZSwgJ3V0ZjgnKTtcbiAgICAgIGNvbnN0IHByaXZhdGVLZXkgPSBCdWZmZXIuZnJvbShBQ0NPVU5UXzEucHJpdmF0ZUtleSwgJ2hleCcpO1xuXG4gICAgICBjb25zdCBvcmlnaW5hbFB1YktleSA9IEJ1ZmZlci5mcm9tKGVjYy5wb2ludEZyb21TY2FsYXIocHJpdmF0ZUtleSwgdHJ1ZSkgYXMgVWludDhBcnJheSk7XG5cbiAgICAgIGNvbnN0IHNpZ25hdHVyZSA9IHV0aWxzLmNyZWF0ZVNpZ25hdHVyZShuZXR3b3JrLCBtZXNzYWdlLCBwcml2YXRlS2V5KTtcbiAgICAgIGNvbnN0IG1lc3NhZ2VIYXNoID0gdXRpbHMuc2hhMjU2KG1lc3NhZ2UpO1xuICAgICAgY29uc3QgcmVjb3ZlcmVkUHViS2V5ID0gdXRpbHMucmVjb3ZlcnlTaWduYXR1cmUobWVzc2FnZUhhc2gsIHNpZ25hdHVyZSk7XG5cbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChyZWNvdmVyZWRQdWJLZXkudG9TdHJpbmcoJ2hleCcpLCBvcmlnaW5hbFB1YktleS50b1N0cmluZygnaGV4JykpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0aHJvdyBlcnJvciBmb3IgaW52YWxpZCBzaWduYXR1cmUgbGVuZ3RoJywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgbWVzc2FnZUhhc2ggPSB1dGlscy5zaGEyNTYoQnVmZmVyLmZyb20oU0VFRF9BQ0NPVU5ULm1lc3NhZ2UsICd1dGY4JykpO1xuICAgICAgY29uc3QgaW52YWxpZFNpZ25hdHVyZSA9IEJ1ZmZlci5mcm9tKElOVkFMSURfU0hPUlRfS0VZUEFJUl9LRVksICdoZXgnKTtcblxuICAgICAgYXNzZXJ0LnRocm93cygoKSA9PiB1dGlscy5yZWNvdmVyeVNpZ25hdHVyZShtZXNzYWdlSGFzaCwgaW52YWxpZFNpZ25hdHVyZSksIC9GYWlsZWQgdG8gcmVjb3ZlciBzaWduYXR1cmUvKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdGhyb3cgZXJyb3IgZm9yIHNpZ25hdHVyZSB3aXRoIGludmFsaWQgcmVjb3ZlcnkgcGFyYW1ldGVyJywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgbWVzc2FnZUhhc2ggPSB1dGlscy5zaGEyNTYoQnVmZmVyLmZyb20oU0VFRF9BQ0NPVU5ULm1lc3NhZ2UsICd1dGY4JykpO1xuICAgICAgY29uc3Qgc2lnbmF0dXJlID0gQnVmZmVyLmFsbG9jKDY1KTsgLy8gVmFsaWQgbGVuZ3RoIGJ1dCBhbGwgemVyb3MgLSBpbnZhbGlkIHNpZ25hdHVyZVxuXG4gICAgICBhc3NlcnQudGhyb3dzKCgpID0+IHV0aWxzLnJlY292ZXJ5U2lnbmF0dXJlKG1lc3NhZ2VIYXNoLCBzaWduYXR1cmUpLCAvRmFpbGVkIHRvIHJlY292ZXIgc2lnbmF0dXJlLyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJlY292ZXIgc2lnbmF0dXJlIGFuZCB2ZXJpZnkgc2VuZGVyIGFkZHJlc3MgZnJvbSBzaWduZWQgQy1jaGFpbiBFeHBvcnQgdHgnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAvLyBUcmFuc2FjdGlvbiBmcm9tIGFjdHVhbCBidWlsZCByZXNwb25zZSAtIEMtY2hhaW4gRXhwb3J0IHR4XG4gICAgICBjb25zdCB0eCA9XG4gICAgICAgICcweDAwMDAwMDAwMDAwMTAwMDAwMDcyNzhkYjVjMzBiZWQwNGMwNWNlMjA5MTc5ODEyODUwYmJiM2ZlNmQ0NmQ3ZWVmMzc0NGQ4MTRjMGRhNTU1MjQ3OTAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMTJhOTYwMjVhZDUwNmI5ZmJiOTAyM2ZiZGMxNjY1YzdmN2Q3YzkyM2YwMDAwMDAwMDA2MDUyMzY2NTg3MzRmOTRhZjg3MWMzZDEzMWI1NjEzMWI2ZmI3YTAyOTFlYWNhZGQyNjFlNjlkZmI0MmE5Y2RmNmY3ZmRkZDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMTU4NzM0Zjk0YWY4NzFjM2QxMzFiNTYxMzFiNmZiN2EwMjkxZWFjYWRkMjYxZTY5ZGZiNDJhOWNkZjZmN2ZkZGQwMDAwMDAwNzAwMDAwMDAwMDYwNTIzNDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDIwMDAwMDAwMzdmYThjN2UwYzhhZDlmMDlmOTE3OWI0MmI3N2U5NGE0ODdjM2RmNzU4ZDRiYTUzOGY3NzIzMzNjYTdiZjM2NjhhMmZlMzY2NDg0MzhjNzlkOWI2Yjc3YjU2ZWZmYjg2MGVhYTQzMGUwZTMwYzRlMzkyZjU5Y2QwODAwMDAwMDAxMDAwMDAwMDkwMDAwMDAwMTc1MDA3NmU2N2Q5NzIwMjgzYTcxYzZlN2E5YTg4ZmY2NjI2MDhmZWZkZDNmMzE2ZjEyMTE5NTdjYTE4NzNlZWUzZWU0YTc0YjQ2OGJkYTY2MTc2YTNlNWQzYWI1NGQ0M2E4YzBiZTEyMzQ4ZjI1MWEzMDkzYzE2ZDlkYjAwY2QwMDFjMzFlOWMxNSc7XG4gICAgICBjb25zdCBleHBlY3RlZFNlbmRlckFkZHJlc3MgPSAnMHgyYTk2MDI1YWQ1MDZiOWZiYjkwMjNmYmRjMTY2NWM3ZjdkN2M5MjNmJztcblxuICAgICAgY29uc3QgZmFjdG9yeSA9IG5ldyBUcmFuc2FjdGlvbkJ1aWxkZXJGYWN0b3J5KGNvaW5zLmdldCgndGZscnAnKSk7XG4gICAgICBjb25zdCB0eG4gPSAoYXdhaXQgZmFjdG9yeS5mcm9tKHR4KS5idWlsZCgpKSBhcyBUcmFuc2FjdGlvbjtcbiAgICAgIGNvbnN0IHNpZ25hYmxlUGF5bG9hZCA9IHR4bi5zaWduYWJsZVBheWxvYWQ7XG4gICAgICBjb25zdCBzaWduYXR1cmVzID0gdHhuLnNpZ25hdHVyZTtcbiAgICAgIGNvbnN0IHNpZyA9IEJ1ZmZlci5mcm9tKHV0aWxzLnJlbW92ZUhleFByZWZpeChzaWduYXR1cmVzWzBdKSwgJ2hleCcpO1xuXG4gICAgICAvLyBSZWNvdmVyIHB1YmxpYyBrZXkgZnJvbSBzaWduYXR1cmUgKHNpZ25hYmxlUGF5bG9hZCBpcyBhbHJlYWR5IFNIQTI1NiBoYXNoZWQpXG4gICAgICBjb25zdCByZWNvdmVyZWRQdWJLZXkgPSB1dGlscy5yZWNvdmVyeVNpZ25hdHVyZShzaWduYWJsZVBheWxvYWQsIHNpZyk7XG5cbiAgICAgIC8vIEdldCB0aGUgc2VuZGVyIGFkZHJlc3MgZnJvbSB0aGUgdHJhbnNhY3Rpb24gaW5wdXRzXG4gICAgICBjb25zdCB0eElucHV0cyA9IHR4bi5pbnB1dHM7XG4gICAgICBjb25zdCBzZW5kZXJBZGRyZXNzRnJvbVR4ID0gdHhJbnB1dHNbMF0uYWRkcmVzcy50b0xvd2VyQ2FzZSgpO1xuXG4gICAgICAvLyBWZXJpZnkgc2VuZGVyIGFkZHJlc3MgbWF0Y2hlcyBleHBlY3RlZFxuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKFxuICAgICAgICBzZW5kZXJBZGRyZXNzRnJvbVR4LFxuICAgICAgICBleHBlY3RlZFNlbmRlckFkZHJlc3MudG9Mb3dlckNhc2UoKSxcbiAgICAgICAgJ1RyYW5zYWN0aW9uIHNlbmRlciBhZGRyZXNzIGRvZXMgbm90IG1hdGNoIGV4cGVjdGVkJ1xuICAgICAgKTtcblxuICAgICAgLy8gRGVyaXZlIGFkZHJlc3MgZnJvbSByZWNvdmVyZWQgcHVibGljIGtleVxuICAgICAgY29uc3QgZGVyaXZlZEV2bUFkZHJlc3MgPVxuICAgICAgICAnMHgnICsgQnVmZmVyLmZyb20obmV3IEFkZHJlc3Moc2VjcDI1NmsxLnB1YmxpY0tleVRvRXRoQWRkcmVzcyhyZWNvdmVyZWRQdWJLZXkpKS50b0J5dGVzKCkpLnRvU3RyaW5nKCdoZXgnKTtcblxuICAgICAgLy8gVmVyaWZ5IHRoZSByZWNvdmVyZWQgcHVibGljIGtleSBtYXRjaGVzIHRoZSBzZW5kZXJcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChcbiAgICAgICAgZGVyaXZlZEV2bUFkZHJlc3MudG9Mb3dlckNhc2UoKSxcbiAgICAgICAgc2VuZGVyQWRkcmVzc0Zyb21UeCxcbiAgICAgICAgJ1JlY292ZXJlZCBwdWJsaWMga2V5IGRvZXMgbm90IG1hdGNoIHNlbmRlciBhZGRyZXNzJ1xuICAgICAgKTtcblxuICAgICAgLy8gQWxzbyB2ZXJpZnkgc2lnbmF0dXJlIHZhbGlkaXR5XG4gICAgICBjb25zdCBzaWdPbmx5ID0gc2lnLnNsaWNlKDAsIDY0KTtcbiAgICAgIGNvbnN0IGlzVmFsaWQgPSB1dGlscy52ZXJpZnlTaWduYXR1cmUoc2lnbmFibGVQYXlsb2FkLCBzaWdPbmx5LCByZWNvdmVyZWRQdWJLZXkpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKGlzVmFsaWQsIHRydWUsICdTaWduYXR1cmUgdmVyaWZpY2F0aW9uIGZhaWxlZCcpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnaXNUcmFuc2FjdGlvbk9mJywgZnVuY3Rpb24gKCkge1xuICAgIGNvbnN0IGZhY3RvcnkgPSBuZXcgVHJhbnNhY3Rpb25CdWlsZGVyRmFjdG9yeShjb2lucy5nZXQoJ3RmbHJwJykpO1xuICAgIGNvbnN0IHV0aWxzSW5zdGFuY2UgPSBuZXcgVXRpbHMoKTtcbiAgICBjb25zdCB0ZXN0bmV0TmV0d29yayA9IGNvaW5zLmdldCgndGZscnAnKS5uZXR3b3JrIGFzIEZsYXJlTmV0d29yaztcbiAgICBjb25zdCBwQ2hhaW5CbG9ja2NoYWluSWRIZXggPSBCdWZmZXIuZnJvbSh1dGlsc0luc3RhbmNlLmNiNThEZWNvZGUodGVzdG5ldE5ldHdvcmsuYmxvY2tjaGFpbklEKSkudG9TdHJpbmcoJ2hleCcpO1xuICAgIGNvbnN0IGNDaGFpbkJsb2NrY2hhaW5JZEhleCA9IEJ1ZmZlci5mcm9tKHV0aWxzSW5zdGFuY2UuY2I1OERlY29kZSh0ZXN0bmV0TmV0d29yay5jQ2hhaW5CbG9ja2NoYWluSUQpKS50b1N0cmluZyhcbiAgICAgICdoZXgnXG4gICAgKTtcblxuICAgIGl0KCdzaG91bGQgcmV0dXJuIHRydWUgZm9yIEltcG9ydCBpbiBQIHRyYW5zYWN0aW9uIHdpdGggbWF0Y2hpbmcgUC1jaGFpbiBibG9ja2NoYWluIElEJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgdHhCdWlsZGVyID0gZmFjdG9yeVxuICAgICAgICAuZ2V0SW1wb3J0SW5QQnVpbGRlcigpXG4gICAgICAgIC50aHJlc2hvbGQoSU1QT1JUX0lOX1AudGhyZXNob2xkKVxuICAgICAgICAubG9ja3RpbWUoSU1QT1JUX0lOX1AubG9ja3RpbWUpXG4gICAgICAgIC5mcm9tUHViS2V5KElNUE9SVF9JTl9QLmNvcmV0aEFkZHJlc3NlcylcbiAgICAgICAgLnRvKElNUE9SVF9JTl9QLnBBZGRyZXNzZXMpXG4gICAgICAgIC5leHRlcm5hbENoYWluSWQoSU1QT1JUX0lOX1Auc291cmNlQ2hhaW5JZClcbiAgICAgICAgLmZlZVN0YXRlKElNUE9SVF9JTl9QLmZlZVN0YXRlKVxuICAgICAgICAuY29udGV4dChJTVBPUlRfSU5fUC5jb250ZXh0KVxuICAgICAgICAuZGVjb2RlZFV0eG9zKElNUE9SVF9JTl9QLnV0eG9zKTtcblxuICAgICAgY29uc3QgdHggPSAoYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCkpIGFzIFRyYW5zYWN0aW9uO1xuICAgICAgY29uc3QgZmxhcmVUcmFuc2FjdGlvbiA9IHR4LmdldEZsYXJlVHJhbnNhY3Rpb24oKTtcblxuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHV0aWxzSW5zdGFuY2UuaXNUcmFuc2FjdGlvbk9mKGZsYXJlVHJhbnNhY3Rpb24sIHBDaGFpbkJsb2NrY2hhaW5JZEhleCksIHRydWUpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCByZXR1cm4gZmFsc2UgZm9yIEltcG9ydCBpbiBQIHRyYW5zYWN0aW9uIHdpdGggbm9uLW1hdGNoaW5nIEMtY2hhaW4gYmxvY2tjaGFpbiBJRCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHR4QnVpbGRlciA9IGZhY3RvcnlcbiAgICAgICAgLmdldEltcG9ydEluUEJ1aWxkZXIoKVxuICAgICAgICAudGhyZXNob2xkKElNUE9SVF9JTl9QLnRocmVzaG9sZClcbiAgICAgICAgLmxvY2t0aW1lKElNUE9SVF9JTl9QLmxvY2t0aW1lKVxuICAgICAgICAuZnJvbVB1YktleShJTVBPUlRfSU5fUC5jb3JldGhBZGRyZXNzZXMpXG4gICAgICAgIC50byhJTVBPUlRfSU5fUC5wQWRkcmVzc2VzKVxuICAgICAgICAuZXh0ZXJuYWxDaGFpbklkKElNUE9SVF9JTl9QLnNvdXJjZUNoYWluSWQpXG4gICAgICAgIC5mZWVTdGF0ZShJTVBPUlRfSU5fUC5mZWVTdGF0ZSlcbiAgICAgICAgLmNvbnRleHQoSU1QT1JUX0lOX1AuY29udGV4dClcbiAgICAgICAgLmRlY29kZWRVdHhvcyhJTVBPUlRfSU5fUC51dHhvcyk7XG5cbiAgICAgIGNvbnN0IHR4ID0gKGF3YWl0IHR4QnVpbGRlci5idWlsZCgpKSBhcyBUcmFuc2FjdGlvbjtcbiAgICAgIGNvbnN0IGZsYXJlVHJhbnNhY3Rpb24gPSB0eC5nZXRGbGFyZVRyYW5zYWN0aW9uKCk7XG5cbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCh1dGlsc0luc3RhbmNlLmlzVHJhbnNhY3Rpb25PZihmbGFyZVRyYW5zYWN0aW9uLCBjQ2hhaW5CbG9ja2NoYWluSWRIZXgpLCBmYWxzZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJldHVybiB0cnVlIGZvciBFeHBvcnQgaW4gUCB0cmFuc2FjdGlvbiB3aXRoIG1hdGNoaW5nIFAtY2hhaW4gYmxvY2tjaGFpbiBJRCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHR4QnVpbGRlciA9IGZhY3RvcnlcbiAgICAgICAgLmdldEV4cG9ydEluUEJ1aWxkZXIoKVxuICAgICAgICAudGhyZXNob2xkKEVYUE9SVF9JTl9QLnRocmVzaG9sZClcbiAgICAgICAgLmxvY2t0aW1lKEVYUE9SVF9JTl9QLmxvY2t0aW1lKVxuICAgICAgICAuZnJvbVB1YktleShFWFBPUlRfSU5fUC5wQWRkcmVzc2VzKVxuICAgICAgICAuZXh0ZXJuYWxDaGFpbklkKEVYUE9SVF9JTl9QLnNvdXJjZUNoYWluSWQpXG4gICAgICAgIC5mZWVTdGF0ZShFWFBPUlRfSU5fUC5mZWVTdGF0ZSlcbiAgICAgICAgLmNvbnRleHQoRVhQT1JUX0lOX1AuY29udGV4dClcbiAgICAgICAgLmFtb3VudChFWFBPUlRfSU5fUC5hbW91bnQpXG4gICAgICAgIC5kZWNvZGVkVXR4b3MoRVhQT1JUX0lOX1AudXR4b3MpO1xuXG4gICAgICBjb25zdCB0eCA9IChhd2FpdCB0eEJ1aWxkZXIuYnVpbGQoKSkgYXMgVHJhbnNhY3Rpb247XG4gICAgICBjb25zdCBmbGFyZVRyYW5zYWN0aW9uID0gdHguZ2V0RmxhcmVUcmFuc2FjdGlvbigpO1xuXG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwodXRpbHNJbnN0YW5jZS5pc1RyYW5zYWN0aW9uT2YoZmxhcmVUcmFuc2FjdGlvbiwgcENoYWluQmxvY2tjaGFpbklkSGV4KSwgdHJ1ZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJldHVybiBmYWxzZSBmb3IgRXhwb3J0IGluIFAgdHJhbnNhY3Rpb24gd2l0aCBub24tbWF0Y2hpbmcgQy1jaGFpbiBibG9ja2NoYWluIElEJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgdHhCdWlsZGVyID0gZmFjdG9yeVxuICAgICAgICAuZ2V0RXhwb3J0SW5QQnVpbGRlcigpXG4gICAgICAgIC50aHJlc2hvbGQoRVhQT1JUX0lOX1AudGhyZXNob2xkKVxuICAgICAgICAubG9ja3RpbWUoRVhQT1JUX0lOX1AubG9ja3RpbWUpXG4gICAgICAgIC5mcm9tUHViS2V5KEVYUE9SVF9JTl9QLnBBZGRyZXNzZXMpXG4gICAgICAgIC5leHRlcm5hbENoYWluSWQoRVhQT1JUX0lOX1Auc291cmNlQ2hhaW5JZClcbiAgICAgICAgLmZlZVN0YXRlKEVYUE9SVF9JTl9QLmZlZVN0YXRlKVxuICAgICAgICAuY29udGV4dChFWFBPUlRfSU5fUC5jb250ZXh0KVxuICAgICAgICAuYW1vdW50KEVYUE9SVF9JTl9QLmFtb3VudClcbiAgICAgICAgLmRlY29kZWRVdHhvcyhFWFBPUlRfSU5fUC51dHhvcyk7XG5cbiAgICAgIGNvbnN0IHR4ID0gKGF3YWl0IHR4QnVpbGRlci5idWlsZCgpKSBhcyBUcmFuc2FjdGlvbjtcbiAgICAgIGNvbnN0IGZsYXJlVHJhbnNhY3Rpb24gPSB0eC5nZXRGbGFyZVRyYW5zYWN0aW9uKCk7XG5cbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCh1dGlsc0luc3RhbmNlLmlzVHJhbnNhY3Rpb25PZihmbGFyZVRyYW5zYWN0aW9uLCBjQ2hhaW5CbG9ja2NoYWluSWRIZXgpLCBmYWxzZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJldHVybiB0cnVlIGZvciBJbXBvcnQgaW4gQyB0cmFuc2FjdGlvbiB3aXRoIG1hdGNoaW5nIEMtY2hhaW4gYmxvY2tjaGFpbiBJRCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHR4QnVpbGRlciA9IGZhY3RvcnlcbiAgICAgICAgLmdldEltcG9ydEluQ0J1aWxkZXIoKVxuICAgICAgICAudGhyZXNob2xkKElNUE9SVF9JTl9DLnRocmVzaG9sZClcbiAgICAgICAgLmxvY2t0aW1lKElNUE9SVF9JTl9DLmxvY2t0aW1lKVxuICAgICAgICAuZnJvbVB1YktleShJTVBPUlRfSU5fQy5wQWRkcmVzc2VzKVxuICAgICAgICAuZXh0ZXJuYWxDaGFpbklkKElNUE9SVF9JTl9DLnNvdXJjZUNoYWluSWQpXG4gICAgICAgIC5mZWUoSU1QT1JUX0lOX0MuZmVlKVxuICAgICAgICAuY29udGV4dChJTVBPUlRfSU5fQy5jb250ZXh0KVxuICAgICAgICAudG8oSU1QT1JUX0lOX0MudG8pXG4gICAgICAgIC5kZWNvZGVkVXR4b3MoSU1QT1JUX0lOX0MudXR4b3MpO1xuXG4gICAgICBjb25zdCB0eCA9IChhd2FpdCB0eEJ1aWxkZXIuYnVpbGQoKSkgYXMgVHJhbnNhY3Rpb247XG4gICAgICBjb25zdCBmbGFyZVRyYW5zYWN0aW9uID0gdHguZ2V0RmxhcmVUcmFuc2FjdGlvbigpO1xuXG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwodXRpbHNJbnN0YW5jZS5pc1RyYW5zYWN0aW9uT2YoZmxhcmVUcmFuc2FjdGlvbiwgY0NoYWluQmxvY2tjaGFpbklkSGV4KSwgdHJ1ZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJldHVybiBmYWxzZSBmb3IgSW1wb3J0IGluIEMgdHJhbnNhY3Rpb24gd2l0aCBub24tbWF0Y2hpbmcgUC1jaGFpbiBibG9ja2NoYWluIElEJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgdHhCdWlsZGVyID0gZmFjdG9yeVxuICAgICAgICAuZ2V0SW1wb3J0SW5DQnVpbGRlcigpXG4gICAgICAgIC50aHJlc2hvbGQoSU1QT1JUX0lOX0MudGhyZXNob2xkKVxuICAgICAgICAubG9ja3RpbWUoSU1QT1JUX0lOX0MubG9ja3RpbWUpXG4gICAgICAgIC5mcm9tUHViS2V5KElNUE9SVF9JTl9DLnBBZGRyZXNzZXMpXG4gICAgICAgIC5leHRlcm5hbENoYWluSWQoSU1QT1JUX0lOX0Muc291cmNlQ2hhaW5JZClcbiAgICAgICAgLmZlZShJTVBPUlRfSU5fQy5mZWUpXG4gICAgICAgIC5jb250ZXh0KElNUE9SVF9JTl9DLmNvbnRleHQpXG4gICAgICAgIC50byhJTVBPUlRfSU5fQy50bylcbiAgICAgICAgLmRlY29kZWRVdHhvcyhJTVBPUlRfSU5fQy51dHhvcyk7XG5cbiAgICAgIGNvbnN0IHR4ID0gKGF3YWl0IHR4QnVpbGRlci5idWlsZCgpKSBhcyBUcmFuc2FjdGlvbjtcbiAgICAgIGNvbnN0IGZsYXJlVHJhbnNhY3Rpb24gPSB0eC5nZXRGbGFyZVRyYW5zYWN0aW9uKCk7XG5cbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCh1dGlsc0luc3RhbmNlLmlzVHJhbnNhY3Rpb25PZihmbGFyZVRyYW5zYWN0aW9uLCBwQ2hhaW5CbG9ja2NoYWluSWRIZXgpLCBmYWxzZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJldHVybiB0cnVlIGZvciBFeHBvcnQgaW4gQyB0cmFuc2FjdGlvbiB3aXRoIG1hdGNoaW5nIEMtY2hhaW4gYmxvY2tjaGFpbiBJRCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHR4QnVpbGRlciA9IGZhY3RvcnlcbiAgICAgICAgLmdldEV4cG9ydEluQ0J1aWxkZXIoKVxuICAgICAgICAuZnJvbVB1YktleShFWFBPUlRfSU5fQy5jSGV4QWRkcmVzcylcbiAgICAgICAgLm5vbmNlKEVYUE9SVF9JTl9DLm5vbmNlKVxuICAgICAgICAuYW1vdW50KEVYUE9SVF9JTl9DLmFtb3VudClcbiAgICAgICAgLnRocmVzaG9sZChFWFBPUlRfSU5fQy50aHJlc2hvbGQpXG4gICAgICAgIC5sb2NrdGltZShFWFBPUlRfSU5fQy5sb2NrdGltZSlcbiAgICAgICAgLnRvKEVYUE9SVF9JTl9DLnBBZGRyZXNzZXMpXG4gICAgICAgIC5mZWUoRVhQT1JUX0lOX0MuZmVlKVxuICAgICAgICAuY29udGV4dChFWFBPUlRfSU5fQy5jb250ZXh0KTtcblxuICAgICAgY29uc3QgdHggPSAoYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCkpIGFzIFRyYW5zYWN0aW9uO1xuICAgICAgY29uc3QgZmxhcmVUcmFuc2FjdGlvbiA9IHR4LmdldEZsYXJlVHJhbnNhY3Rpb24oKTtcblxuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHV0aWxzSW5zdGFuY2UuaXNUcmFuc2FjdGlvbk9mKGZsYXJlVHJhbnNhY3Rpb24sIGNDaGFpbkJsb2NrY2hhaW5JZEhleCksIHRydWUpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCByZXR1cm4gZmFsc2UgZm9yIEV4cG9ydCBpbiBDIHRyYW5zYWN0aW9uIHdpdGggbm9uLW1hdGNoaW5nIFAtY2hhaW4gYmxvY2tjaGFpbiBJRCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHR4QnVpbGRlciA9IGZhY3RvcnlcbiAgICAgICAgLmdldEV4cG9ydEluQ0J1aWxkZXIoKVxuICAgICAgICAuZnJvbVB1YktleShFWFBPUlRfSU5fQy5jSGV4QWRkcmVzcylcbiAgICAgICAgLm5vbmNlKEVYUE9SVF9JTl9DLm5vbmNlKVxuICAgICAgICAuYW1vdW50KEVYUE9SVF9JTl9DLmFtb3VudClcbiAgICAgICAgLnRocmVzaG9sZChFWFBPUlRfSU5fQy50aHJlc2hvbGQpXG4gICAgICAgIC5sb2NrdGltZShFWFBPUlRfSU5fQy5sb2NrdGltZSlcbiAgICAgICAgLnRvKEVYUE9SVF9JTl9DLnBBZGRyZXNzZXMpXG4gICAgICAgIC5mZWUoRVhQT1JUX0lOX0MuZmVlKVxuICAgICAgICAuY29udGV4dChFWFBPUlRfSU5fQy5jb250ZXh0KTtcblxuICAgICAgY29uc3QgdHggPSAoYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCkpIGFzIFRyYW5zYWN0aW9uO1xuICAgICAgY29uc3QgZmxhcmVUcmFuc2FjdGlvbiA9IHR4LmdldEZsYXJlVHJhbnNhY3Rpb24oKTtcblxuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHV0aWxzSW5zdGFuY2UuaXNUcmFuc2FjdGlvbk9mKGZsYXJlVHJhbnNhY3Rpb24sIHBDaGFpbkJsb2NrY2hhaW5JZEhleCksIGZhbHNlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmV0dXJuIGZhbHNlIGZvciBpbnZhbGlkIGJsb2NrY2hhaW4gSUQnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB0eEJ1aWxkZXIgPSBmYWN0b3J5XG4gICAgICAgIC5nZXRJbXBvcnRJblBCdWlsZGVyKClcbiAgICAgICAgLnRocmVzaG9sZChJTVBPUlRfSU5fUC50aHJlc2hvbGQpXG4gICAgICAgIC5sb2NrdGltZShJTVBPUlRfSU5fUC5sb2NrdGltZSlcbiAgICAgICAgLmZyb21QdWJLZXkoSU1QT1JUX0lOX1AuY29yZXRoQWRkcmVzc2VzKVxuICAgICAgICAudG8oSU1QT1JUX0lOX1AucEFkZHJlc3NlcylcbiAgICAgICAgLmV4dGVybmFsQ2hhaW5JZChJTVBPUlRfSU5fUC5zb3VyY2VDaGFpbklkKVxuICAgICAgICAuZmVlU3RhdGUoSU1QT1JUX0lOX1AuZmVlU3RhdGUpXG4gICAgICAgIC5jb250ZXh0KElNUE9SVF9JTl9QLmNvbnRleHQpXG4gICAgICAgIC5kZWNvZGVkVXR4b3MoSU1QT1JUX0lOX1AudXR4b3MpO1xuXG4gICAgICBjb25zdCB0eCA9IChhd2FpdCB0eEJ1aWxkZXIuYnVpbGQoKSkgYXMgVHJhbnNhY3Rpb247XG4gICAgICBjb25zdCBmbGFyZVRyYW5zYWN0aW9uID0gdHguZ2V0RmxhcmVUcmFuc2FjdGlvbigpO1xuXG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwodXRpbHNJbnN0YW5jZS5pc1RyYW5zYWN0aW9uT2YoZmxhcmVUcmFuc2FjdGlvbiwgJ2ludmFsaWRibG9ja2NoYWluaWQnKSwgZmFsc2UpO1xuICAgIH0pO1xuICB9KTtcbn0pO1xuIl19