@bitgo-beta/sdk-coin-sol 7.6.4-beta.62 → 7.6.4-beta.621

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 (421) hide show
  1. package/dist/cjs/src/bigint-buffer-guard.d.ts.map +1 -0
  2. package/dist/cjs/src/bigint-buffer-guard.js +29 -0
  3. package/dist/cjs/src/index.d.ts.map +1 -0
  4. package/dist/{src → cjs/src}/index.js +1 -1
  5. package/dist/cjs/src/lib/ataInitializationBuilder.d.ts.map +1 -0
  6. package/dist/cjs/src/lib/ataInitializationBuilder.js +201 -0
  7. package/dist/cjs/src/lib/closeAtaBuilder.d.ts +51 -0
  8. package/dist/cjs/src/lib/closeAtaBuilder.d.ts.map +1 -0
  9. package/dist/cjs/src/lib/closeAtaBuilder.js +147 -0
  10. package/dist/{src → cjs/src}/lib/constants.d.ts +45 -2
  11. package/dist/cjs/src/lib/constants.d.ts.map +1 -0
  12. package/dist/cjs/src/lib/constants.js +216 -0
  13. package/dist/cjs/src/lib/customInstructionBuilder.d.ts.map +1 -0
  14. package/dist/cjs/src/lib/customInstructionBuilder.js +289 -0
  15. package/dist/cjs/src/lib/explainTransactionWasm.d.ts +21 -0
  16. package/dist/cjs/src/lib/explainTransactionWasm.d.ts.map +1 -0
  17. package/dist/cjs/src/lib/explainTransactionWasm.js +264 -0
  18. package/dist/{src → cjs/src}/lib/iface.d.ts +79 -2
  19. package/dist/cjs/src/lib/iface.d.ts.map +1 -0
  20. package/dist/cjs/src/lib/iface.js +7 -0
  21. package/dist/{src → cjs/src}/lib/index.d.ts +3 -0
  22. package/dist/cjs/src/lib/index.d.ts.map +1 -0
  23. package/dist/cjs/src/lib/index.js +89 -0
  24. package/dist/{src → cjs/src}/lib/instructionParamsFactory.d.ts +3 -1
  25. package/dist/cjs/src/lib/instructionParamsFactory.d.ts.map +1 -0
  26. package/dist/cjs/src/lib/instructionParamsFactory.js +1122 -0
  27. package/dist/cjs/src/lib/jitoStakePoolOperations.d.ts.map +1 -0
  28. package/dist/cjs/src/lib/jitoStakePoolOperations.js +200 -0
  29. package/dist/cjs/src/lib/keyPair.d.ts.map +1 -0
  30. package/dist/cjs/src/lib/keyPair.js +63 -0
  31. package/dist/cjs/src/lib/messages/index.d.ts.map +1 -0
  32. package/dist/{src → cjs/src}/lib/messages/index.js +1 -1
  33. package/dist/cjs/src/lib/messages/messageBuilderFactory.d.ts.map +1 -0
  34. package/dist/cjs/src/lib/messages/messageBuilderFactory.js +19 -0
  35. package/dist/cjs/src/lib/recoverNestedAtaBuilder.d.ts +25 -0
  36. package/dist/cjs/src/lib/recoverNestedAtaBuilder.d.ts.map +1 -0
  37. package/dist/cjs/src/lib/recoverNestedAtaBuilder.js +90 -0
  38. package/dist/cjs/src/lib/solInstructionFactory.d.ts.map +1 -0
  39. package/dist/cjs/src/lib/solInstructionFactory.js +649 -0
  40. package/dist/cjs/src/lib/stakingActivateBuilder.d.ts.map +1 -0
  41. package/dist/cjs/src/lib/stakingActivateBuilder.js +120 -0
  42. package/dist/cjs/src/lib/stakingAuthorizeBuilder.d.ts.map +1 -0
  43. package/dist/cjs/src/lib/stakingAuthorizeBuilder.js +89 -0
  44. package/dist/cjs/src/lib/stakingDeactivateBuilder.d.ts.map +1 -0
  45. package/dist/cjs/src/lib/stakingDeactivateBuilder.js +208 -0
  46. package/dist/cjs/src/lib/stakingDelegateBuilder.d.ts.map +1 -0
  47. package/dist/cjs/src/lib/stakingDelegateBuilder.js +120 -0
  48. package/dist/cjs/src/lib/stakingRawMsgAuthorizeBuilder.d.ts.map +1 -0
  49. package/dist/cjs/src/lib/stakingRawMsgAuthorizeBuilder.js +110 -0
  50. package/dist/cjs/src/lib/stakingWithdrawBuilder.d.ts.map +1 -0
  51. package/dist/cjs/src/lib/stakingWithdrawBuilder.js +78 -0
  52. package/dist/cjs/src/lib/token2022Resolve.d.ts +106 -0
  53. package/dist/cjs/src/lib/token2022Resolve.d.ts.map +1 -0
  54. package/dist/cjs/src/lib/token2022Resolve.js +199 -0
  55. package/dist/cjs/src/lib/tokenExtensions.d.ts +31 -0
  56. package/dist/cjs/src/lib/tokenExtensions.d.ts.map +1 -0
  57. package/dist/cjs/src/lib/tokenExtensions.js +112 -0
  58. package/dist/{src → cjs/src}/lib/tokenTransferBuilder.d.ts +27 -1
  59. package/dist/cjs/src/lib/tokenTransferBuilder.d.ts.map +1 -0
  60. package/dist/cjs/src/lib/tokenTransferBuilder.js +237 -0
  61. package/dist/cjs/src/lib/transaction.d.ts.map +1 -0
  62. package/dist/cjs/src/lib/transaction.js +612 -0
  63. package/dist/cjs/src/lib/transactionBuilder.d.ts.map +1 -0
  64. package/dist/cjs/src/lib/transactionBuilder.js +380 -0
  65. package/dist/{src → cjs/src}/lib/transactionBuilderFactory.d.ts +5 -0
  66. package/dist/cjs/src/lib/transactionBuilderFactory.d.ts.map +1 -0
  67. package/dist/cjs/src/lib/transactionBuilderFactory.js +209 -0
  68. package/dist/cjs/src/lib/transferBuilder.d.ts.map +1 -0
  69. package/dist/cjs/src/lib/transferBuilder.js +70 -0
  70. package/dist/cjs/src/lib/transferBuilderV2.d.ts +69 -0
  71. package/dist/cjs/src/lib/transferBuilderV2.d.ts.map +1 -0
  72. package/dist/cjs/src/lib/transferBuilderV2.js +254 -0
  73. package/dist/{src → cjs/src}/lib/utils.d.ts +5 -0
  74. package/dist/cjs/src/lib/utils.d.ts.map +1 -0
  75. package/dist/cjs/src/lib/utils.js +635 -0
  76. package/dist/cjs/src/lib/walletInitializationBuilder.d.ts.map +1 -0
  77. package/dist/cjs/src/lib/walletInitializationBuilder.js +71 -0
  78. package/dist/cjs/src/register.d.ts +5 -0
  79. package/dist/cjs/src/register.d.ts.map +1 -0
  80. package/dist/cjs/src/register.js +29 -0
  81. package/dist/{src → cjs/src}/sol.d.ts +112 -3
  82. package/dist/cjs/src/sol.d.ts.map +1 -0
  83. package/dist/cjs/src/sol.js +1617 -0
  84. package/dist/{src → cjs/src}/solToken.d.ts +7 -0
  85. package/dist/cjs/src/solToken.d.ts.map +1 -0
  86. package/dist/cjs/src/solToken.js +79 -0
  87. package/dist/cjs/src/tsol.d.ts.map +1 -0
  88. package/dist/cjs/src/tsol.js +24 -0
  89. package/dist/{test → cjs/test}/fixtures/sol.d.ts.map +1 -1
  90. package/dist/cjs/test/fixtures/sol.js +1433 -0
  91. package/dist/{test → cjs/test}/resources/sol.d.ts +29 -29
  92. package/dist/cjs/test/resources/sol.d.ts.map +1 -0
  93. package/dist/cjs/test/resources/sol.js +320 -0
  94. package/dist/cjs/test/unit/explainTransactionWasm.d.ts +5 -0
  95. package/dist/cjs/test/unit/explainTransactionWasm.d.ts.map +1 -0
  96. package/dist/cjs/test/unit/explainTransactionWasm.js +26 -0
  97. package/dist/cjs/test/unit/fixtures/solBackupKey.d.ts.map +1 -0
  98. package/dist/cjs/test/unit/fixtures/solBackupKey.js +8 -0
  99. package/dist/cjs/test/unit/getBuilderFactory.d.ts.map +1 -0
  100. package/dist/cjs/test/unit/getBuilderFactory.js +10 -0
  101. package/dist/cjs/test/unit/instructionParamsFactory.d.ts.map +1 -0
  102. package/dist/cjs/test/unit/instructionParamsFactory.js +425 -0
  103. package/dist/cjs/test/unit/instructionParamsFactory.staking.d.ts.map +1 -0
  104. package/dist/cjs/test/unit/instructionParamsFactory.staking.js +1059 -0
  105. package/dist/cjs/test/unit/jitoWasmVerification.d.ts +2 -0
  106. package/dist/cjs/test/unit/jitoWasmVerification.d.ts.map +1 -0
  107. package/dist/cjs/test/unit/jitoWasmVerification.js +78 -0
  108. package/dist/{test → cjs/test}/unit/keyPair.d.ts.map +1 -1
  109. package/dist/cjs/test/unit/keyPair.js +177 -0
  110. package/dist/cjs/test/unit/messages/messageBuilderFactory.d.ts.map +1 -0
  111. package/dist/cjs/test/unit/messages/messageBuilderFactory.js +118 -0
  112. package/dist/cjs/test/unit/messages/simpleMessageBuilder.d.ts.map +1 -0
  113. package/dist/cjs/test/unit/messages/simpleMessageBuilder.js +194 -0
  114. package/dist/cjs/test/unit/register.d.ts +2 -0
  115. package/dist/cjs/test/unit/register.d.ts.map +1 -0
  116. package/dist/cjs/test/unit/register.js +65 -0
  117. package/dist/{test → cjs/test}/unit/sol.d.ts.map +1 -1
  118. package/dist/cjs/test/unit/sol.js +4790 -0
  119. package/dist/cjs/test/unit/solInstructionFactory.d.ts.map +1 -0
  120. package/dist/cjs/test/unit/solInstructionFactory.js +611 -0
  121. package/dist/cjs/test/unit/solToken.d.ts.map +1 -0
  122. package/dist/cjs/test/unit/solToken.js +37 -0
  123. package/dist/cjs/test/unit/token2022Resolve.d.ts +2 -0
  124. package/dist/cjs/test/unit/token2022Resolve.d.ts.map +1 -0
  125. package/dist/cjs/test/unit/token2022Resolve.js +252 -0
  126. package/dist/cjs/test/unit/tokenExtensions.d.ts +2 -0
  127. package/dist/cjs/test/unit/tokenExtensions.d.ts.map +1 -0
  128. package/dist/cjs/test/unit/tokenExtensions.js +32 -0
  129. package/dist/cjs/test/unit/transaction.d.ts.map +1 -0
  130. package/dist/cjs/test/unit/transaction.js +1108 -0
  131. package/dist/cjs/test/unit/transactionBuilder/StakingWithdrawBuilder.d.ts.map +1 -0
  132. package/dist/cjs/test/unit/transactionBuilder/StakingWithdrawBuilder.js +202 -0
  133. package/dist/cjs/test/unit/transactionBuilder/ataInitBuilder.d.ts.map +1 -0
  134. package/dist/cjs/test/unit/transactionBuilder/ataInitBuilder.js +471 -0
  135. package/dist/cjs/test/unit/transactionBuilder/closeAtaBuilder.d.ts +2 -0
  136. package/dist/cjs/test/unit/transactionBuilder/closeAtaBuilder.d.ts.map +1 -0
  137. package/dist/cjs/test/unit/transactionBuilder/closeAtaBuilder.js +333 -0
  138. package/dist/cjs/test/unit/transactionBuilder/customInstructionBuilder.d.ts.map +1 -0
  139. package/dist/cjs/test/unit/transactionBuilder/customInstructionBuilder.js +413 -0
  140. package/dist/cjs/test/unit/transactionBuilder/stakingActivateBuilder.d.ts.map +1 -0
  141. package/dist/cjs/test/unit/transactionBuilder/stakingActivateBuilder.js +430 -0
  142. package/dist/cjs/test/unit/transactionBuilder/stakingAuthorizeBuilder.d.ts.map +1 -0
  143. package/dist/cjs/test/unit/transactionBuilder/stakingAuthorizeBuilder.js +157 -0
  144. package/dist/cjs/test/unit/transactionBuilder/stakingDeactivateBuilder.d.ts.map +1 -0
  145. package/dist/cjs/test/unit/transactionBuilder/stakingDeactivateBuilder.js +384 -0
  146. package/dist/cjs/test/unit/transactionBuilder/stakingDelegateBuilder.d.ts.map +1 -0
  147. package/dist/cjs/test/unit/transactionBuilder/stakingDelegateBuilder.js +224 -0
  148. package/dist/cjs/test/unit/transactionBuilder/stakingRawMsgAuthorizeBuilder.d.ts.map +1 -0
  149. package/dist/cjs/test/unit/transactionBuilder/stakingRawMsgAuthorizeBuilder.js +259 -0
  150. package/dist/cjs/test/unit/transactionBuilder/tokenTransferBuilder.d.ts.map +1 -0
  151. package/dist/cjs/test/unit/transactionBuilder/tokenTransferBuilder.js +926 -0
  152. package/dist/cjs/test/unit/transactionBuilder/transactionBuilder.d.ts.map +1 -0
  153. package/dist/cjs/test/unit/transactionBuilder/transactionBuilder.js +495 -0
  154. package/dist/cjs/test/unit/transactionBuilder/transferBuilder.d.ts.map +1 -0
  155. package/dist/cjs/test/unit/transactionBuilder/transferBuilder.js +286 -0
  156. package/dist/cjs/test/unit/transactionBuilder/transferBuilderV2.d.ts.map +1 -0
  157. package/dist/cjs/test/unit/transactionBuilder/transferBuilderV2.js +910 -0
  158. package/dist/cjs/test/unit/transactionBuilder/walletInitBuilder.d.ts.map +1 -0
  159. package/dist/cjs/test/unit/transactionBuilder/walletInitBuilder.js +259 -0
  160. package/dist/{test → cjs/test}/unit/utils.d.ts.map +1 -1
  161. package/dist/cjs/test/unit/utils.js +557 -0
  162. package/dist/cjs/test/unit/versionedTransaction.d.ts.map +1 -0
  163. package/dist/cjs/test/unit/versionedTransaction.js +207 -0
  164. package/dist/cjs/tsconfig.tsbuildinfo +1 -0
  165. package/dist/esm/bigint-buffer-guard.d.ts +1 -0
  166. package/dist/esm/index.d.ts +7 -0
  167. package/dist/esm/index.js +7 -0
  168. package/dist/esm/lib/ataInitializationBuilder.d.ts +47 -0
  169. package/dist/{src → esm}/lib/ataInitializationBuilder.d.ts.map +1 -1
  170. package/dist/esm/lib/ataInitializationBuilder.js +161 -0
  171. package/dist/esm/lib/closeAtaBuilder.d.ts +51 -0
  172. package/dist/esm/lib/closeAtaBuilder.d.ts.map +1 -0
  173. package/dist/esm/lib/closeAtaBuilder.js +140 -0
  174. package/dist/esm/lib/constants.d.ts +183 -0
  175. package/dist/esm/lib/constants.d.ts.map +1 -0
  176. package/dist/esm/lib/constants.js +213 -0
  177. package/dist/esm/lib/customInstructionBuilder.d.ts +72 -0
  178. package/dist/esm/lib/customInstructionBuilder.js +282 -0
  179. package/dist/esm/lib/explainTransactionWasm.d.ts +21 -0
  180. package/dist/esm/lib/explainTransactionWasm.d.ts.map +1 -0
  181. package/dist/esm/lib/explainTransactionWasm.js +261 -0
  182. package/dist/esm/lib/iface.d.ts +321 -0
  183. package/dist/esm/lib/iface.d.ts.map +1 -0
  184. package/dist/esm/lib/iface.js +3 -0
  185. package/dist/esm/lib/index.d.ts +25 -0
  186. package/dist/{src → esm}/lib/index.d.ts.map +1 -1
  187. package/dist/esm/lib/index.js +25 -0
  188. package/dist/esm/lib/instructionParamsFactory.d.ts +14 -0
  189. package/dist/esm/lib/instructionParamsFactory.d.ts.map +1 -0
  190. package/dist/esm/lib/instructionParamsFactory.js +1114 -0
  191. package/dist/esm/lib/jitoStakePoolOperations.d.ts +113 -0
  192. package/dist/esm/lib/jitoStakePoolOperations.js +189 -0
  193. package/dist/esm/lib/keyPair.d.ts +26 -0
  194. package/dist/esm/lib/keyPair.js +59 -0
  195. package/dist/esm/lib/messages/index.d.ts +2 -0
  196. package/dist/esm/lib/messages/index.js +2 -0
  197. package/dist/esm/lib/messages/messageBuilderFactory.d.ts +7 -0
  198. package/dist/{src → esm}/lib/messages/messageBuilderFactory.js +5 -9
  199. package/dist/esm/lib/recoverNestedAtaBuilder.d.ts +25 -0
  200. package/dist/esm/lib/recoverNestedAtaBuilder.d.ts.map +1 -0
  201. package/dist/esm/lib/recoverNestedAtaBuilder.js +83 -0
  202. package/dist/esm/lib/solInstructionFactory.d.ts +10 -0
  203. package/dist/esm/lib/solInstructionFactory.d.ts.map +1 -0
  204. package/dist/esm/lib/solInstructionFactory.js +643 -0
  205. package/dist/esm/lib/stakingActivateBuilder.d.ts +59 -0
  206. package/dist/esm/lib/stakingActivateBuilder.js +113 -0
  207. package/dist/esm/lib/stakingAuthorizeBuilder.d.ts +43 -0
  208. package/dist/esm/lib/stakingAuthorizeBuilder.js +82 -0
  209. package/dist/esm/lib/stakingDeactivateBuilder.d.ts +81 -0
  210. package/dist/{src → esm}/lib/stakingDeactivateBuilder.js +31 -38
  211. package/dist/esm/lib/stakingDelegateBuilder.d.ts +42 -0
  212. package/dist/esm/lib/stakingDelegateBuilder.js +113 -0
  213. package/dist/esm/lib/stakingRawMsgAuthorizeBuilder.d.ts +33 -0
  214. package/dist/esm/lib/stakingRawMsgAuthorizeBuilder.js +103 -0
  215. package/dist/esm/lib/stakingWithdrawBuilder.d.ts +31 -0
  216. package/dist/esm/lib/stakingWithdrawBuilder.js +71 -0
  217. package/dist/esm/lib/token2022Resolve.d.ts +106 -0
  218. package/dist/esm/lib/token2022Resolve.d.ts.map +1 -0
  219. package/dist/esm/lib/token2022Resolve.js +194 -0
  220. package/dist/esm/lib/tokenExtensions.d.ts +31 -0
  221. package/dist/esm/lib/tokenExtensions.d.ts.map +1 -0
  222. package/dist/esm/lib/tokenExtensions.js +105 -0
  223. package/dist/esm/lib/tokenTransferBuilder.d.ts +67 -0
  224. package/dist/esm/lib/tokenTransferBuilder.d.ts.map +1 -0
  225. package/dist/esm/lib/tokenTransferBuilder.js +230 -0
  226. package/dist/esm/lib/transaction.d.ts +103 -0
  227. package/dist/esm/lib/transaction.d.ts.map +1 -0
  228. package/dist/esm/lib/transaction.js +605 -0
  229. package/dist/esm/lib/transactionBuilder.d.ts +128 -0
  230. package/dist/esm/lib/transactionBuilder.js +373 -0
  231. package/dist/esm/lib/transactionBuilderFactory.d.ts +120 -0
  232. package/dist/esm/lib/transactionBuilderFactory.d.ts.map +1 -0
  233. package/dist/esm/lib/transactionBuilderFactory.js +205 -0
  234. package/dist/esm/lib/transferBuilder.d.ts +26 -0
  235. package/dist/esm/lib/transferBuilder.js +63 -0
  236. package/dist/esm/lib/transferBuilderV2.d.ts +69 -0
  237. package/dist/esm/lib/transferBuilderV2.d.ts.map +1 -0
  238. package/dist/esm/lib/transferBuilderV2.js +247 -0
  239. package/dist/esm/lib/utils.d.ts +205 -0
  240. package/dist/{src → esm}/lib/utils.d.ts.map +1 -1
  241. package/dist/esm/lib/utils.js +597 -0
  242. package/dist/esm/lib/walletInitializationBuilder.d.ts +26 -0
  243. package/dist/esm/lib/walletInitializationBuilder.js +64 -0
  244. package/dist/esm/register.d.ts +5 -0
  245. package/dist/esm/register.d.ts.map +1 -0
  246. package/dist/esm/register.js +24 -0
  247. package/dist/esm/sol.d.ts +349 -0
  248. package/dist/esm/sol.d.ts.map +1 -0
  249. package/dist/esm/sol.js +1576 -0
  250. package/dist/esm/solToken.d.ts +44 -0
  251. package/dist/esm/solToken.d.ts.map +1 -0
  252. package/dist/esm/solToken.js +75 -0
  253. package/dist/esm/tsol.d.ts +11 -0
  254. package/dist/esm/tsol.js +20 -0
  255. package/package.json +35 -16
  256. package/dist/src/config/token2022StaticConfig.d.ts +0 -3
  257. package/dist/src/config/token2022StaticConfig.d.ts.map +0 -1
  258. package/dist/src/config/token2022StaticConfig.js +0 -50
  259. package/dist/src/lib/ataInitializationBuilder.js +0 -196
  260. package/dist/src/lib/closeAtaBuilder.d.ts +0 -19
  261. package/dist/src/lib/closeAtaBuilder.d.ts.map +0 -1
  262. package/dist/src/lib/closeAtaBuilder.js +0 -69
  263. package/dist/src/lib/constants.d.ts.map +0 -1
  264. package/dist/src/lib/constants.js +0 -171
  265. package/dist/src/lib/customInstructionBuilder.js +0 -289
  266. package/dist/src/lib/iface.d.ts.map +0 -1
  267. package/dist/src/lib/iface.js +0 -7
  268. package/dist/src/lib/index.js +0 -77
  269. package/dist/src/lib/instructionParamsFactory.d.ts.map +0 -1
  270. package/dist/src/lib/instructionParamsFactory.js +0 -1036
  271. package/dist/src/lib/jitoStakePoolOperations.js +0 -200
  272. package/dist/src/lib/keyPair.js +0 -63
  273. package/dist/src/lib/solInstructionFactory.d.ts.map +0 -1
  274. package/dist/src/lib/solInstructionFactory.js +0 -572
  275. package/dist/src/lib/stakingActivateBuilder.js +0 -120
  276. package/dist/src/lib/stakingAuthorizeBuilder.js +0 -89
  277. package/dist/src/lib/stakingDelegateBuilder.js +0 -120
  278. package/dist/src/lib/stakingRawMsgAuthorizeBuilder.js +0 -110
  279. package/dist/src/lib/stakingWithdrawBuilder.js +0 -78
  280. package/dist/src/lib/token2022Config.d.ts +0 -44
  281. package/dist/src/lib/token2022Config.d.ts.map +0 -1
  282. package/dist/src/lib/token2022Config.js +0 -27
  283. package/dist/src/lib/tokenTransferBuilder.d.ts.map +0 -1
  284. package/dist/src/lib/tokenTransferBuilder.js +0 -188
  285. package/dist/src/lib/transaction.d.ts.map +0 -1
  286. package/dist/src/lib/transaction.js +0 -595
  287. package/dist/src/lib/transactionBuilder.js +0 -380
  288. package/dist/src/lib/transactionBuilderFactory.d.ts.map +0 -1
  289. package/dist/src/lib/transactionBuilderFactory.js +0 -202
  290. package/dist/src/lib/transferBuilder.js +0 -70
  291. package/dist/src/lib/transferBuilderV2.d.ts +0 -43
  292. package/dist/src/lib/transferBuilderV2.d.ts.map +0 -1
  293. package/dist/src/lib/transferBuilderV2.js +0 -210
  294. package/dist/src/lib/utils.js +0 -589
  295. package/dist/src/lib/walletInitializationBuilder.js +0 -71
  296. package/dist/src/register.d.ts +0 -3
  297. package/dist/src/register.d.ts.map +0 -1
  298. package/dist/src/register.js +0 -15
  299. package/dist/src/sol.d.ts.map +0 -1
  300. package/dist/src/sol.js +0 -1324
  301. package/dist/src/solToken.d.ts.map +0 -1
  302. package/dist/src/solToken.js +0 -69
  303. package/dist/src/tsol.js +0 -24
  304. package/dist/test/fixtures/sol.js +0 -1433
  305. package/dist/test/resources/sol.d.ts.map +0 -1
  306. package/dist/test/resources/sol.js +0 -320
  307. package/dist/test/unit/fixtures/solBackupKey.d.ts.map +0 -1
  308. package/dist/test/unit/fixtures/solBackupKey.js +0 -8
  309. package/dist/test/unit/getBuilderFactory.d.ts.map +0 -1
  310. package/dist/test/unit/getBuilderFactory.js +0 -10
  311. package/dist/test/unit/instructionParamsFactory.d.ts.map +0 -1
  312. package/dist/test/unit/instructionParamsFactory.js +0 -412
  313. package/dist/test/unit/instructionParamsFactory.staking.d.ts.map +0 -1
  314. package/dist/test/unit/instructionParamsFactory.staking.js +0 -1059
  315. package/dist/test/unit/keyPair.js +0 -177
  316. package/dist/test/unit/messages/messageBuilderFactory.d.ts.map +0 -1
  317. package/dist/test/unit/messages/messageBuilderFactory.js +0 -118
  318. package/dist/test/unit/messages/simpleMessageBuilder.d.ts.map +0 -1
  319. package/dist/test/unit/messages/simpleMessageBuilder.js +0 -194
  320. package/dist/test/unit/sol.js +0 -3180
  321. package/dist/test/unit/solInstructionFactory.d.ts.map +0 -1
  322. package/dist/test/unit/solInstructionFactory.js +0 -454
  323. package/dist/test/unit/solToken.d.ts.map +0 -1
  324. package/dist/test/unit/solToken.js +0 -31
  325. package/dist/test/unit/transaction.d.ts.map +0 -1
  326. package/dist/test/unit/transaction.js +0 -983
  327. package/dist/test/unit/transactionBuilder/StakingWithdrawBuilder.d.ts.map +0 -1
  328. package/dist/test/unit/transactionBuilder/StakingWithdrawBuilder.js +0 -202
  329. package/dist/test/unit/transactionBuilder/ataInitBuilder.d.ts.map +0 -1
  330. package/dist/test/unit/transactionBuilder/ataInitBuilder.js +0 -471
  331. package/dist/test/unit/transactionBuilder/customInstructionBuilder.d.ts.map +0 -1
  332. package/dist/test/unit/transactionBuilder/customInstructionBuilder.js +0 -413
  333. package/dist/test/unit/transactionBuilder/stakingActivateBuilder.d.ts.map +0 -1
  334. package/dist/test/unit/transactionBuilder/stakingActivateBuilder.js +0 -430
  335. package/dist/test/unit/transactionBuilder/stakingAuthorizeBuilder.d.ts.map +0 -1
  336. package/dist/test/unit/transactionBuilder/stakingAuthorizeBuilder.js +0 -157
  337. package/dist/test/unit/transactionBuilder/stakingDeactivateBuilder.d.ts.map +0 -1
  338. package/dist/test/unit/transactionBuilder/stakingDeactivateBuilder.js +0 -384
  339. package/dist/test/unit/transactionBuilder/stakingDelegateBuilder.d.ts.map +0 -1
  340. package/dist/test/unit/transactionBuilder/stakingDelegateBuilder.js +0 -224
  341. package/dist/test/unit/transactionBuilder/stakingRawMsgAuthorizeBuilder.d.ts.map +0 -1
  342. package/dist/test/unit/transactionBuilder/stakingRawMsgAuthorizeBuilder.js +0 -259
  343. package/dist/test/unit/transactionBuilder/tokenTransferBuilder.d.ts.map +0 -1
  344. package/dist/test/unit/transactionBuilder/tokenTransferBuilder.js +0 -787
  345. package/dist/test/unit/transactionBuilder/transactionBuilder.d.ts.map +0 -1
  346. package/dist/test/unit/transactionBuilder/transactionBuilder.js +0 -495
  347. package/dist/test/unit/transactionBuilder/transferBuilder.d.ts.map +0 -1
  348. package/dist/test/unit/transactionBuilder/transferBuilder.js +0 -286
  349. package/dist/test/unit/transactionBuilder/transferBuilderV2.d.ts.map +0 -1
  350. package/dist/test/unit/transactionBuilder/transferBuilderV2.js +0 -862
  351. package/dist/test/unit/transactionBuilder/walletInitBuilder.d.ts.map +0 -1
  352. package/dist/test/unit/transactionBuilder/walletInitBuilder.js +0 -259
  353. package/dist/test/unit/utils.js +0 -517
  354. package/dist/test/unit/versionedTransaction.d.ts.map +0 -1
  355. package/dist/test/unit/versionedTransaction.js +0 -207
  356. package/dist/tsconfig.tsbuildinfo +0 -1
  357. /package/dist/{src → cjs/src}/bigint-buffer-guard.d.ts +0 -0
  358. /package/dist/{src → cjs/src}/index.d.ts +0 -0
  359. /package/dist/{src → cjs/src}/lib/ataInitializationBuilder.d.ts +0 -0
  360. /package/dist/{src → cjs/src}/lib/customInstructionBuilder.d.ts +0 -0
  361. /package/dist/{src → cjs/src}/lib/jitoStakePoolOperations.d.ts +0 -0
  362. /package/dist/{src → cjs/src}/lib/keyPair.d.ts +0 -0
  363. /package/dist/{src → cjs/src}/lib/messages/index.d.ts +0 -0
  364. /package/dist/{src → cjs/src}/lib/messages/messageBuilderFactory.d.ts +0 -0
  365. /package/dist/{src → cjs/src}/lib/solInstructionFactory.d.ts +0 -0
  366. /package/dist/{src → cjs/src}/lib/stakingActivateBuilder.d.ts +0 -0
  367. /package/dist/{src → cjs/src}/lib/stakingAuthorizeBuilder.d.ts +0 -0
  368. /package/dist/{src → cjs/src}/lib/stakingDeactivateBuilder.d.ts +0 -0
  369. /package/dist/{src → cjs/src}/lib/stakingDelegateBuilder.d.ts +0 -0
  370. /package/dist/{src → cjs/src}/lib/stakingRawMsgAuthorizeBuilder.d.ts +0 -0
  371. /package/dist/{src → cjs/src}/lib/stakingWithdrawBuilder.d.ts +0 -0
  372. /package/dist/{src → cjs/src}/lib/transaction.d.ts +0 -0
  373. /package/dist/{src → cjs/src}/lib/transactionBuilder.d.ts +0 -0
  374. /package/dist/{src → cjs/src}/lib/transferBuilder.d.ts +0 -0
  375. /package/dist/{src → cjs/src}/lib/walletInitializationBuilder.d.ts +0 -0
  376. /package/dist/{src → cjs/src}/tsol.d.ts +0 -0
  377. /package/dist/{test → cjs/test}/fixtures/sol.d.ts +0 -0
  378. /package/dist/{test → cjs/test}/unit/fixtures/solBackupKey.d.ts +0 -0
  379. /package/dist/{test → cjs/test}/unit/getBuilderFactory.d.ts +0 -0
  380. /package/dist/{test → cjs/test}/unit/instructionParamsFactory.d.ts +0 -0
  381. /package/dist/{test → cjs/test}/unit/instructionParamsFactory.staking.d.ts +0 -0
  382. /package/dist/{test → cjs/test}/unit/keyPair.d.ts +0 -0
  383. /package/dist/{test → cjs/test}/unit/messages/messageBuilderFactory.d.ts +0 -0
  384. /package/dist/{test → cjs/test}/unit/messages/simpleMessageBuilder.d.ts +0 -0
  385. /package/dist/{test → cjs/test}/unit/sol.d.ts +0 -0
  386. /package/dist/{test → cjs/test}/unit/solInstructionFactory.d.ts +0 -0
  387. /package/dist/{test → cjs/test}/unit/solToken.d.ts +0 -0
  388. /package/dist/{test → cjs/test}/unit/transaction.d.ts +0 -0
  389. /package/dist/{test → cjs/test}/unit/transactionBuilder/StakingWithdrawBuilder.d.ts +0 -0
  390. /package/dist/{test → cjs/test}/unit/transactionBuilder/ataInitBuilder.d.ts +0 -0
  391. /package/dist/{test → cjs/test}/unit/transactionBuilder/customInstructionBuilder.d.ts +0 -0
  392. /package/dist/{test → cjs/test}/unit/transactionBuilder/stakingActivateBuilder.d.ts +0 -0
  393. /package/dist/{test → cjs/test}/unit/transactionBuilder/stakingAuthorizeBuilder.d.ts +0 -0
  394. /package/dist/{test → cjs/test}/unit/transactionBuilder/stakingDeactivateBuilder.d.ts +0 -0
  395. /package/dist/{test → cjs/test}/unit/transactionBuilder/stakingDelegateBuilder.d.ts +0 -0
  396. /package/dist/{test → cjs/test}/unit/transactionBuilder/stakingRawMsgAuthorizeBuilder.d.ts +0 -0
  397. /package/dist/{test → cjs/test}/unit/transactionBuilder/tokenTransferBuilder.d.ts +0 -0
  398. /package/dist/{test → cjs/test}/unit/transactionBuilder/transactionBuilder.d.ts +0 -0
  399. /package/dist/{test → cjs/test}/unit/transactionBuilder/transferBuilder.d.ts +0 -0
  400. /package/dist/{test → cjs/test}/unit/transactionBuilder/transferBuilderV2.d.ts +0 -0
  401. /package/dist/{test → cjs/test}/unit/transactionBuilder/walletInitBuilder.d.ts +0 -0
  402. /package/dist/{test → cjs/test}/unit/utils.d.ts +0 -0
  403. /package/dist/{test → cjs/test}/unit/versionedTransaction.d.ts +0 -0
  404. /package/dist/{src → esm}/bigint-buffer-guard.d.ts.map +0 -0
  405. /package/dist/{src → esm}/bigint-buffer-guard.js +0 -0
  406. /package/dist/{src → esm}/index.d.ts.map +0 -0
  407. /package/dist/{src → esm}/lib/customInstructionBuilder.d.ts.map +0 -0
  408. /package/dist/{src → esm}/lib/jitoStakePoolOperations.d.ts.map +0 -0
  409. /package/dist/{src → esm}/lib/keyPair.d.ts.map +0 -0
  410. /package/dist/{src → esm}/lib/messages/index.d.ts.map +0 -0
  411. /package/dist/{src → esm}/lib/messages/messageBuilderFactory.d.ts.map +0 -0
  412. /package/dist/{src → esm}/lib/stakingActivateBuilder.d.ts.map +0 -0
  413. /package/dist/{src → esm}/lib/stakingAuthorizeBuilder.d.ts.map +0 -0
  414. /package/dist/{src → esm}/lib/stakingDeactivateBuilder.d.ts.map +0 -0
  415. /package/dist/{src → esm}/lib/stakingDelegateBuilder.d.ts.map +0 -0
  416. /package/dist/{src → esm}/lib/stakingRawMsgAuthorizeBuilder.d.ts.map +0 -0
  417. /package/dist/{src → esm}/lib/stakingWithdrawBuilder.d.ts.map +0 -0
  418. /package/dist/{src → esm}/lib/transactionBuilder.d.ts.map +0 -0
  419. /package/dist/{src → esm}/lib/transferBuilder.d.ts.map +0 -0
  420. /package/dist/{src → esm}/lib/walletInitializationBuilder.d.ts.map +0 -0
  421. /package/dist/{src → esm}/tsol.d.ts.map +0 -0
@@ -0,0 +1,1576 @@
1
+ /**
2
+ * @prettier
3
+ */
4
+ import { TOKEN_2022_PROGRAM_ID, TOKEN_PROGRAM_ID } from '@solana/spl-token';
5
+ import { PublicKey as SolPublicKey } from '@solana/web3.js';
6
+ import BigNumber from 'bignumber.js';
7
+ import * as base58 from 'bs58';
8
+ import * as _ from 'lodash';
9
+ import * as request from 'superagent';
10
+ import { logger } from '@bitgo-beta/logger';
11
+ import assert from 'assert';
12
+ import { BaseCoin, EDDSAMethods, Environments, multisigTypes, TransactionType, verifyEddsaTssWalletAddress, deriveMPCWalletAddress, UnexpectedAddressError, getEddsaSigningMaterial, signEddsaMpcV2RecoveryTx, } from '@bitgo-beta/sdk-core';
13
+ import { auditEddsaPrivateKey, getDerivationPath } from '@bitgo-beta/sdk-lib-mpc';
14
+ import { coins } from '@bitgo-beta/statics';
15
+ import { KeyPair as SolKeyPair, Transaction, TransactionBuilder, TransactionBuilderFactory, explainSolTransaction, } from './lib';
16
+ import { InstructionBuilderTypes } from './lib/constants';
17
+ import { buildSolAccountConnection, resolvePermissionlessThaw as resolvePermissionlessThawLib, resolveTransferHookAccounts as resolveTransferHookAccountsLib, } from './lib/token2022Resolve';
18
+ import { getAssociatedTokenAccountAddress, getSolTokenFromAddress, getSolTokenFromTokenName, isValidAddress, isValidPrivateKey, isValidPublicKey, validateRawTransaction, } from './lib/utils';
19
+ export const DEFAULT_SCAN_FACTOR = 20; // default number of receive addresses to scan for funds
20
+ const HEX_REGEX = /^[0-9a-fA-F]+$/;
21
+ const BLIND_SIGNING_TX_TYPES_TO_CHECK = { enabletoken: 'AssociatedTokenAccountInitialization' };
22
+ /**
23
+ * Get amount string corrected for architecture-specific endianness issues.
24
+ *
25
+ * On s390x (big-endian) architecture, the Solana transaction parser (via @solana/web3.js)
26
+ * incorrectly reads little-endian u64 amounts as big-endian, resulting in corrupted values.
27
+ *
28
+ * This function corrects all amounts on s390x by swapping byte order to undo
29
+ * the incorrect byte order that happened during transaction parsing.
30
+ *
31
+ * @param amount - The amount to check and potentially fix
32
+ * @returns The corrected amount as a string
33
+ */
34
+ export function getAmountBasedOnEndianness(amount) {
35
+ const amountStr = String(amount);
36
+ // Only s390x architecture has this endianness issue
37
+ const isS390x = process.arch === 's390x';
38
+ if (!isS390x) {
39
+ return amountStr;
40
+ }
41
+ try {
42
+ const amountBN = BigInt(amountStr);
43
+ // On s390x, the parser ALWAYS reads u64 as big-endian when it's actually little-endian
44
+ // So we ALWAYS need to swap bytes to get the correct value
45
+ const buf = Buffer.alloc(8);
46
+ buf.writeBigUInt64BE(amountBN, 0);
47
+ const fixed = buf.readBigUInt64LE(0);
48
+ return fixed.toString();
49
+ }
50
+ catch (e) {
51
+ // If conversion fails, return original value
52
+ return amountStr;
53
+ }
54
+ }
55
+ export class Sol extends BaseCoin {
56
+ constructor(bitgo, staticsCoin) {
57
+ super(bitgo);
58
+ if (!staticsCoin) {
59
+ throw new Error('missing required constructor parameter staticsCoin');
60
+ }
61
+ this._staticsCoin = staticsCoin;
62
+ }
63
+ static createInstance(bitgo, staticsCoin) {
64
+ return new Sol(bitgo, staticsCoin);
65
+ }
66
+ allowsAccountConsolidations() {
67
+ return true;
68
+ }
69
+ supportsTss() {
70
+ return true;
71
+ }
72
+ /** @inheritDoc */
73
+ supportsMessageSigning() {
74
+ return true;
75
+ }
76
+ /** inherited doc */
77
+ getDefaultMultisigType() {
78
+ return multisigTypes.tss;
79
+ }
80
+ getMPCAlgorithm() {
81
+ return 'eddsa';
82
+ }
83
+ getChain() {
84
+ return this._staticsCoin.name;
85
+ }
86
+ getFamily() {
87
+ return this._staticsCoin.family;
88
+ }
89
+ getFullName() {
90
+ return this._staticsCoin.fullName;
91
+ }
92
+ getNetwork() {
93
+ return this._staticsCoin.network;
94
+ }
95
+ getBaseFactor() {
96
+ return Math.pow(10, this._staticsCoin.decimalPlaces);
97
+ }
98
+ verifyTxType(expectedTypeFromUserParams, actualTypeFromDecoded) {
99
+ const matchFromUserToDecodedType = BLIND_SIGNING_TX_TYPES_TO_CHECK[expectedTypeFromUserParams];
100
+ if (matchFromUserToDecodedType !== actualTypeFromDecoded) {
101
+ throw new Error(`Invalid transaction type on token enablement: expected "${matchFromUserToDecodedType}", got "${actualTypeFromDecoded}".`);
102
+ }
103
+ }
104
+ throwIfMissingTokenEnablementsOrReturn(explanation) {
105
+ if (!explanation.tokenEnablements || explanation.tokenEnablements.length === 0)
106
+ throw new Error('Missing tx token enablements data on token enablement tx prebuild');
107
+ return explanation.tokenEnablements;
108
+ }
109
+ throwIfMissingEnableTokenConfigOrReturn(txParams) {
110
+ if (!txParams.enableTokens || txParams.enableTokens.length === 0)
111
+ throw new Error('Missing enable token config');
112
+ return txParams.enableTokens;
113
+ }
114
+ verifyTokenName(tokenEnablementsPrebuild, enableTokensConfig) {
115
+ enableTokensConfig.forEach((enableTokenConfig) => {
116
+ const expectedTokenName = enableTokenConfig.name;
117
+ tokenEnablementsPrebuild.forEach((tokenEnablement) => {
118
+ if (!tokenEnablement.tokenName)
119
+ throw new Error('Missing token name on token enablement tx');
120
+ if (tokenEnablement.tokenName !== expectedTokenName)
121
+ throw new Error(`Invalid token name: expected ${expectedTokenName}, got ${tokenEnablement.tokenName} on token enablement tx`);
122
+ });
123
+ });
124
+ }
125
+ async verifyTokenAddress(tokenEnablementsPrebuild, enableTokensConfig) {
126
+ for (const enableTokenConfig of enableTokensConfig) {
127
+ const expectedTokenAddress = enableTokenConfig.address;
128
+ const expectedTokenName = enableTokenConfig.name;
129
+ if (!expectedTokenAddress)
130
+ throw new Error('Missing token address on token enablement tx');
131
+ if (!expectedTokenName)
132
+ throw new Error('Missing token name on token enablement tx');
133
+ for (const tokenEnablement of tokenEnablementsPrebuild) {
134
+ let tokenMintAddress;
135
+ try {
136
+ tokenMintAddress = getSolTokenFromTokenName(expectedTokenName);
137
+ }
138
+ catch {
139
+ throw new Error(`Unable to derive ATA for token address: ${expectedTokenAddress}`);
140
+ }
141
+ if (!tokenMintAddress ||
142
+ tokenMintAddress.tokenAddress === undefined ||
143
+ tokenMintAddress.programId === undefined) {
144
+ throw new Error(`Unable to get token mint address for ${expectedTokenName}`);
145
+ }
146
+ let ata;
147
+ try {
148
+ ata = await getAssociatedTokenAccountAddress(tokenMintAddress.tokenAddress, expectedTokenAddress, true, tokenMintAddress.programId);
149
+ }
150
+ catch {
151
+ throw new Error(`Unable to derive ATA for token address: ${expectedTokenAddress}`);
152
+ }
153
+ if (ata !== tokenEnablement.address) {
154
+ throw new Error(`Invalid token address: expected ${ata}, got ${tokenEnablement.address} on token enablement tx`);
155
+ }
156
+ }
157
+ }
158
+ }
159
+ /**
160
+ * For transactions typed as `CloseAssociatedTokenAccount` (includes SPL close-account and
161
+ * recover-nested flows), enforce that rent / authority aligns with the wallet root when known.
162
+ *
163
+ * No-op when `walletRootAddress` is not provided (e.g. uninitialized wallets).
164
+ */
165
+ verifyCloseAssociatedTokenAccountFamilyRoots(transaction, walletRootAddress) {
166
+ if (!walletRootAddress) {
167
+ return;
168
+ }
169
+ const txJson = transaction.toJson();
170
+ for (const instruction of txJson.instructionsData) {
171
+ if (instruction.type === InstructionBuilderTypes.CloseAssociatedTokenAccount) {
172
+ const closeInstruction = instruction;
173
+ if (closeInstruction.params.destinationAddress !== walletRootAddress) {
174
+ throw new Error(`Close ATA destination must be wallet root address. Expected ${walletRootAddress}, got ${closeInstruction.params.destinationAddress}`);
175
+ }
176
+ }
177
+ else if (instruction.type === InstructionBuilderTypes.RecoverNestedAssociatedTokenAccount) {
178
+ const recoverNestedInstruction = instruction;
179
+ if (recoverNestedInstruction.params.walletAddress !== walletRootAddress) {
180
+ throw new Error(`Recover nested wallet address must be wallet root address. Expected ${walletRootAddress}, got ${recoverNestedInstruction.params.walletAddress}`);
181
+ }
182
+ }
183
+ }
184
+ }
185
+ /**
186
+ * When the caller supplies `recipients` for a close-ATA prebuild, require they match the
187
+ * on-chain ATA accounts being closed (order-independent) and carry zero amount (intent-only).
188
+ * Recover-nested-only txs have no close instructions; this is a no-op in that case.
189
+ */
190
+ verifyCloseAtaRecipientsMatchCloseInstructions(transaction, recipients) {
191
+ const txJson = transaction.toJson();
192
+ const closeAtaAccountAddresses = txJson.instructionsData
193
+ .filter((inst) => inst.type === InstructionBuilderTypes.CloseAssociatedTokenAccount)
194
+ .map((inst) => inst.params.accountAddress);
195
+ if (closeAtaAccountAddresses.length === 0) {
196
+ return;
197
+ }
198
+ for (const recipient of recipients) {
199
+ if (recipient.tokenName) {
200
+ throw new Error('Close ATA recipients must not specify tokenName');
201
+ }
202
+ if (!new BigNumber(String(recipient.amount ?? '0')).isZero()) {
203
+ throw new Error('Close ATA recipients must have zero amount');
204
+ }
205
+ }
206
+ const sortedRecipients = [...recipients.map((r) => r.address)].sort();
207
+ const sortedCloses = [...closeAtaAccountAddresses].sort();
208
+ if (!_.isEqual(sortedRecipients, sortedCloses)) {
209
+ throw new Error('Close ATA txParams.recipients addresses must match the ATA account addresses in the transaction instructions');
210
+ }
211
+ }
212
+ hasSolVersionedTransactionData(txParams) {
213
+ return 'solVersionedTransactionData' in txParams && txParams.solVersionedTransactionData !== undefined;
214
+ }
215
+ /**
216
+ * Verify a versioned Solana transaction with basic structural validation
217
+ * @param params - verification parameters
218
+ * @returns true if verification passes
219
+ */
220
+ async verifyVersionedTransaction(params) {
221
+ const { txParams, txPrebuild } = params;
222
+ const rawTx = txPrebuild.txBase64 || txPrebuild.txHex;
223
+ if (!rawTx) {
224
+ throw new Error('missing required tx prebuild property txBase64 or txHex');
225
+ }
226
+ // Validate that the versioned transaction data is well-formed
227
+ if (!this.hasSolVersionedTransactionData(txParams)) {
228
+ throw new Error('solVersionedTransactionData is required for versioned transaction verification');
229
+ }
230
+ const versionedData = txParams.solVersionedTransactionData;
231
+ if (!versionedData.versionedInstructions || versionedData.versionedInstructions.length === 0) {
232
+ throw new Error('versioned transaction must have at least one instruction');
233
+ }
234
+ if (!versionedData.staticAccountKeys || versionedData.staticAccountKeys.length === 0) {
235
+ throw new Error('versioned transaction must have at least one static account key');
236
+ }
237
+ if (!versionedData.messageHeader) {
238
+ throw new Error('versioned transaction must have a message header');
239
+ }
240
+ // Validate that we can deserialize the transaction
241
+ let rawTxBase64 = rawTx;
242
+ if (HEX_REGEX.test(rawTx)) {
243
+ rawTxBase64 = Buffer.from(rawTx, 'hex').toString('base64');
244
+ }
245
+ try {
246
+ const txBytes = Buffer.from(rawTxBase64, 'base64');
247
+ if (txBytes.length < 1) {
248
+ throw new Error('transaction bytes are empty');
249
+ }
250
+ // Check version byte (after signatures)
251
+ const numSignatures = txBytes[0];
252
+ const signatureSize = 64;
253
+ const versionByteOffset = 1 + numSignatures * signatureSize;
254
+ if (txBytes.length <= versionByteOffset) {
255
+ throw new Error('transaction bytes are too short to contain version byte');
256
+ }
257
+ const versionByte = txBytes[versionByteOffset];
258
+ const isVersioned = (versionByte & 0x80) !== 0;
259
+ if (!isVersioned) {
260
+ throw new Error('transaction does not have versioned format');
261
+ }
262
+ }
263
+ catch (error) {
264
+ throw new Error(`failed to validate versioned transaction format: ${error.message}`);
265
+ }
266
+ return true;
267
+ }
268
+ async verifyTransaction(params) {
269
+ // asset name to transfer amount map
270
+ const totalAmount = {};
271
+ const coinConfig = coins.get(this.getChain());
272
+ const { txParams: txParams, txPrebuild: txPrebuild, memo: memo, durableNonce: durableNonce, verification: verificationOptions, } = params;
273
+ if (this.hasSolVersionedTransactionData(txParams)) {
274
+ return this.verifyVersionedTransaction(params);
275
+ }
276
+ const transaction = new Transaction(coinConfig);
277
+ // Allow unsupported tokens (not in static map) to use their mint address as tokenName during parsing
278
+ transaction.setUseTokenAddressTokenName(true);
279
+ const rawTx = txPrebuild.txBase64 || txPrebuild.txHex;
280
+ const consolidateId = txPrebuild.consolidateId;
281
+ const walletRootAddress = params.wallet.coinSpecific()?.rootAddress;
282
+ if (!rawTx) {
283
+ throw new Error('missing required tx prebuild property txBase64 or txHex');
284
+ }
285
+ let rawTxBase64 = rawTx;
286
+ if (HEX_REGEX.test(rawTx)) {
287
+ rawTxBase64 = Buffer.from(rawTx, 'hex').toString('base64');
288
+ }
289
+ transaction.fromRawTransaction(rawTxBase64);
290
+ const explainedTx = transaction.explainTransaction();
291
+ const isCloseAssociatedTokenAccountTx = transaction.type === TransactionType.CloseAssociatedTokenAccount;
292
+ if (txParams.type === 'enabletoken' && verificationOptions?.verifyTokenEnablement) {
293
+ this.verifyTxType(txParams.type, explainedTx.type);
294
+ const tokenEnablementsPrebuild = this.throwIfMissingTokenEnablementsOrReturn(explainedTx);
295
+ const enableTokensConfig = this.throwIfMissingEnableTokenConfigOrReturn(txParams);
296
+ this.verifyTokenName(tokenEnablementsPrebuild, enableTokensConfig);
297
+ await this.verifyTokenAddress(tokenEnablementsPrebuild, enableTokensConfig);
298
+ }
299
+ if (isCloseAssociatedTokenAccountTx) {
300
+ this.verifyCloseAssociatedTokenAccountFamilyRoots(transaction, walletRootAddress);
301
+ if (txParams.recipients !== undefined) {
302
+ this.verifyCloseAtaRecipientsMatchCloseInstructions(transaction, txParams.recipients);
303
+ }
304
+ }
305
+ const isTokenEnablementTx = txParams.type === 'enabletoken';
306
+ // users do not input recipients for consolidation requests as they are generated by the server
307
+ // Close-ATA txs do not populate explainedTx.outputs; recipients carry ATA addresses for intent only.
308
+ if (txParams.recipients !== undefined && !isTokenEnablementTx && !isCloseAssociatedTokenAccountTx) {
309
+ const filteredRecipients = txParams.recipients?.map((recipient) => _.pick(recipient, ['address', 'amount', 'tokenName', 'tokenAddress', 'programId']));
310
+ const filteredOutputs = explainedTx.outputs.map((output) => _.pick(output, ['address', 'amount', 'tokenName']));
311
+ if (filteredRecipients.length !== filteredOutputs.length) {
312
+ throw new Error('Number of tx outputs does not match with number of txParams recipients');
313
+ }
314
+ // For each recipient, check if it's a token tx (tokenName will exist if so)
315
+ // If it is a token tx, verify that the recipient address equals the derived address from explainedTx
316
+ // Derive the ATA if it is a native address and confirm it is equal to the explained tx recipient
317
+ const recipientChecks = await Promise.all(filteredRecipients.map(async (recipientFromUser, index) => {
318
+ const recipientFromTx = filteredOutputs[index]; // This address should be an ATA
319
+ // Compare the BigNumber values because amount is (string | number)
320
+ // Apply s390x endianness fix if needed
321
+ const userAmountStr = String(recipientFromUser.amount);
322
+ const txAmountStr = getAmountBasedOnEndianness(recipientFromTx.amount);
323
+ const userAmount = new BigNumber(userAmountStr);
324
+ const txAmount = new BigNumber(txAmountStr);
325
+ if (!userAmount.isEqualTo(txAmount)) {
326
+ return false;
327
+ }
328
+ // Compare the addresses and tokenNames
329
+ // Else if the addresses are not the same, check the derived ATA for parity
330
+ if (recipientFromUser.address === recipientFromTx.address &&
331
+ recipientFromUser.tokenName === recipientFromTx.tokenName) {
332
+ return true;
333
+ }
334
+ else if (recipientFromUser.address !== recipientFromTx.address && recipientFromUser.tokenName) {
335
+ // Try to check if the user's derived ATA is equal to the tx recipient address
336
+ // If getAssociatedTokenAccountAddress throws an error, then we are unable to derive the ATA for that address.
337
+ // Return false and throw an error if that is the case.
338
+ try {
339
+ const tokenFromMap = getSolTokenFromTokenName(recipientFromUser.tokenName);
340
+ const mintAddress = tokenFromMap?.tokenAddress ?? recipientFromUser.tokenAddress;
341
+ const programId = tokenFromMap?.programId ?? recipientFromUser.programId;
342
+ if (!mintAddress) {
343
+ return false;
344
+ }
345
+ return getAssociatedTokenAccountAddress(mintAddress, recipientFromUser.address, true, programId).then((ata) => {
346
+ return ata === recipientFromTx.address;
347
+ });
348
+ }
349
+ catch {
350
+ // Unable to derive ATA
351
+ return false;
352
+ }
353
+ }
354
+ return false;
355
+ }));
356
+ if (recipientChecks.includes(false)) {
357
+ throw new Error('Tx outputs does not match with expected txParams recipients');
358
+ }
359
+ }
360
+ else if (verificationOptions?.consolidationToBaseAddress) {
361
+ //verify funds are sent to walletRootAddress for a consolidation
362
+ const filteredOutputs = explainedTx.outputs.map((output) => _.pick(output, ['address', 'amount', 'tokenName']));
363
+ // Cache to store already derived ATA addresses
364
+ const ataAddressCache = {};
365
+ for (const output of filteredOutputs) {
366
+ if (output.tokenName) {
367
+ // Check cache first before deriving ATA address
368
+ if (!ataAddressCache[output.tokenName]) {
369
+ const tokenFromMap = getSolTokenFromTokenName(output.tokenName);
370
+ if (tokenFromMap?.tokenAddress && tokenFromMap?.programId) {
371
+ ataAddressCache[output.tokenName] = await getAssociatedTokenAccountAddress(tokenFromMap.tokenAddress, walletRootAddress, true, tokenFromMap.programId);
372
+ }
373
+ else {
374
+ // For unsupported tokens, explainTransaction sets tokenName to the mint address itself.
375
+ // Attempt ATA derivation using tokenName as the mint address; programId defaults to TOKEN_PROGRAM_ID.
376
+ ataAddressCache[output.tokenName] = await getAssociatedTokenAccountAddress(output.tokenName, walletRootAddress, true);
377
+ }
378
+ }
379
+ if (ataAddressCache[output.tokenName] !== output.address) {
380
+ throw new Error('tx outputs does not match with expected address');
381
+ }
382
+ }
383
+ else if (output.address !== walletRootAddress) {
384
+ throw new Error('tx outputs does not match with expected address');
385
+ }
386
+ }
387
+ }
388
+ const transactionJson = transaction.toJson();
389
+ if (memo && memo.value !== explainedTx.memo) {
390
+ throw new Error('Tx memo does not match with expected txParams recipient memo');
391
+ }
392
+ if (txParams.recipients && !isTokenEnablementTx && !isCloseAssociatedTokenAccountTx) {
393
+ for (const recipients of txParams.recipients) {
394
+ // totalAmount based on each token
395
+ const assetName = recipients.tokenName || this.getChain();
396
+ const amount = totalAmount[assetName] || new BigNumber(0);
397
+ totalAmount[assetName] = amount.plus(recipients.amount);
398
+ }
399
+ // total output amount from explainedTx
400
+ const explainedTxTotal = {};
401
+ for (const output of explainedTx.outputs) {
402
+ // Apply s390x endianness fix to output amounts before summing
403
+ const outputAmountStr = getAmountBasedOnEndianness(output.amount);
404
+ // total output amount based on each token
405
+ const assetName = output.tokenName || this.getChain();
406
+ const amount = explainedTxTotal[assetName] || new BigNumber(0);
407
+ explainedTxTotal[assetName] = amount.plus(outputAmountStr);
408
+ }
409
+ if (!_.isEqual(explainedTxTotal, totalAmount)) {
410
+ throw new Error('Tx total amount does not match with expected total amount field');
411
+ }
412
+ }
413
+ // For non-consolidate transactions, feePayer must be the wallet's root address
414
+ if (consolidateId === undefined && transactionJson.feePayer !== walletRootAddress) {
415
+ throw new Error('Tx fee payer is not the wallet root address');
416
+ }
417
+ if (durableNonce && !_.isEqual(explainedTx.durableNonce, durableNonce)) {
418
+ throw new Error('Tx durableNonce does not match with param durableNonce');
419
+ }
420
+ return true;
421
+ }
422
+ async isWalletAddress(params) {
423
+ const result = await verifyEddsaTssWalletAddress(params, (address) => this.isValidAddress(address), (publicKey) => this.getAddressFromPublicKey(publicKey));
424
+ if (!result) {
425
+ throw new UnexpectedAddressError(`address validation failure: ${params.address} is not a wallet address`);
426
+ }
427
+ return true;
428
+ }
429
+ /**
430
+ * Locally derive a SOL wallet receive address from a derivation path, using the wallet's
431
+ * commonKeychain only (no private keys, no network access). This is the inverse of
432
+ * {@link isWalletAddress}: it *produces* the address via the same EdDSA TSS derivation that
433
+ * isWalletAddress checks against, so the two can never diverge.
434
+ * @param params keychains (commonKeychain), derivation index, and optional SMC seed
435
+ * @returns the derived address, the index used, and the HD derivation path
436
+ */
437
+ async deriveAddress(params) {
438
+ // Derive the native owner (wallet) address from the commonKeychain.
439
+ const { address: ownerAddress, derivationPath } = await deriveMPCWalletAddress({
440
+ // extractCommonKeychain validates the commonKeychain is present at runtime
441
+ keychains: (params.keychains ?? []),
442
+ index: params.index,
443
+ derivedFromParentWithSeed: params.derivedFromParentWithSeed,
444
+ multisigTypeVersion: params.multisigTypeVersion,
445
+ keyCurve: 'ed25519',
446
+ }, (publicKey) => this.getAddressFromPublicKey(publicKey));
447
+ // No token requested: return the native SOL receive address.
448
+ if (!params.tokenName) {
449
+ return { address: ownerAddress, index: params.index, derivationPath };
450
+ }
451
+ // Token requested: the deposit address is the owner's Associated Token Account (ATA) for the
452
+ // token's mint, derived the same way SOL token addresses are produced elsewhere in this coin.
453
+ const token = getSolTokenFromTokenName(params.tokenName);
454
+ if (!token || token.tokenAddress === undefined || token.programId === undefined) {
455
+ throw new Error(`unknown or unsupported SOL token: ${params.tokenName}`);
456
+ }
457
+ const address = await getAssociatedTokenAccountAddress(token.tokenAddress, ownerAddress, true, token.programId);
458
+ return { address, index: params.index, derivationPath };
459
+ }
460
+ /**
461
+ * Converts a Solana public key to an address
462
+ * @param publicKey Hex-encoded public key (64 hex characters = 32 bytes)
463
+ * @returns Base58-encoded Solana address
464
+ */
465
+ getAddressFromPublicKey(publicKey) {
466
+ const publicKeyBuffer = Buffer.from(publicKey, 'hex');
467
+ return base58.encode(publicKeyBuffer);
468
+ }
469
+ /**
470
+ * Generate Solana key pair
471
+ *
472
+ * @param {Buffer} seed - Seed from which the new SolKeyPair should be generated, otherwise a random seed is used
473
+ * @returns {Object} object with generated pub and prv
474
+ */
475
+ generateKeyPair(seed) {
476
+ const result = seed ? new SolKeyPair({ seed }).getKeys() : new SolKeyPair().getKeys();
477
+ return result;
478
+ }
479
+ /**
480
+ * Return boolean indicating whether input is valid public key for the coin
481
+ *
482
+ * @param {string} pub the prv to be checked
483
+ * @returns is it valid?
484
+ */
485
+ isValidPub(pub) {
486
+ return isValidPublicKey(pub);
487
+ }
488
+ /**
489
+ * Return boolean indicating whether input is valid private key for the coin
490
+ *
491
+ * @param {string} prv the prv to be checked
492
+ * @returns is it valid?
493
+ */
494
+ isValidPrv(prv) {
495
+ return isValidPrivateKey(prv);
496
+ }
497
+ isValidAddress(address) {
498
+ return isValidAddress(address);
499
+ }
500
+ async signMessage(key, message) {
501
+ const solKeypair = new SolKeyPair({ prv: key.prv });
502
+ if (Buffer.isBuffer(message)) {
503
+ message = base58.encode(message);
504
+ }
505
+ return Buffer.from(solKeypair.signMessage(message));
506
+ }
507
+ /**
508
+ * Signs Solana transaction
509
+ * @param params
510
+ * @param callback
511
+ */
512
+ async signTransaction(params) {
513
+ const factory = this.getBuilder();
514
+ const rawTx = params.txPrebuild.txHex || params.txPrebuild.txBase64;
515
+ const txBuilder = factory.from(rawTx);
516
+ txBuilder.sign({ key: params.prv });
517
+ const transaction = await txBuilder.build();
518
+ if (!transaction) {
519
+ throw new Error('Invalid transaction');
520
+ }
521
+ const serializedTx = transaction.toBroadcastFormat();
522
+ return {
523
+ txHex: serializedTx,
524
+ };
525
+ }
526
+ async parseTransaction(params) {
527
+ // explainTransaction now uses WASM for testnet automatically
528
+ const transactionExplanation = await this.explainTransaction({
529
+ txBase64: params.txBase64,
530
+ feeInfo: params.feeInfo,
531
+ tokenAccountRentExemptAmount: params.tokenAccountRentExemptAmount,
532
+ });
533
+ if (!transactionExplanation) {
534
+ throw new Error('Invalid transaction');
535
+ }
536
+ const solTransaction = transactionExplanation;
537
+ if (solTransaction.outputs.length <= 0) {
538
+ return {
539
+ inputs: [],
540
+ outputs: [],
541
+ };
542
+ }
543
+ const senderAddress = solTransaction.outputs[0].address;
544
+ const feeAmount = new BigNumber(solTransaction.fee.fee);
545
+ // assume 1 sender, who is also the fee payer
546
+ const inputs = [
547
+ {
548
+ address: senderAddress,
549
+ amount: new BigNumber(solTransaction.outputAmount).plus(feeAmount).toNumber(),
550
+ },
551
+ ];
552
+ const outputs = solTransaction.outputs.map(({ address, amount, tokenName }) => {
553
+ const output = { address, amount };
554
+ if (tokenName) {
555
+ output.tokenName = tokenName;
556
+ }
557
+ return output;
558
+ });
559
+ return {
560
+ inputs,
561
+ outputs,
562
+ };
563
+ }
564
+ /**
565
+ * Explain a Solana transaction from txBase64
566
+ * Uses WASM-based parsing for testnet, with fallback to legacy builder approach.
567
+ * @param params
568
+ */
569
+ async explainTransaction(params) {
570
+ // Use WASM-based parsing for testnet (simpler, faster, no @solana/web3.js rebuild)
571
+ if (this.getChain() === 'tsol') {
572
+ return this.explainTransactionWithWasm(params);
573
+ }
574
+ // Legacy approach for mainnet (until WASM is fully validated)
575
+ const factory = this.getBuilder();
576
+ let rebuiltTransaction;
577
+ try {
578
+ const transactionBuilder = factory.from(params.txBase64);
579
+ if (transactionBuilder instanceof TransactionBuilder) {
580
+ const txBuilder = transactionBuilder;
581
+ txBuilder.fee({ amount: params.feeInfo.fee });
582
+ if (params.tokenAccountRentExemptAmount) {
583
+ txBuilder.associatedTokenAccountRent(params.tokenAccountRentExemptAmount);
584
+ }
585
+ }
586
+ rebuiltTransaction = await transactionBuilder.build();
587
+ }
588
+ catch (e) {
589
+ logger.error(e);
590
+ throw new Error('Invalid transaction');
591
+ }
592
+ const explainedTransaction = rebuiltTransaction.explainTransaction();
593
+ return explainedTransaction;
594
+ }
595
+ /**
596
+ * Explain a Solana transaction using WASM parsing (bypasses @solana/web3.js rebuild).
597
+ * Delegates to standalone explainSolTransaction().
598
+ */
599
+ explainTransactionWithWasm(params) {
600
+ return explainSolTransaction({ ...params, coinName: params.coinName ?? this.getChain() });
601
+ }
602
+ /** @inheritDoc */
603
+ async getSignablePayload(serializedTx) {
604
+ const factory = this.getBuilder();
605
+ const rebuiltTransaction = await factory.from(serializedTx).build();
606
+ return rebuiltTransaction.signablePayload;
607
+ }
608
+ /** @inheritDoc */
609
+ async presignTransaction(params) {
610
+ // Hot wallet txns are only valid for 1-2 minutes.
611
+ // To buy more time, we rebuild the transaction with a new blockhash right before we sign.
612
+ if (params.walletData.type !== 'hot') {
613
+ return Promise.resolve(params);
614
+ }
615
+ const txRequestId = params.txPrebuild?.txRequestId;
616
+ if (txRequestId === undefined) {
617
+ throw new Error('Missing txRequestId');
618
+ }
619
+ const { tssUtils } = params;
620
+ await tssUtils.deleteSignatureShares(txRequestId);
621
+ const recreated = await tssUtils.getTxRequest(txRequestId);
622
+ let txHex = '';
623
+ if (recreated.unsignedTxs) {
624
+ txHex = recreated.unsignedTxs[0]?.serializedTxHex;
625
+ }
626
+ else {
627
+ txHex = recreated.transactions ? recreated.transactions[0]?.unsignedTx.serializedTxHex : '';
628
+ }
629
+ if (!txHex) {
630
+ throw new Error('Missing serialized tx hex');
631
+ }
632
+ return Promise.resolve({
633
+ ...params,
634
+ txPrebuild: recreated,
635
+ txHex,
636
+ });
637
+ }
638
+ getPublicNodeUrl(apiKey) {
639
+ if (apiKey) {
640
+ return Environments[this.bitgo.getEnv()].solAlchemyNodeUrl + `/${apiKey}`;
641
+ }
642
+ return Environments[this.bitgo.getEnv()].solNodeUrl;
643
+ }
644
+ /**
645
+ * Make a request to one of the public SOL nodes available
646
+ * @param params.payload
647
+ */
648
+ async getDataFromNode(params, apiKey) {
649
+ const nodeUrl = this.getPublicNodeUrl(apiKey);
650
+ try {
651
+ return await request.post(nodeUrl).send(params.payload);
652
+ }
653
+ catch (e) {
654
+ console.debug(e);
655
+ }
656
+ throw new Error(`Unable to call endpoint: '/' from node: ${nodeUrl}`);
657
+ }
658
+ async getBlockhash(apiKey) {
659
+ const response = await this.getDataFromNode({
660
+ payload: {
661
+ id: '1',
662
+ jsonrpc: '2.0',
663
+ method: 'getLatestBlockhash',
664
+ params: [
665
+ {
666
+ commitment: 'finalized',
667
+ },
668
+ ],
669
+ },
670
+ }, apiKey);
671
+ if (response.status !== 200) {
672
+ throw new Error('Account not found');
673
+ }
674
+ return response.body.result.value.blockhash;
675
+ }
676
+ async getFeeForMessage(message, apiKey) {
677
+ const response = await this.getDataFromNode({
678
+ payload: {
679
+ id: '1',
680
+ jsonrpc: '2.0',
681
+ method: 'getFeeForMessage',
682
+ params: [
683
+ message,
684
+ {
685
+ commitment: 'finalized',
686
+ },
687
+ ],
688
+ },
689
+ }, apiKey);
690
+ if (response.status !== 200) {
691
+ throw new Error('Account not found');
692
+ }
693
+ return response.body.result.value;
694
+ }
695
+ async getRentExemptAmount(apiKey) {
696
+ const response = await this.getDataFromNode({
697
+ payload: {
698
+ jsonrpc: '2.0',
699
+ id: '1',
700
+ method: 'getMinimumBalanceForRentExemption',
701
+ params: [165],
702
+ },
703
+ }, apiKey);
704
+ if (response.status !== 200 || response.error) {
705
+ throw new Error(JSON.stringify(response.error));
706
+ }
707
+ return response.body.result;
708
+ }
709
+ async getAccountBalance(pubKey, apiKey) {
710
+ const response = await this.getDataFromNode({
711
+ payload: {
712
+ id: '1',
713
+ jsonrpc: '2.0',
714
+ method: 'getBalance',
715
+ params: [pubKey],
716
+ },
717
+ }, apiKey);
718
+ if (response.status !== 200) {
719
+ throw new Error('Account not found');
720
+ }
721
+ return response.body.result.value;
722
+ }
723
+ async getAccountInfo(pubKey, apiKey) {
724
+ const response = await this.getDataFromNode({
725
+ payload: {
726
+ id: '1',
727
+ jsonrpc: '2.0',
728
+ method: 'getAccountInfo',
729
+ params: [
730
+ pubKey,
731
+ {
732
+ encoding: 'jsonParsed',
733
+ },
734
+ ],
735
+ },
736
+ }, apiKey);
737
+ if (response.status !== 200) {
738
+ throw new Error('Account not found');
739
+ }
740
+ return {
741
+ authority: response.body.result.value.data.parsed.info.authority,
742
+ blockhash: response.body.result.value.data.parsed.info.blockhash,
743
+ };
744
+ }
745
+ async getTokenAccountsByOwner(pubKey = '', programId = '', apiKey) {
746
+ const response = await this.getDataFromNode({
747
+ payload: {
748
+ id: '1',
749
+ jsonrpc: '2.0',
750
+ method: 'getTokenAccountsByOwner',
751
+ params: [
752
+ pubKey,
753
+ {
754
+ programId: programId.toString().toLowerCase() === TOKEN_2022_PROGRAM_ID.toString().toLowerCase()
755
+ ? TOKEN_2022_PROGRAM_ID.toString()
756
+ : TOKEN_PROGRAM_ID.toString(),
757
+ },
758
+ {
759
+ encoding: 'jsonParsed',
760
+ },
761
+ ],
762
+ },
763
+ }, apiKey);
764
+ if (response.status !== 200) {
765
+ throw new Error('Account not found');
766
+ }
767
+ if (response.body.result.value.length !== 0) {
768
+ const tokenAccounts = [];
769
+ for (const tokenAccount of response.body.result.value) {
770
+ tokenAccounts.push({ info: tokenAccount.account.data.parsed.info, pubKey: tokenAccount.pubKey });
771
+ }
772
+ return tokenAccounts;
773
+ }
774
+ return [];
775
+ }
776
+ async getTokenAccountInfo(pubKey, apiKey) {
777
+ const response = await this.getDataFromNode({
778
+ payload: {
779
+ id: '1',
780
+ jsonrpc: '2.0',
781
+ method: 'getAccountInfo',
782
+ params: [
783
+ pubKey,
784
+ {
785
+ encoding: 'jsonParsed',
786
+ },
787
+ ],
788
+ },
789
+ }, apiKey);
790
+ if (response.status !== 200) {
791
+ throw new Error('Account not found');
792
+ }
793
+ return {
794
+ pubKey: pubKey,
795
+ info: response.body.result.value.data.parsed.info,
796
+ };
797
+ }
798
+ /**
799
+ * Build a minimal `Connection`-like shim backed by {@link getDataFromNode}.
800
+ *
801
+ * `@solana/spl-token`'s transfer-hook resolution helpers only require
802
+ * `getAccountInfo(publicKey)` returning an `AccountInfo<Buffer>`. Rather than
803
+ * open a second RPC transport, we reuse the existing public-node request path
804
+ * as the {@link SolAccountFetcher} (base64-decoding the JSON-RPC response here),
805
+ * then adapt it via {@link buildSolAccountConnection}.
806
+ *
807
+ * @param {string} [apiKey] - optional Alchemy API key threaded to the node URL
808
+ * @returns {Connection} a shim exposing `getAccountInfo`, cast to `Connection`
809
+ */
810
+ buildTransferHookConnection(apiKey) {
811
+ const fetch = async (address) => {
812
+ const response = await this.getDataFromNode({
813
+ payload: {
814
+ id: '1',
815
+ jsonrpc: '2.0',
816
+ method: 'getAccountInfo',
817
+ params: [address, { encoding: 'base64' }],
818
+ },
819
+ }, apiKey);
820
+ if (response.status !== 200) {
821
+ throw new Error('Account not found');
822
+ }
823
+ const value = response.body?.result?.value;
824
+ if (!value) {
825
+ return null;
826
+ }
827
+ const [data] = value.data;
828
+ return {
829
+ executable: value.executable,
830
+ owner: new SolPublicKey(value.owner),
831
+ lamports: value.lamports,
832
+ data: Buffer.from(data, 'base64'),
833
+ rentEpoch: value.rentEpoch,
834
+ };
835
+ };
836
+ return buildSolAccountConnection(fetch);
837
+ }
838
+ /**
839
+ * Resolve the Token-2022 Transfer Hook extra accounts for a specific transfer.
840
+ *
841
+ * Thin wrapper around {@link resolveTransferHookAccountsLib}: builds a connection
842
+ * over this coin's node transport and delegates the resolution. See the standalone
843
+ * function in `./lib/token2022Resolve` for the full behavior.
844
+ *
845
+ * Builders remain offline, so the caller (e.g. wallet-platform) is responsible
846
+ * for invoking this and threading the result into the token-transfer builder via
847
+ * `transferHookAccounts(...)`. When the mint has no Transfer Hook, this returns
848
+ * an empty array and callers can omit the param.
849
+ *
850
+ * @param {string} mint - the Token-2022 mint address
851
+ * @param {string} source - the source token account (sender ATA)
852
+ * @param {string} destination - the destination token account (recipient ATA)
853
+ * @param {string} owner - the source account owner / transfer authority
854
+ * @param {string} amount - the raw transfer amount in base units
855
+ * @param {string} [apiKey] - optional Alchemy API key threaded to the node URL
856
+ * @returns {Promise<ExtraAccountMeta[]>} ordered extra account metas, or [] when no hook
857
+ */
858
+ async resolveTransferHookAccounts(mint, source, destination, owner, amount, apiKey) {
859
+ const connection = this.buildTransferHookConnection(apiKey);
860
+ return resolveTransferHookAccountsLib(connection, { mint, source, destination, owner, amount });
861
+ }
862
+ /**
863
+ * Resolve the sRFC-37 Token ACL permissionless-thaw dependencies for a token account.
864
+ *
865
+ * Thin wrapper around {@link resolvePermissionlessThawLib}: builds a connection
866
+ * over this coin's node transport and delegates the resolution. See the standalone
867
+ * function in `./lib/token2022Resolve` for the full behavior.
868
+ *
869
+ * Builders remain offline, so the caller (e.g. wallet-platform) invokes this and threads the
870
+ * result into the token-transfer builder via `permissionlessThaw(...)`, which bundles the thaw
871
+ * atomically with any ATA creation and the transfer. When the mint is not a Token ACL mint, or
872
+ * permissionless thaw is disabled, this returns `{ applicable: false }` and callers skip the thaw.
873
+ *
874
+ * @param {string} mint - the Token-2022 mint address
875
+ * @param {string} tokenAccount - the token account (ATA) to thaw
876
+ * @param {string} tokenAccountOwner - the owner of the token account
877
+ * @param {string} authority - the signer invoking the thaw (fee payer / authority)
878
+ * @param {string} [apiKey] - optional Alchemy API key threaded to the node URL
879
+ * @returns {Promise<ResolvePermissionlessThawResult>} the resolved thaw params, or `{ applicable: false }`
880
+ */
881
+ async resolvePermissionlessThaw(mint, tokenAccount, tokenAccountOwner, authority, apiKey) {
882
+ const connection = this.buildTransferHookConnection(apiKey);
883
+ return resolvePermissionlessThawLib(connection, { mint, tokenAccount, tokenAccountOwner, authority });
884
+ }
885
+ /** inherited doc */
886
+ async createBroadcastableSweepTransaction(params) {
887
+ if (!params.signatureShares) {
888
+ ('Missing transaction(s)');
889
+ }
890
+ const req = params.signatureShares;
891
+ const broadcastableTransactions = [];
892
+ let lastScanIndex = 0;
893
+ for (let i = 0; i < req.length; i++) {
894
+ const MPC = await EDDSAMethods.getInitializedMpcInstance();
895
+ const transaction = req[i].txRequest.transactions[0].unsignedTx;
896
+ if (!req[i].ovc || !req[i].ovc[0].eddsaSignature) {
897
+ throw new Error('Missing signature(s)');
898
+ }
899
+ const signature = req[i].ovc[0].eddsaSignature;
900
+ if (!transaction.signableHex) {
901
+ throw new Error('Missing signable hex');
902
+ }
903
+ const messageBuffer = Buffer.from(transaction.signableHex, 'hex');
904
+ const result = MPC.verify(messageBuffer, signature);
905
+ if (!result) {
906
+ throw new Error('Invalid signature');
907
+ }
908
+ const signatureHex = Buffer.concat([Buffer.from(signature.R, 'hex'), Buffer.from(signature.sigma, 'hex')]);
909
+ const txBuilder = this.getBuilder().from(transaction.serializedTx);
910
+ if (!transaction.coinSpecific?.commonKeychain) {
911
+ throw new Error('Missing common keychain');
912
+ }
913
+ const commonKeychain = transaction.coinSpecific.commonKeychain;
914
+ if (!transaction.derivationPath) {
915
+ throw new Error('Missing derivation path');
916
+ }
917
+ const derivationPath = transaction.derivationPath;
918
+ const accountId = MPC.deriveUnhardened(commonKeychain, derivationPath).slice(0, 64);
919
+ const bs58EncodedPublicKey = new SolKeyPair({ pub: accountId }).getAddress();
920
+ // add combined signature from ovc
921
+ const publicKeyObj = { pub: bs58EncodedPublicKey };
922
+ txBuilder.addSignature(publicKeyObj, signatureHex);
923
+ const signedTransaction = await txBuilder.build();
924
+ const serializedTx = signedTransaction.toBroadcastFormat();
925
+ broadcastableTransactions.push({
926
+ serializedTx: serializedTx,
927
+ scanIndex: transaction.scanIndex,
928
+ });
929
+ if (i === req.length - 1 && transaction.coinSpecific.lastScanIndex) {
930
+ lastScanIndex = transaction.coinSpecific.lastScanIndex;
931
+ }
932
+ }
933
+ return { transactions: broadcastableTransactions, lastScanIndex };
934
+ }
935
+ /**
936
+ * Builds a funds recovery transaction without BitGo
937
+ * @param {SolRecoveryOptions} params parameters needed to construct and
938
+ * (maybe) sign the transaction
939
+ *
940
+ * @returns {MPCTx | MPCSweepTxs} the serialized transaction hex string and index
941
+ * of the address being swept
942
+ */
943
+ async recover(params) {
944
+ if (!params.bitgoKey) {
945
+ throw new Error('missing bitgoKey');
946
+ }
947
+ if (!params.recoveryDestination || !this.isValidAddress(params.recoveryDestination)) {
948
+ throw new Error('invalid recoveryDestination');
949
+ }
950
+ const bitgoKey = params.bitgoKey.replace(/\s/g, '');
951
+ const isUnsignedSweep = !params.walletPassphrase;
952
+ // Validate signing keys and detect MPCv2 format early for signed recovery.
953
+ // When multisigTypeVersion is pre-resolved by the caller (e.g. recoverConsolidations),
954
+ // skip keycard decryption to avoid redundant work on each loop iteration.
955
+ const isMpcV2 = params.multisigTypeVersion === 'MPCv2'
956
+ ? true
957
+ : await this.isMpcv2SigningMaterial(params.userKey, params.backupKey, params.walletPassphrase);
958
+ let balance = 0;
959
+ const index = params.index || 0;
960
+ const currPath = params.seed ? getDerivationPath(params.seed) + `/${index}` : `m/${index}`;
961
+ const MPC = await EDDSAMethods.getInitializedMpcInstance();
962
+ const accountId = MPC.deriveUnhardened(bitgoKey, currPath).slice(0, 64);
963
+ const bs58EncodedPublicKey = new SolKeyPair({ pub: accountId }).getAddress();
964
+ balance = await this.getAccountBalance(bs58EncodedPublicKey, params.apiKey);
965
+ const factory = this.getBuilder();
966
+ const walletCoin = this.getChain();
967
+ let txBuilder;
968
+ let blockhash = await this.getBlockhash(params.apiKey);
969
+ let rentExemptAmount;
970
+ let authority = '';
971
+ let totalFee = new BigNumber(0);
972
+ let totalFeeForTokenRecovery = new BigNumber(0);
973
+ // check for possible token recovery, recover the token provide by user
974
+ if (params.tokenContractAddress) {
975
+ let isUnsupportedToken = false;
976
+ const tokenAccounts = await this.getTokenAccountsByOwner(bs58EncodedPublicKey, params.programId, params.apiKey);
977
+ if (tokenAccounts.length !== 0) {
978
+ // there exists token accounts on the given address, but need to check certain conditions:
979
+ // 1. if there is a recoverable balance
980
+ // 2. if the token is supported by bitgo
981
+ const recovereableTokenAccounts = [];
982
+ for (const tokenAccount of tokenAccounts) {
983
+ if (params.tokenContractAddress === tokenAccount.info.mint) {
984
+ const tokenAmount = new BigNumber(tokenAccount.info.tokenAmount.amount);
985
+ const network = this.getNetwork();
986
+ const token = getSolTokenFromAddress(tokenAccount.info.mint, network); // todo(WIN-5894) fix for ams
987
+ if (!token) {
988
+ isUnsupportedToken = true;
989
+ }
990
+ if (tokenAmount.gt(new BigNumber(0))) {
991
+ tokenAccount.tokenName = token?.name || 'Unsupported Token';
992
+ recovereableTokenAccounts.push(tokenAccount);
993
+ }
994
+ break;
995
+ }
996
+ }
997
+ if (recovereableTokenAccounts.length !== 0) {
998
+ rentExemptAmount = await this.getRentExemptAmount(params.apiKey);
999
+ txBuilder = factory
1000
+ .getTokenTransferBuilder()
1001
+ .nonce(blockhash)
1002
+ .sender(bs58EncodedPublicKey)
1003
+ .associatedTokenAccountRent(rentExemptAmount.toString())
1004
+ .feePayer(bs58EncodedPublicKey);
1005
+ // need to get all token accounts of the recipient address and need to create them if they do not exist
1006
+ const recipientTokenAccounts = await this.getTokenAccountsByOwner(params.recoveryDestination, params.programId, params.apiKey);
1007
+ for (const tokenAccount of recovereableTokenAccounts) {
1008
+ let recipientTokenAccountExists = false;
1009
+ for (const recipientTokenAccount of recipientTokenAccounts) {
1010
+ if (recipientTokenAccount.info.mint === tokenAccount.info.mint) {
1011
+ recipientTokenAccountExists = true;
1012
+ break;
1013
+ }
1014
+ }
1015
+ const recipientTokenAccount = await getAssociatedTokenAccountAddress(tokenAccount.info.mint, params.recoveryDestination, false, params.programId?.toString());
1016
+ const tokenName = tokenAccount.tokenName;
1017
+ const sendParams = {
1018
+ address: recipientTokenAccount,
1019
+ amount: tokenAccount.info.tokenAmount.amount,
1020
+ tokenName,
1021
+ ...(isUnsupportedToken
1022
+ ? {
1023
+ tokenAddress: tokenAccount.info.mint,
1024
+ programId: params.programId?.toString(),
1025
+ decimalPlaces: tokenAccount.info.tokenAmount.decimals,
1026
+ }
1027
+ : {}),
1028
+ };
1029
+ txBuilder.send(sendParams);
1030
+ if (!recipientTokenAccountExists) {
1031
+ // recipient token account does not exist for token and must be created
1032
+ txBuilder.createAssociatedTokenAccount({
1033
+ ownerAddress: params.recoveryDestination,
1034
+ tokenName: tokenName,
1035
+ ...(isUnsupportedToken ? { tokenAddress: tokenAccount.info.mint } : {}),
1036
+ programId: params.programId?.toString().toLowerCase() === TOKEN_2022_PROGRAM_ID.toString().toLowerCase()
1037
+ ? TOKEN_2022_PROGRAM_ID.toString()
1038
+ : TOKEN_PROGRAM_ID.toString(),
1039
+ });
1040
+ // add rent exempt amount to total fee for each token account that has to be created
1041
+ totalFeeForTokenRecovery = totalFeeForTokenRecovery.plus(rentExemptAmount);
1042
+ }
1043
+ }
1044
+ }
1045
+ else {
1046
+ throw Error('Not enough token funds to recover');
1047
+ }
1048
+ }
1049
+ else {
1050
+ // there are no recoverable token accounts , need to check if there are tokens to recover
1051
+ throw Error('Did not find token account to recover tokens, please check token account');
1052
+ }
1053
+ }
1054
+ else {
1055
+ txBuilder = factory
1056
+ .getTransferBuilder()
1057
+ .nonce(blockhash)
1058
+ .sender(bs58EncodedPublicKey)
1059
+ .send({ address: params.recoveryDestination, amount: balance.toString() })
1060
+ .feePayer(bs58EncodedPublicKey);
1061
+ }
1062
+ if (params.durableNonce) {
1063
+ const durableNonceInfo = await this.getAccountInfo(params.durableNonce.publicKey, params.apiKey);
1064
+ blockhash = durableNonceInfo.blockhash;
1065
+ authority = durableNonceInfo.authority;
1066
+ txBuilder.nonce(blockhash, {
1067
+ walletNonceAddress: params.durableNonce.publicKey,
1068
+ authWalletAddress: authority,
1069
+ });
1070
+ }
1071
+ // build the transaction without fee
1072
+ const unsignedTransactionWithoutFee = (await txBuilder.build());
1073
+ const serializedMessage = unsignedTransactionWithoutFee.solTransaction.serializeMessage().toString('base64');
1074
+ const baseFee = await this.getFeeForMessage(serializedMessage, params.apiKey);
1075
+ const feePerSignature = params.durableNonce ? baseFee / 2 : baseFee;
1076
+ totalFee = totalFee.plus(new BigNumber(baseFee));
1077
+ totalFeeForTokenRecovery = totalFeeForTokenRecovery.plus(new BigNumber(baseFee));
1078
+ if (totalFee.gt(balance)) {
1079
+ throw Error('Did not find address with funds to recover');
1080
+ }
1081
+ if (params.tokenContractAddress) {
1082
+ // Check if there is sufficient native solana to recover tokens
1083
+ if (new BigNumber(balance).lt(totalFeeForTokenRecovery)) {
1084
+ throw Error('Not enough funds to pay for recover tokens fees, have: ' +
1085
+ balance +
1086
+ ' need: ' +
1087
+ totalFeeForTokenRecovery.toString());
1088
+ }
1089
+ txBuilder.fee({ amount: feePerSignature });
1090
+ }
1091
+ else {
1092
+ const netAmount = new BigNumber(balance).minus(totalFee);
1093
+ txBuilder = factory
1094
+ .getTransferBuilder()
1095
+ .nonce(blockhash)
1096
+ .sender(bs58EncodedPublicKey)
1097
+ .send({ address: params.recoveryDestination, amount: netAmount.toString() })
1098
+ .feePayer(bs58EncodedPublicKey)
1099
+ .fee({ amount: feePerSignature });
1100
+ if (params.durableNonce) {
1101
+ txBuilder.nonce(blockhash, {
1102
+ walletNonceAddress: params.durableNonce.publicKey,
1103
+ authWalletAddress: authority,
1104
+ });
1105
+ }
1106
+ }
1107
+ if (!isUnsignedSweep) {
1108
+ // Sign the txn
1109
+ if (!params.userKey) {
1110
+ throw new Error('missing userKey');
1111
+ }
1112
+ if (!params.backupKey) {
1113
+ throw new Error('missing backupKey');
1114
+ }
1115
+ if (!params.walletPassphrase) {
1116
+ throw new Error('missing wallet passphrase');
1117
+ }
1118
+ // build the transaction with fee
1119
+ const unsignedTransaction = (await txBuilder.build());
1120
+ await this.addRecoverySignature(params, txBuilder, bs58EncodedPublicKey, isMpcV2, unsignedTransaction, currPath, bitgoKey);
1121
+ }
1122
+ if (params.durableNonce) {
1123
+ // add durable nonce account signature
1124
+ txBuilder.sign({ key: params.durableNonce.secretKey });
1125
+ }
1126
+ const completedTransaction = await txBuilder.build();
1127
+ const serializedTx = completedTransaction.toBroadcastFormat();
1128
+ const derivationPath = params.seed ? getDerivationPath(params.seed) + `/${index}` : `m/${index}`;
1129
+ const inputs = [];
1130
+ for (const input of completedTransaction.inputs) {
1131
+ inputs.push({
1132
+ address: input.address,
1133
+ valueString: input.value,
1134
+ value: new BigNumber(input.value).toNumber(),
1135
+ });
1136
+ }
1137
+ const outputs = [];
1138
+ for (const output of completedTransaction.outputs) {
1139
+ outputs.push({
1140
+ address: output.address,
1141
+ valueString: output.value,
1142
+ coinName: output.coin ? output.coin : walletCoin,
1143
+ });
1144
+ }
1145
+ const spendAmount = completedTransaction.inputs.length === 1 ? completedTransaction.inputs[0].value : 0;
1146
+ const parsedTx = { inputs: inputs, outputs: outputs, spendAmount: spendAmount, type: '' };
1147
+ const feeInfo = { fee: totalFeeForTokenRecovery.toNumber(), feeString: totalFee.toString() };
1148
+ const coinSpecific = { commonKeychain: bitgoKey };
1149
+ if (isUnsignedSweep) {
1150
+ const transaction = {
1151
+ serializedTx: serializedTx,
1152
+ scanIndex: index,
1153
+ coin: walletCoin,
1154
+ signableHex: completedTransaction.signablePayload.toString('hex'),
1155
+ derivationPath: derivationPath,
1156
+ parsedTx: parsedTx,
1157
+ feeInfo: feeInfo,
1158
+ coinSpecific: coinSpecific,
1159
+ };
1160
+ const unsignedTx = { unsignedTx: transaction, signatureShares: [] };
1161
+ const transactions = [unsignedTx];
1162
+ const txRequest = {
1163
+ transactions: transactions,
1164
+ walletCoin: walletCoin,
1165
+ };
1166
+ const txRequests = { txRequests: [txRequest] };
1167
+ return txRequests;
1168
+ }
1169
+ const transaction = {
1170
+ serializedTx: serializedTx,
1171
+ scanIndex: index,
1172
+ };
1173
+ return transaction;
1174
+ }
1175
+ /**
1176
+ * Builds a funds recovery transaction without BitGo
1177
+ * @param {SolRecoveryOptions} params parameters needed to construct and
1178
+ * (maybe) sign the transaction
1179
+ *
1180
+ * @returns {BaseBroadcastTransactionResult[]} the serialized transaction hex string and index
1181
+ * of the address being swept
1182
+ */
1183
+ async recoverCloseATA(params) {
1184
+ if (!params.bitgoKey) {
1185
+ throw new Error('missing bitgoKey');
1186
+ }
1187
+ if (!params.recoveryDestination || !this.isValidAddress(params.recoveryDestination)) {
1188
+ throw new Error('invalid recoveryDestination');
1189
+ }
1190
+ if (!params.closeAtaAddress || !this.isValidAddress(params.closeAtaAddress)) {
1191
+ throw new Error('invalid closeAtaAddress');
1192
+ }
1193
+ const bitgoKey = params.bitgoKey.replace(/\s/g, '');
1194
+ // Validate signing keys and detect MPCv2 format early
1195
+ const isMpcV2 = await this.isMpcv2SigningMaterial(params.userKey, params.backupKey, params.walletPassphrase);
1196
+ // Build the transaction
1197
+ let balance = 0;
1198
+ const index = params.index || 0;
1199
+ const currPath = params.seed ? getDerivationPath(params.seed) + `/${index}` : `m/${index}`;
1200
+ const MPC = await EDDSAMethods.getInitializedMpcInstance();
1201
+ const accountId = MPC.deriveUnhardened(bitgoKey, currPath).slice(0, 64);
1202
+ const bs58EncodedPublicKey = new SolKeyPair({ pub: accountId }).getAddress();
1203
+ const accountBalance = await this.getAccountBalance(bs58EncodedPublicKey);
1204
+ balance = await this.getAccountBalance(params.closeAtaAddress);
1205
+ if (balance <= 0) {
1206
+ throw Error('Did not find closeAtaAddress with sol funds to recover');
1207
+ }
1208
+ const factory = this.getBuilder();
1209
+ let txBuilder;
1210
+ let blockhash;
1211
+ const recovertTxns = [];
1212
+ const rentExemptAmount = await this.getRentExemptAmount();
1213
+ // do token recovery before closing ATA address
1214
+ // check if any token is present on the closeAtaAddress
1215
+ const tokenInfo = await this.getTokenAccountInfo(params.closeAtaAddress);
1216
+ const tokenBalance = Number(tokenInfo.info.tokenAmount.amount);
1217
+ if (tokenBalance > 0) {
1218
+ // closeATA address has some token balance, it needs to be withdrawn before closing ATA
1219
+ console.log(`closeATA address ${params.closeAtaAddress} has token balance ${tokenBalance}, it needs to be withdrawn before closing ATA address`);
1220
+ if (!params.recoveryDestinationAtaAddress || !this.isValidAddress(params.recoveryDestinationAtaAddress)) {
1221
+ throw new Error('invalid recoveryDestinationAtaAddress');
1222
+ }
1223
+ blockhash = await this.getBlockhash(params.apiKey);
1224
+ txBuilder = factory
1225
+ .getTokenTransferBuilder()
1226
+ .nonce(blockhash)
1227
+ .sender(bs58EncodedPublicKey)
1228
+ .associatedTokenAccountRent(rentExemptAmount.toString())
1229
+ .feePayer(bs58EncodedPublicKey);
1230
+ const unsignedTransaction = (await txBuilder.build());
1231
+ const serializedMessage = unsignedTransaction.solTransaction.serializeMessage().toString('base64');
1232
+ const feePerSignature = await this.getFeeForMessage(serializedMessage, params.apiKey);
1233
+ const baseFee = params.durableNonce ? feePerSignature * 2 : feePerSignature;
1234
+ const totalFee = new BigNumber(baseFee);
1235
+ if (totalFee.gt(accountBalance)) {
1236
+ throw Error('Did not find address with funds to recover');
1237
+ }
1238
+ txBuilder.fee({ amount: feePerSignature });
1239
+ const network = this.getNetwork();
1240
+ const token = getSolTokenFromAddress(tokenInfo.info.mint, network); // todo(WIN-5894) fix for ams
1241
+ txBuilder.send({
1242
+ address: params.recoveryDestinationAtaAddress,
1243
+ amount: tokenBalance,
1244
+ tokenName: token?.name,
1245
+ });
1246
+ const tokenRecoveryTxn = await this.signAndGenerateBroadcastableTransaction(params, txBuilder, bs58EncodedPublicKey, isMpcV2);
1247
+ const serializedTokenRecoveryTxn = (await tokenRecoveryTxn).serializedTx;
1248
+ const broadcastTokenRecoveryTxn = await this.broadcastTransaction({
1249
+ serializedSignedTransaction: serializedTokenRecoveryTxn,
1250
+ });
1251
+ logger.log(broadcastTokenRecoveryTxn);
1252
+ recovertTxns.push(broadcastTokenRecoveryTxn);
1253
+ }
1254
+ // after recovering the token amount, attempting to close the ATA address
1255
+ if (params.closeAtaAddress) {
1256
+ blockhash = await this.getBlockhash(params.apiKey);
1257
+ const ataCloseBuilder = () => {
1258
+ const txBuilder = factory.getCloseAtaInitializationBuilder();
1259
+ txBuilder.nonce(blockhash);
1260
+ txBuilder.sender(bs58EncodedPublicKey);
1261
+ txBuilder.accountAddress(params.closeAtaAddress ?? '');
1262
+ txBuilder.destinationAddress(params.recoveryDestination);
1263
+ txBuilder.authorityAddress(bs58EncodedPublicKey);
1264
+ txBuilder.associatedTokenAccountRent(rentExemptAmount.toString());
1265
+ return txBuilder;
1266
+ };
1267
+ txBuilder = ataCloseBuilder();
1268
+ }
1269
+ const closeATARecoveryTxn = await this.signAndGenerateBroadcastableTransaction(params, txBuilder, bs58EncodedPublicKey, isMpcV2);
1270
+ const serializedCloseATARecoveryTxn = (await closeATARecoveryTxn).serializedTx;
1271
+ const broadcastCloseATARecoveryTxn = await this.broadcastTransaction({
1272
+ serializedSignedTransaction: serializedCloseATARecoveryTxn,
1273
+ });
1274
+ logger.log(broadcastCloseATARecoveryTxn);
1275
+ recovertTxns.push(broadcastCloseATARecoveryTxn);
1276
+ return recovertTxns;
1277
+ }
1278
+ /**
1279
+ * Recovers tokens from a nested ATA — an ATA whose owner is another ATA rather than a wallet address.
1280
+ *
1281
+ * This situation occurs when an external sender mistakenly calls createAssociatedTokenAccount with
1282
+ * an ATA address as the owner instead of the root wallet address. The result is a "nested ATA"
1283
+ * (ATA-2) owned by the wallet's normal ATA (ATA-1). Because ATA-1 is a PDA with no private key,
1284
+ * the standard recoverCloseATA flow cannot sign for ATA-2.
1285
+ *
1286
+ * This method uses the Associated Token Account program's RecoverNested instruction, which allows
1287
+ * the root wallet owner to sign and atomically move tokens from ATA-2 → ATA-1 and close ATA-2,
1288
+ * returning the rent-exempt SOL to the wallet address.
1289
+ *
1290
+ * @param {SolRecoveryOptions} params - recovery params, requires nestedAtaAddress, ownerAtaAddress,
1291
+ * and tokenMintAddress in addition to the standard keychain fields
1292
+ */
1293
+ async recoverNestedAta(params) {
1294
+ if (!params.bitgoKey) {
1295
+ throw new Error('missing bitgoKey');
1296
+ }
1297
+ if (!params.recoveryDestination || !this.isValidAddress(params.recoveryDestination)) {
1298
+ throw new Error('invalid recoveryDestination');
1299
+ }
1300
+ if (!params.nestedAtaAddress || !this.isValidAddress(params.nestedAtaAddress)) {
1301
+ throw new Error('invalid nestedAtaAddress');
1302
+ }
1303
+ if (!params.ownerAtaAddress || !this.isValidAddress(params.ownerAtaAddress)) {
1304
+ throw new Error('invalid ownerAtaAddress');
1305
+ }
1306
+ if (!params.tokenMintAddress || !this.isValidAddress(params.tokenMintAddress)) {
1307
+ throw new Error('invalid tokenMintAddress');
1308
+ }
1309
+ const bitgoKey = params.bitgoKey.replace(/\s/g, '');
1310
+ const userKey = params.userKey?.replace(/\s/g, '') ?? '';
1311
+ const isMpcV2 = params.walletPassphrase
1312
+ ? (await getEddsaSigningMaterial(userKey, params.walletPassphrase, this.bitgo)).version === 'v2'
1313
+ : false;
1314
+ const index = params.index || 0;
1315
+ const currPath = params.seed ? getDerivationPath(params.seed) + `/${index}` : `m/${index}`;
1316
+ const accountId = (await EDDSAMethods.getInitializedMpcInstance())
1317
+ .deriveUnhardened(bitgoKey, currPath)
1318
+ .slice(0, 64);
1319
+ const bs58EncodedPublicKey = new SolKeyPair({ pub: accountId }).getAddress();
1320
+ const blockhash = await this.getBlockhash(params.apiKey);
1321
+ const rentExemptAmount = await this.getRentExemptAmount();
1322
+ const factory = this.getBuilder();
1323
+ const txBuilder = factory.getRecoverNestedAtaBuilder();
1324
+ txBuilder.nonce(blockhash);
1325
+ txBuilder.sender(bs58EncodedPublicKey);
1326
+ txBuilder.feePayer(bs58EncodedPublicKey);
1327
+ txBuilder.associatedTokenAccountRent(rentExemptAmount.toString());
1328
+ txBuilder.nestedAccountAddress(params.nestedAtaAddress);
1329
+ txBuilder.nestedMintAddress(params.tokenMintAddress);
1330
+ txBuilder.destinationAccountAddress(params.ownerAtaAddress);
1331
+ txBuilder.ownerAccountAddress(params.ownerAtaAddress);
1332
+ txBuilder.ownerMintAddress(params.tokenMintAddress);
1333
+ txBuilder.walletAddress(bs58EncodedPublicKey);
1334
+ const recoverNestedTxn = await this.signAndGenerateBroadcastableTransaction(params, txBuilder, bs58EncodedPublicKey, isMpcV2);
1335
+ const serializedTxn = (await recoverNestedTxn).serializedTx;
1336
+ const broadcastResult = await this.broadcastTransaction({
1337
+ serializedSignedTransaction: serializedTxn,
1338
+ });
1339
+ logger.log(broadcastResult);
1340
+ return broadcastResult;
1341
+ }
1342
+ async signAndGenerateBroadcastableTransaction(params, txBuilder, bs58EncodedPublicKey, isMpcV2 = false) {
1343
+ if (!params.userKey) {
1344
+ throw new Error('missing userKey');
1345
+ }
1346
+ if (!params.backupKey) {
1347
+ throw new Error('missing backupKey');
1348
+ }
1349
+ if (!params.walletPassphrase) {
1350
+ throw new Error('missing wallet passphrase');
1351
+ }
1352
+ const unsignedTransaction = (await txBuilder.build());
1353
+ const index = params.index || 0;
1354
+ const currPath = params.seed ? getDerivationPath(params.seed) + `/${index}` : `m/${index}`;
1355
+ await this.addRecoverySignature(params, txBuilder, bs58EncodedPublicKey, isMpcV2, unsignedTransaction, currPath, params.bitgoKey.replace(/\s/g, ''));
1356
+ const completedTransaction = await txBuilder.build();
1357
+ const serializedTx = completedTransaction.toBroadcastFormat();
1358
+ const transaction = {
1359
+ serializedTx: serializedTx,
1360
+ scanIndex: index,
1361
+ };
1362
+ return transaction;
1363
+ }
1364
+ /**
1365
+ * Builds native SOL recoveries of receive addresses in batch without BitGo.
1366
+ * Funds will be recovered to base address first. You need to initiate another sweep txn after that.
1367
+ *
1368
+ * @param {SolConsolidationRecoveryOptions} params - options for consolidation recovery.
1369
+ * @param {string} [params.startingScanIndex] - receive address index to start scanning from. default to 1 (inclusive).
1370
+ * @param {string} [params.endingScanIndex] - receive address index to end scanning at. default to startingScanIndex + 20 (exclusive).
1371
+ */
1372
+ async recoverConsolidations(params) {
1373
+ if (!params.bitgoKey) {
1374
+ throw new Error('missing bitgoKey');
1375
+ }
1376
+ const isUnsignedSweep = !params.walletPassphrase;
1377
+ const startIdx = params.startingScanIndex || 1;
1378
+ const endIdx = params.endingScanIndex || startIdx + DEFAULT_SCAN_FACTOR;
1379
+ if (startIdx < 1 || endIdx <= startIdx || endIdx - startIdx > 10 * DEFAULT_SCAN_FACTOR) {
1380
+ throw new Error(`Invalid starting or ending index to scan for addresses. startingScanIndex: ${startIdx}, endingScanIndex: ${endIdx}.`);
1381
+ }
1382
+ // validate durable nonces array
1383
+ if (!params.durableNonces) {
1384
+ throw new Error('Missing durable nonces');
1385
+ }
1386
+ if (!params.durableNonces.publicKeys) {
1387
+ throw new Error('Invalid durable nonces: missing public keys');
1388
+ }
1389
+ if (!params.durableNonces.secretKey) {
1390
+ throw new Error('Invalid durable nonces array: missing secret key');
1391
+ }
1392
+ const bitgoKey = params.bitgoKey.replace(/\s/g, '');
1393
+ const userKey = params.userKey?.replace(/\s/g, '') ?? '';
1394
+ // Detect once at the top to avoid decrypting the keycard on every iteration of the scan loop.
1395
+ // For unsigned sweep (no passphrase), isMpcV2 is false — cold MPCv2 is out of scope.
1396
+ const isMpcV2 = params.walletPassphrase
1397
+ ? (await getEddsaSigningMaterial(userKey, params.walletPassphrase, this.bitgo)).version === 'v2'
1398
+ : false;
1399
+ const baseAddressIndex = 0;
1400
+ const baseAddressPath = params.seed
1401
+ ? getDerivationPath(params.seed) + `/${baseAddressIndex}`
1402
+ : `m/${baseAddressIndex}`;
1403
+ const baseAccountId = (await EDDSAMethods.getInitializedMpcInstance())
1404
+ .deriveUnhardened(bitgoKey, baseAddressPath)
1405
+ .slice(0, 64);
1406
+ const baseAddress = new SolKeyPair({ pub: baseAccountId }).getAddress();
1407
+ let durableNoncePubKeysIndex = 0;
1408
+ const durableNoncePubKeysLength = params.durableNonces.publicKeys.length;
1409
+ const consolidationTransactions = [];
1410
+ let lastScanIndex = startIdx;
1411
+ for (let i = startIdx; i < endIdx; i++) {
1412
+ const recoverParams = {
1413
+ userKey: params.userKey,
1414
+ backupKey: params.backupKey,
1415
+ bitgoKey: params.bitgoKey,
1416
+ walletPassphrase: params.walletPassphrase,
1417
+ multisigTypeVersion: isMpcV2 ? 'MPCv2' : undefined,
1418
+ recoveryDestination: baseAddress,
1419
+ seed: params.seed,
1420
+ index: i,
1421
+ durableNonce: {
1422
+ publicKey: params.durableNonces.publicKeys[durableNoncePubKeysIndex],
1423
+ secretKey: params.durableNonces.secretKey,
1424
+ },
1425
+ tokenContractAddress: params.tokenContractAddress,
1426
+ apiKey: params.apiKey,
1427
+ programId: params.programId,
1428
+ };
1429
+ let recoveryTransaction;
1430
+ try {
1431
+ recoveryTransaction = await this.recover(recoverParams);
1432
+ }
1433
+ catch (e) {
1434
+ if (e.message === 'Did not find address with funds to recover' ||
1435
+ e.message === 'Did not find token account to recover tokens, please check token account' ||
1436
+ e.message === 'Not enough token funds to recover') {
1437
+ lastScanIndex = i;
1438
+ continue;
1439
+ }
1440
+ throw e;
1441
+ }
1442
+ if (isUnsignedSweep) {
1443
+ consolidationTransactions.push(recoveryTransaction.txRequests[0]);
1444
+ }
1445
+ else {
1446
+ consolidationTransactions.push(recoveryTransaction);
1447
+ }
1448
+ lastScanIndex = i;
1449
+ durableNoncePubKeysIndex++;
1450
+ if (durableNoncePubKeysIndex >= durableNoncePubKeysLength) {
1451
+ // no more available nonce accounts to create transactions
1452
+ break;
1453
+ }
1454
+ }
1455
+ if (consolidationTransactions.length === 0) {
1456
+ throw new Error('Did not find an address with funds to recover');
1457
+ }
1458
+ if (isUnsignedSweep) {
1459
+ // lastScanIndex will be used to inform user the last address index scanned for available funds (so they can
1460
+ // appropriately adjust the scan range on the next iteration of consolidation recoveries). In the case of unsigned
1461
+ // sweep consolidations, this lastScanIndex will be provided in the coinSpecific of the last txn made.
1462
+ const lastTransactionCoinSpecific = {
1463
+ commonKeychain: consolidationTransactions[consolidationTransactions.length - 1].transactions[0].unsignedTx.coinSpecific
1464
+ .commonKeychain,
1465
+ lastScanIndex: lastScanIndex,
1466
+ };
1467
+ consolidationTransactions[consolidationTransactions.length - 1].transactions[0].unsignedTx.coinSpecific =
1468
+ lastTransactionCoinSpecific;
1469
+ const consolidationSweepTransactions = { txRequests: consolidationTransactions };
1470
+ return consolidationSweepTransactions;
1471
+ }
1472
+ return { transactions: consolidationTransactions, lastScanIndex };
1473
+ }
1474
+ getTokenEnablementConfig() {
1475
+ return {
1476
+ requiresTokenEnablement: true,
1477
+ supportsMultipleTokenEnablements: true,
1478
+ };
1479
+ }
1480
+ getBuilder() {
1481
+ return new TransactionBuilderFactory(coins.get(this.getChain()));
1482
+ }
1483
+ async addRecoverySignature(params, txBuilder, bs58EncodedPublicKey, isMpcV2, unsignedTransaction, currPath, bitgoKey) {
1484
+ assert(params.userKey, 'missing userKey');
1485
+ assert(params.backupKey, 'missing backupKey');
1486
+ const userKey = params.userKey.replace(/\s/g, '');
1487
+ const backupKey = params.backupKey.replace(/\s/g, '');
1488
+ if (!isMpcV2) {
1489
+ let userPrv;
1490
+ try {
1491
+ userPrv = await this.bitgo.decrypt({
1492
+ input: userKey,
1493
+ password: params.walletPassphrase,
1494
+ });
1495
+ }
1496
+ catch (e) {
1497
+ throw new Error(`Error decrypting user keychain: ${e.message}`);
1498
+ }
1499
+ const userSigningMaterial = JSON.parse(userPrv);
1500
+ let backupPrv;
1501
+ try {
1502
+ backupPrv = await this.bitgo.decrypt({
1503
+ input: backupKey,
1504
+ password: params.walletPassphrase,
1505
+ });
1506
+ }
1507
+ catch (e) {
1508
+ throw new Error(`Error decrypting backup keychain: ${e.message}`);
1509
+ }
1510
+ const backupSigningMaterial = JSON.parse(backupPrv);
1511
+ const signatureHex = await EDDSAMethods.getTSSSignature(userSigningMaterial, backupSigningMaterial, currPath, unsignedTransaction);
1512
+ txBuilder.addSignature({ pub: bs58EncodedPublicKey }, signatureHex);
1513
+ }
1514
+ else {
1515
+ const signature = await signEddsaMpcV2RecoveryTx({
1516
+ message: unsignedTransaction.signablePayload,
1517
+ userKey,
1518
+ backupKey,
1519
+ walletPassphrase: params.walletPassphrase,
1520
+ bitgoKey,
1521
+ derivationPath: currPath,
1522
+ bitgo: this.bitgo,
1523
+ });
1524
+ txBuilder.addSignature({ pub: bs58EncodedPublicKey }, signature);
1525
+ }
1526
+ }
1527
+ async isMpcv2SigningMaterial(userKey, backupKey, walletPassphrase) {
1528
+ if (!walletPassphrase)
1529
+ return false;
1530
+ if (!userKey)
1531
+ throw new Error('missing userKey');
1532
+ if (!backupKey)
1533
+ throw new Error('missing backupKey');
1534
+ const material = await getEddsaSigningMaterial(userKey.replace(/\s/g, ''), walletPassphrase, this.bitgo);
1535
+ return material.version === 'v2';
1536
+ }
1537
+ async broadcastTransaction({ serializedSignedTransaction, }) {
1538
+ validateRawTransaction(serializedSignedTransaction, true, true);
1539
+ const response = await this.getDataFromNode({
1540
+ payload: {
1541
+ id: '1',
1542
+ jsonrpc: '2.0',
1543
+ method: 'sendTransaction',
1544
+ params: [
1545
+ serializedSignedTransaction,
1546
+ {
1547
+ encoding: 'base64',
1548
+ },
1549
+ ],
1550
+ },
1551
+ });
1552
+ if (response.body.error) {
1553
+ throw new Error('Error broadcasting transaction: ' + response.body.error.message);
1554
+ }
1555
+ return { txId: response.body.result };
1556
+ }
1557
+ /** @inheritDoc */
1558
+ auditDecryptedKey({ prv, publicKey, multiSigType }) {
1559
+ if (multiSigType !== 'tss') {
1560
+ throw new Error('Unsupported multiSigType');
1561
+ }
1562
+ auditEddsaPrivateKey(prv, publicKey ?? '');
1563
+ }
1564
+ /** @inheritDoc */
1565
+ setCoinSpecificFieldsInIntent(intent, params) {
1566
+ // Handle custom instructions for Solana
1567
+ if (params.solInstructions) {
1568
+ intent.solInstructions = params.solInstructions;
1569
+ }
1570
+ // Handle versioned transaction data for Solana
1571
+ if (params.solVersionedTransactionData) {
1572
+ intent.solVersionedTransactionData = params.solVersionedTransactionData;
1573
+ }
1574
+ }
1575
+ }
1576
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic29sLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3NvbC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7R0FFRztBQUVILE9BQU8sRUFBRSxxQkFBcUIsRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBQzVFLE9BQU8sRUFBMkIsU0FBUyxJQUFJLFlBQVksRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQ3JGLE9BQU8sU0FBUyxNQUFNLGNBQWMsQ0FBQztBQUNyQyxPQUFPLEtBQUssTUFBTSxNQUFNLE1BQU0sQ0FBQztBQUMvQixPQUFPLEtBQUssQ0FBQyxNQUFNLFFBQVEsQ0FBQztBQUM1QixPQUFPLEtBQUssT0FBTyxNQUFNLFlBQVksQ0FBQztBQUN0QyxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFDNUMsT0FBTyxNQUFNLE1BQU0sUUFBUSxDQUFDO0FBRTVCLE9BQU8sRUFJTCxRQUFRLEVBS1IsWUFBWSxFQUVaLFlBQVksRUFhWixhQUFhLEVBaUJiLGVBQWUsRUFHZiwyQkFBMkIsRUFDM0Isc0JBQXNCLEVBR3RCLHNCQUFzQixFQUN0Qix1QkFBdUIsRUFDdkIsd0JBQXdCLEdBQ3pCLE1BQU0sc0JBQXNCLENBQUM7QUFDOUIsT0FBTyxFQUFFLG9CQUFvQixFQUFFLGlCQUFpQixFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDbEYsT0FBTyxFQUEyQixLQUFLLEVBQXdDLE1BQU0scUJBQXFCLENBQUM7QUFDM0csT0FBTyxFQUNMLE9BQU8sSUFBSSxVQUFVLEVBQ3JCLFdBQVcsRUFDWCxrQkFBa0IsRUFDbEIseUJBQXlCLEVBQ3pCLHFCQUFxQixHQUN0QixNQUFNLE9BQU8sQ0FBQztBQU9mLE9BQU8sRUFBRSx1QkFBdUIsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQzFELE9BQU8sRUFHTCx5QkFBeUIsRUFDekIseUJBQXlCLElBQUksNEJBQTRCLEVBQ3pELDJCQUEyQixJQUFJLDhCQUE4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XG4gKi9cblxuaW1wb3J0IHsgVE9LRU5fMjAyMl9QUk9HUkFNX0lELCBUT0tFTl9QUk9HUkFNX0lEIH0gZnJvbSAnQHNvbGFuYS9zcGwtdG9rZW4nO1xuaW1wb3J0IHsgQWNjb3VudEluZm8sIENvbm5lY3Rpb24sIFB1YmxpY0tleSBhcyBTb2xQdWJsaWNLZXkgfSBmcm9tICdAc29sYW5hL3dlYjMuanMnO1xuaW1wb3J0IEJpZ051bWJlciBmcm9tICdiaWdudW1iZXIuanMnO1xuaW1wb3J0ICogYXMgYmFzZTU4IGZyb20gJ2JzNTgnO1xuaW1wb3J0ICogYXMgXyBmcm9tICdsb2Rhc2gnO1xuaW1wb3J0ICogYXMgcmVxdWVzdCBmcm9tICdzdXBlcmFnZW50JztcbmltcG9ydCB7IGxvZ2dlciB9IGZyb20gJ0BiaXRnby1iZXRhL2xvZ2dlcic7XG5pbXBvcnQgYXNzZXJ0IGZyb20gJ2Fzc2VydCc7XG5cbmltcG9ydCB7XG4gIEF1ZGl0RGVjcnlwdGVkS2V5UGFyYW1zLFxuICBCYXNlQnJvYWRjYXN0VHJhbnNhY3Rpb25PcHRpb25zLFxuICBCYXNlQnJvYWRjYXN0VHJhbnNhY3Rpb25SZXN1bHQsXG4gIEJhc2VDb2luLFxuICBQYXJzZVRyYW5zYWN0aW9uT3B0aW9ucyBhcyBCYXNlUGFyc2VUcmFuc2FjdGlvbk9wdGlvbnMsXG4gIEJhc2VUcmFuc2FjdGlvbixcbiAgVHJhbnNhY3Rpb25QcmVidWlsZCBhcyBCYXNlVHJhbnNhY3Rpb25QcmVidWlsZCxcbiAgQml0R29CYXNlLFxuICBFRERTQU1ldGhvZHMsXG4gIEVERFNBTWV0aG9kVHlwZXMsXG4gIEVudmlyb25tZW50cyxcbiAgSVRva2VuRW5hYmxlbWVudCxcbiAgS2V5UGFpcixcbiAgTWVtbyxcbiAgTVBDQWxnb3JpdGhtLFxuICBNUENDb25zb2xpZGF0aW9uUmVjb3ZlcnlPcHRpb25zLFxuICBNUENSZWNvdmVyeU9wdGlvbnMsXG4gIE1QQ1N3ZWVwUmVjb3ZlcnlPcHRpb25zLFxuICBNUENTd2VlcFR4cyxcbiAgTVBDVHgsXG4gIE1QQ1R4cyxcbiAgTVBDVW5zaWduZWRUeCxcbiAgTXVsdGlzaWdUeXBlLFxuICBtdWx0aXNpZ1R5cGVzLFxuICBPdmNJbnB1dCxcbiAgT3ZjT3V0cHV0LFxuICBQYXJzZWRUcmFuc2FjdGlvbixcbiAgUG9wdWxhdGVkSW50ZW50LFxuICBQcmVidWlsZFRyYW5zYWN0aW9uV2l0aEludGVudE9wdGlvbnMsXG4gIFByZXNpZ25UcmFuc2FjdGlvbk9wdGlvbnMsXG4gIFB1YmxpY0tleSxcbiAgUmVjb3ZlcnlUeFJlcXVlc3QsXG4gIFNpZ25lZFRyYW5zYWN0aW9uLFxuICBTaWduVHJhbnNhY3Rpb25PcHRpb25zLFxuICBTb2xWZXJzaW9uZWRUcmFuc2FjdGlvbkRhdGEsXG4gIFRva2VuRW5hYmxlbWVudCxcbiAgVG9rZW5FbmFibGVtZW50Q29uZmlnLFxuICBUcmFuc2FjdGlvbkV4cGxhbmF0aW9uLFxuICBUcmFuc2FjdGlvblBhcmFtcyxcbiAgVHJhbnNhY3Rpb25SZWNpcGllbnQsXG4gIFRyYW5zYWN0aW9uVHlwZSxcbiAgVmVyaWZ5VHJhbnNhY3Rpb25PcHRpb25zLFxuICBUc3NWZXJpZnlBZGRyZXNzT3B0aW9ucyxcbiAgdmVyaWZ5RWRkc2FUc3NXYWxsZXRBZGRyZXNzLFxuICBkZXJpdmVNUENXYWxsZXRBZGRyZXNzLFxuICBEZXJpdmVBZGRyZXNzT3B0aW9ucyxcbiAgRGVyaXZlQWRkcmVzc1Jlc3VsdCxcbiAgVW5leHBlY3RlZEFkZHJlc3NFcnJvcixcbiAgZ2V0RWRkc2FTaWduaW5nTWF0ZXJpYWwsXG4gIHNpZ25FZGRzYU1wY1YyUmVjb3ZlcnlUeCxcbn0gZnJvbSAnQGJpdGdvLWJldGEvc2RrLWNvcmUnO1xuaW1wb3J0IHsgYXVkaXRFZGRzYVByaXZhdGVLZXksIGdldERlcml2YXRpb25QYXRoIH0gZnJvbSAnQGJpdGdvLWJldGEvc2RrLWxpYi1tcGMnO1xuaW1wb3J0IHsgQmFzZU5ldHdvcmssIENvaW5GYW1pbHksIGNvaW5zLCBTb2xDb2luLCBCYXNlQ29pbiBhcyBTdGF0aWNzQmFzZUNvaW4gfSBmcm9tICdAYml0Z28tYmV0YS9zdGF0aWNzJztcbmltcG9ydCB7XG4gIEtleVBhaXIgYXMgU29sS2V5UGFpcixcbiAgVHJhbnNhY3Rpb24sXG4gIFRyYW5zYWN0aW9uQnVpbGRlcixcbiAgVHJhbnNhY3Rpb25CdWlsZGVyRmFjdG9yeSxcbiAgZXhwbGFpblNvbFRyYW5zYWN0aW9uLFxufSBmcm9tICcuL2xpYic7XG5pbXBvcnQge1xuICBBdGFDbG9zZSxcbiAgQXRhUmVjb3Zlck5lc3RlZCxcbiAgRXh0cmFBY2NvdW50TWV0YSxcbiAgVHJhbnNhY3Rpb25FeHBsYW5hdGlvbiBhcyBTb2xMaWJUcmFuc2FjdGlvbkV4cGxhbmF0aW9uLFxufSBmcm9tICcuL2xpYi9pZmFjZSc7XG5pbXBvcnQgeyBJbnN0cnVjdGlvbkJ1aWxkZXJUeXBlcyB9IGZyb20gJy4vbGliL2NvbnN0YW50cyc7XG5pbXBvcnQge1xuICBSZXNvbHZlUGVybWlzc2lvbmxlc3NUaGF3UmVzdWx0LFxuICBTb2xBY2NvdW50RmV0Y2hlcixcbiAgYnVpbGRTb2xBY2NvdW50Q29ubmVjdGlvbixcbiAgcmVzb2x2ZVBlcm1pc3Npb25sZXNzVGhhdyBhcyByZXNvbHZlUGVybWlzc2lvbmxlc3NUaGF3TGliLFxuICByZXNvbHZlVHJhbnNmZXJIb29rQWNjb3VudHMgYXMgcmVzb2x2ZVRyYW5zZmVySG9va0FjY291bnRzTGliLFxufSBmcm9tICcuL2xpYi90b2tlbjIwMjJSZXNvbHZlJztcbmltcG9ydCB7XG4gIGdldEFzc29jaWF0ZWRUb2tlbkFjY291bnRBZGRyZXNzLFxuICBnZXRTb2xUb2tlbkZyb21BZGRyZXNzLFxuICBnZXRTb2xUb2tlbkZyb21Ub2tlbk5hbWUsXG4gIGlzVmFsaWRBZGRyZXNzLFxuICBpc1ZhbGlkUHJpdmF0ZUtleSxcbiAgaXNWYWxpZFB1YmxpY0tleSxcbiAgdmFsaWRhdGVSYXdUcmFuc2FjdGlvbixcbn0gZnJvbSAnLi9saWIvdXRpbHMnO1xuXG5leHBvcnQgY29uc3QgREVGQVVMVF9TQ0FOX0ZBQ1RPUiA9IDIwOyAvLyBkZWZhdWx0IG51bWJlciBvZiByZWNlaXZlIGFkZHJlc3NlcyB0byBzY2FuIGZvciBmdW5kc1xuXG5leHBvcnQgaW50ZXJmYWNlIFRyYW5zYWN0aW9uRmVlIHtcbiAgZmVlOiBzdHJpbmc7XG59XG5cbmV4cG9ydCB0eXBlIFNvbFRyYW5zYWN0aW9uRXhwbGFuYXRpb24gPSBUcmFuc2FjdGlvbkV4cGxhbmF0aW9uO1xuXG5leHBvcnQgaW50ZXJmYWNlIEV4cGxhaW5UcmFuc2FjdGlvbk9wdGlvbnMge1xuICB0eEJhc2U2NDogc3RyaW5nO1xuICBmZWVJbmZvOiBUcmFuc2FjdGlvbkZlZTtcbiAgdG9rZW5BY2NvdW50UmVudEV4ZW1wdEFtb3VudD86IHN0cmluZztcbiAgY29pbk5hbWU/OiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgVHhJbmZvIHtcbiAgcmVjaXBpZW50czogVHJhbnNhY3Rpb25SZWNpcGllbnRbXTtcbiAgZnJvbTogc3RyaW5nO1xuICB0eGlkOiBzdHJpbmc7XG59XG5cbi8vIGBSZXNvbHZlUGVybWlzc2lvbmxlc3NUaGF3UmVzdWx0YCBub3cgbGl2ZXMgaW4gYC4vbGliL3Rva2VuMjAyMlJlc29sdmVgOyByZS1leHBvcnRlZCBoZXJlIHRvXG4vLyBwcmVzZXJ2ZSB0aGUgZXhpc3RpbmcgYEBiaXRnby1iZXRhL3Nkay1jb2luLXNvbGAgcHVibGljIGV4cG9ydCBzdXJmYWNlLlxuZXhwb3J0IHR5cGUgeyBSZXNvbHZlUGVybWlzc2lvbmxlc3NUaGF3UmVzdWx0IH07XG5cbmV4cG9ydCBpbnRlcmZhY2UgU29sU2lnblRyYW5zYWN0aW9uT3B0aW9ucyBleHRlbmRzIFNpZ25UcmFuc2FjdGlvbk9wdGlvbnMge1xuICB0eFByZWJ1aWxkOiBUcmFuc2FjdGlvblByZWJ1aWxkO1xuICBwcnY6IHN0cmluZyB8IHN0cmluZ1tdO1xuICBwdWJLZXlzPzogc3RyaW5nW107XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgVHJhbnNhY3Rpb25QcmVidWlsZCBleHRlbmRzIEJhc2VUcmFuc2FjdGlvblByZWJ1aWxkIHtcbiAgdHhCYXNlNjQ6IHN0cmluZztcbiAgdHhJbmZvOiBUeEluZm87XG4gIHNvdXJjZTogc3RyaW5nO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFNvbFZlcmlmeVRyYW5zYWN0aW9uT3B0aW9ucyBleHRlbmRzIFZlcmlmeVRyYW5zYWN0aW9uT3B0aW9ucyB7XG4gIG1lbW8/OiBNZW1vO1xuICBmZWVQYXllcjogc3RyaW5nO1xuICBibG9ja2hhc2g6IHN0cmluZztcbiAgZHVyYWJsZU5vbmNlPzogeyB3YWxsZXROb25jZUFkZHJlc3M6IHN0cmluZzsgYXV0aFdhbGxldEFkZHJlc3M6IG51bWJlciB9O1xufVxuXG5pbnRlcmZhY2UgVHJhbnNhY3Rpb25PdXRwdXQge1xuICBhZGRyZXNzOiBzdHJpbmc7XG4gIGFtb3VudDogbnVtYmVyIHwgc3RyaW5nO1xuICB0b2tlbk5hbWU/OiBzdHJpbmc7XG59XG5cbnR5cGUgVHJhbnNhY3Rpb25JbnB1dCA9IFRyYW5zYWN0aW9uT3V0cHV0O1xuXG5leHBvcnQgaW50ZXJmYWNlIFNvbFBhcnNlZFRyYW5zYWN0aW9uIGV4dGVuZHMgUGFyc2VkVHJhbnNhY3Rpb24ge1xuICAvLyB0b3RhbCBhc3NldHMgYmVpbmcgbW92ZWQsIGluY2x1ZGluZyBmZWVzXG4gIGlucHV0czogVHJhbnNhY3Rpb25JbnB1dFtdO1xuXG4gIC8vIHdoZXJlIGFzc2V0cyBhcmUgbW92ZWQgdG9cbiAgb3V0cHV0czogVHJhbnNhY3Rpb25PdXRwdXRbXTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBTb2xQYXJzZVRyYW5zYWN0aW9uT3B0aW9ucyBleHRlbmRzIEJhc2VQYXJzZVRyYW5zYWN0aW9uT3B0aW9ucyB7XG4gIHR4QmFzZTY0OiBzdHJpbmc7XG4gIGZlZUluZm86IFRyYW5zYWN0aW9uRmVlO1xuICB0b2tlbkFjY291bnRSZW50RXhlbXB0QW1vdW50Pzogc3RyaW5nO1xufVxuXG5pbnRlcmZhY2UgU29sRHVyYWJsZU5vbmNlRnJvbU5vZGUge1xuICBhdXRob3JpdHk6IHN0cmluZztcbiAgYmxvY2toYXNoOiBzdHJpbmc7XG59XG5cbmludGVyZmFjZSBUb2tlbkFtb3VudCB7XG4gIGFtb3VudDogc3RyaW5nO1xuICBkZWNpbWFsczogbnVtYmVyO1xuICB1aUFtb3VudDogbnVtYmVyO1xuICB1aUFtb3VudFN0cmluZzogc3RyaW5nO1xufVxuXG5pbnRlcmZhY2UgVG9rZW5BY2NvdW50SW5mbyB7XG4gIGlzTmF0aXZlOiBib29sZWFuO1xuICBtaW50OiBzdHJpbmc7XG4gIG93bmVyOiBzdHJpbmc7XG4gIHN0YXRlOiBzdHJpbmc7XG4gIHRva2VuQW1vdW50OiBUb2tlbkFtb3VudDtcbn1cblxuaW50ZXJmYWNlIFRva2VuQWNjb3VudCB7XG4gIGluZm86IFRva2VuQWNjb3VudEluZm87XG4gIHB1YktleTogc3RyaW5nO1xuICB0b2tlbk5hbWU/OiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgU29sUmVjb3ZlcnlPcHRpb25zIGV4dGVuZHMgTVBDUmVjb3ZlcnlPcHRpb25zIHtcbiAgZHVyYWJsZU5vbmNlPzoge1xuICAgIHB1YmxpY0tleTogc3RyaW5nO1xuICAgIHNlY3JldEtleTogc3RyaW5nO1xuICB9O1xuICB0b2tlbkNvbnRyYWN0QWRkcmVzcz86IHN0cmluZztcbiAgY2xvc2VBdGFBZGRyZXNzPzogc3RyaW5nO1xuICAvLyBkZXN0aW5hdGlvbiBhZGRyZXNzIHdoZXJlIHRva2VuIHNob3VsZCBiZSBzZW50IGJlZm9yZSBjbG9zaW5nIHRoZSBBVEEgYWRkcmVzc1xuICByZWNvdmVyeURlc3RpbmF0aW9uQXRhQWRkcmVzcz86IHN0cmluZztcbiAgLy8gbmVzdGVkIEFUQSBhZGRyZXNzIChBVEEgd2hvc2Ugb3duZXIgaXMgYW5vdGhlciBBVEEpIHRvIHJlY292ZXIgdG9rZW5zIGZyb21cbiAgbmVzdGVkQXRhQWRkcmVzcz86IHN0cmluZztcbiAgLy8gdGhlIEFUQSB0aGF0IG93bnMgdGhlIG5lc3RlZCBBVEEgKGFuZCB3aGVyZSByZWNvdmVyZWQgdG9rZW5zIHdpbGwgYmUgc2VudClcbiAgb3duZXJBdGFBZGRyZXNzPzogc3RyaW5nO1xuICAvLyB0aGUgdG9rZW4gbWludCBhZGRyZXNzIGZvciBib3RoIEFUQXMgKHJlcXVpcmVkIHdoZW4gcmVjb3ZlcmluZyBmcm9tIG5lc3RlZCBBVEEpXG4gIHRva2VuTWludEFkZHJlc3M/OiBzdHJpbmc7XG4gIHByb2dyYW1JZD86IHN0cmluZzsgLy8gcHJvZ3JhbUlkIG9mIHRoZSB0b2tlblxuICBhcGlLZXk/OiBzdHJpbmc7IC8vIEFQSSBrZXkgZm9yIG5vZGUgcmVxdWVzdHNcbiAgLy8gUHJlLXJlc29sdmVkIHNpZ25pbmcgcm91dGU7IHdoZW4gc2V0LCBza2lwcyBwZXItY2FsbCBrZXljYXJkIGRlY3J5cHRpb24gaW4gcmVjb3ZlcigpLlxuICBtdWx0aXNpZ1R5cGVWZXJzaW9uPzogJ01QQ3YyJztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBTb2xDb25zb2xpZGF0aW9uUmVjb3ZlcnlPcHRpb25zIGV4dGVuZHMgTVBDQ29uc29saWRhdGlvblJlY292ZXJ5T3B0aW9ucyB7XG4gIGR1cmFibGVOb25jZXM6IHtcbiAgICBwdWJsaWNLZXlzOiBzdHJpbmdbXTtcbiAgICBzZWNyZXRLZXk6IHN0cmluZztcbiAgfTtcbiAgdG9rZW5Db250cmFjdEFkZHJlc3M/OiBzdHJpbmc7XG4gIGFwaUtleT86IHN0cmluZzsgLy8gQVBJIGtleSBmb3Igbm9kZSByZXF1ZXN0c1xuICBwcm9ncmFtSWQ/OiBzdHJpbmc7IC8vIHByb2dyYW1JZCBvZiB0aGUgdG9rZW5cbn1cblxuY29uc3QgSEVYX1JFR0VYID0gL15bMC05YS1mQS1GXSskLztcbmNvbnN0IEJMSU5EX1NJR05JTkdfVFhfVFlQRVNfVE9fQ0hFQ0sgPSB7IGVuYWJsZXRva2VuOiAnQXNzb2NpYXRlZFRva2VuQWNjb3VudEluaXRpYWxpemF0aW9uJyB9O1xuXG4vKipcbiAqIEdldCBhbW91bnQgc3RyaW5nIGNvcnJlY3RlZCBmb3IgYXJjaGl0ZWN0dXJlLXNwZWNpZmljIGVuZGlhbm5lc3MgaXNzdWVzLlxuICpcbiAqIE9uIHMzOTB4IChiaWctZW5kaWFuKSBhcmNoaXRlY3R1cmUsIHRoZSBTb2xhbmEgdHJhbnNhY3Rpb24gcGFyc2VyICh2aWEgQHNvbGFuYS93ZWIzLmpzKVxuICogaW5jb3JyZWN0bHkgcmVhZHMgbGl0dGxlLWVuZGlhbiB1NjQgYW1vdW50cyBhcyBiaWctZW5kaWFuLCByZXN1bHRpbmcgaW4gY29ycnVwdGVkIHZhbHVlcy5cbiAqXG4gKiBUaGlzIGZ1bmN0aW9uIGNvcnJlY3RzIGFsbCBhbW91bnRzIG9uIHMzOTB4IGJ5IHN3YXBwaW5nIGJ5dGUgb3JkZXIgdG8gdW5kb1xuICogdGhlIGluY29ycmVjdCBieXRlIG9yZGVyIHRoYXQgaGFwcGVuZWQgZHVyaW5nIHRyYW5zYWN0aW9uIHBhcnNpbmcuXG4gKlxuICogQHBhcmFtIGFtb3VudCAtIFRoZSBhbW91bnQgdG8gY2hlY2sgYW5kIHBvdGVudGlhbGx5IGZpeFxuICogQHJldHVybnMgVGhlIGNvcnJlY3RlZCBhbW91bnQgYXMgYSBzdHJpbmdcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldEFtb3VudEJhc2VkT25FbmRpYW5uZXNzKGFtb3VudDogc3RyaW5nIHwgbnVtYmVyKTogc3RyaW5nIHtcbiAgY29uc3QgYW1vdW50U3RyID0gU3RyaW5nKGFtb3VudCk7XG5cbiAgLy8gT25seSBzMzkweCBhcmNoaXRlY3R1cmUgaGFzIHRoaXMgZW5kaWFubmVzcyBpc3N1ZVxuICBjb25zdCBpc1MzOTB4ID0gcHJvY2Vzcy5hcmNoID09PSAnczM5MHgnO1xuICBpZiAoIWlzUzM5MHgpIHtcbiAgICByZXR1cm4gYW1vdW50U3RyO1xuICB9XG5cbiAgdHJ5IHtcbiAgICBjb25zdCBhbW91bnRCTiA9IEJpZ0ludChhbW91bnRTdHIpO1xuICAgIC8vIE9uIHMzOTB4LCB0aGUgcGFyc2VyIEFMV0FZUyByZWFkcyB1NjQgYXMgYmlnLWVuZGlhbiB3aGVuIGl0J3MgYWN0dWFsbHkgbGl0dGxlLWVuZGlhblxuICAgIC8vIFNvIHdlIEFMV0FZUyBuZWVkIHRvIHN3YXAgYnl0ZXMgdG8gZ2V0IHRoZSBjb3JyZWN0IHZhbHVlXG4gICAgY29uc3QgYnVmID0gQnVmZmVyLmFsbG9jKDgpO1xuICAgIGJ1Zi53cml0ZUJpZ1VJbnQ2NEJFKGFtb3VudEJOLCAwKTtcbiAgICBjb25zdCBmaXhlZCA9IGJ1Zi5yZWFkQmlnVUludDY0TEUoMCk7XG4gICAgcmV0dXJuIGZpeGVkLnRvU3RyaW5nKCk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICAvLyBJZiBjb252ZXJzaW9uIGZhaWxzLCByZXR1cm4gb3JpZ2luYWwgdmFsdWVcbiAgICByZXR1cm4gYW1vdW50U3RyO1xuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBTb2wgZXh0ZW5kcyBCYXNlQ29pbiB7XG4gIHByb3RlY3RlZCByZWFkb25seSBfc3RhdGljc0NvaW46IFJlYWRvbmx5PFN0YXRpY3NCYXNlQ29pbj47XG5cbiAgY29uc3RydWN0b3IoYml0Z286IEJpdEdvQmFzZSwgc3RhdGljc0NvaW4/OiBSZWFkb25seTxTdGF0aWNzQmFzZUNvaW4+KSB7XG4gICAgc3VwZXIoYml0Z28pO1xuXG4gICAgaWYgKCFzdGF0aWNzQ29pbikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdtaXNzaW5nIHJlcXVpcmVkIGNvbnN0cnVjdG9yIHBhcmFtZXRlciBzdGF0aWNzQ29pbicpO1xuICAgIH1cblxuICAgIHRoaXMuX3N0YXRpY3NDb2luID0gc3RhdGljc0NvaW47XG4gIH1cblxuICBzdGF0aWMgY3JlYXRlSW5zdGFuY2UoYml0Z286IEJpdEdvQmFzZSwgc3RhdGljc0NvaW4/OiBSZWFkb25seTxTdGF0aWNzQmFzZUNvaW4+KTogQmFzZUNvaW4ge1xuICAgIHJldHVybiBuZXcgU29sKGJpdGdvLCBzdGF0aWNzQ29pbik7XG4gIH1cblxuICBhbGxvd3NBY2NvdW50Q29uc29saWRhdGlvbnMoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICBzdXBwb3J0c1RzcygpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIC8qKiBAaW5oZXJpdERvYyAqL1xuICBzdXBwb3J0c01lc3NhZ2VTaWduaW5nKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgLyoqIGluaGVyaXRlZCBkb2MgKi9cbiAgZ2V0RGVmYXVsdE11bHRpc2lnVHlwZSgpOiBNdWx0aXNpZ1R5cGUge1xuICAgIHJldHVybiBtdWx0aXNpZ1R5cGVzLnRzcztcbiAgfVxuXG4gIGdldE1QQ0FsZ29yaXRobSgpOiBNUENBbGdvcml0aG0ge1xuICAgIHJldHVybiAnZWRkc2EnO1xuICB9XG5cbiAgZ2V0Q2hhaW4oKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5fc3RhdGljc0NvaW4ubmFtZTtcbiAgfVxuXG4gIGdldEZhbWlseSgpOiBDb2luRmFtaWx5IHtcbiAgICByZXR1cm4gdGhpcy5fc3RhdGljc0NvaW4uZmFtaWx5O1xuICB9XG5cbiAgZ2V0RnVsbE5hbWUoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5fc3RhdGljc0NvaW4uZnVsbE5hbWU7XG4gIH1cblxuICBnZXROZXR3b3JrKCk6IEJhc2VOZXR3b3JrIHtcbiAgICByZXR1cm4gdGhpcy5fc3RhdGljc0NvaW4ubmV0d29yaztcbiAgfVxuXG4gIGdldEJhc2VGYWN0b3IoKTogc3RyaW5nIHwgbnVtYmVyIHtcbiAgICByZXR1cm4gTWF0aC5wb3coMTAsIHRoaXMuX3N0YXRpY3NDb2luLmRlY2ltYWxQbGFjZXMpO1xuICB9XG5cbiAgdmVyaWZ5VHhUeXBlKGV4cGVjdGVkVHlwZUZyb21Vc2VyUGFyYW1zOiBzdHJpbmcsIGFjdHVhbFR5cGVGcm9tRGVjb2RlZDogc3RyaW5nIHwgdW5kZWZpbmVkKTogdm9pZCB7XG4gICAgY29uc3QgbWF0Y2hGcm9tVXNlclRvRGVjb2RlZFR5cGUgPSBCTElORF9TSUdOSU5HX1RYX1RZUEVTX1RPX0NIRUNLW2V4cGVjdGVkVHlwZUZyb21Vc2VyUGFyYW1zXTtcbiAgICBpZiAobWF0Y2hGcm9tVXNlclRvRGVjb2RlZFR5cGUgIT09IGFjdHVhbFR5cGVGcm9tRGVjb2RlZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgSW52YWxpZCB0cmFuc2FjdGlvbiB0eXBlIG9uIHRva2VuIGVuYWJsZW1lbnQ6IGV4cGVjdGVkIFwiJHttYXRjaEZyb21Vc2VyVG9EZWNvZGVkVHlwZX1cIiwgZ290IFwiJHthY3R1YWxUeXBlRnJvbURlY29kZWR9XCIuYFxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICB0aHJvd0lmTWlzc2luZ1Rva2VuRW5hYmxlbWVudHNPclJldHVybihleHBsYW5hdGlvbjogVHJhbnNhY3Rpb25FeHBsYW5hdGlvbik6IElUb2tlbkVuYWJsZW1lbnRbXSB7XG4gICAgaWYgKCFleHBsYW5hdGlvbi50b2tlbkVuYWJsZW1lbnRzIHx8IGV4cGxhbmF0aW9uLnRva2VuRW5hYmxlbWVudHMubGVuZ3RoID09PSAwKVxuICAgICAgdGhyb3cgbmV3IEVycm9yKCdNaXNzaW5nIHR4IHRva2VuIGVuYWJsZW1lbnRzIGRhdGEgb24gdG9rZW4gZW5hYmxlbWVudCB0eCBwcmVidWlsZCcpO1xuICAgIHJldHVybiBleHBsYW5hdGlvbi50b2tlbkVuYWJsZW1lbnRzO1xuICB9XG5cbiAgdGhyb3dJZk1pc3NpbmdFbmFibGVUb2tlbkNvbmZpZ09yUmV0dXJuKHR4UGFyYW1zOiBUcmFuc2FjdGlvblBhcmFtcyk6IFRva2VuRW5hYmxlbWVudFtdIHtcbiAgICBpZiAoIXR4UGFyYW1zLmVuYWJsZVRva2VucyB8fCB0eFBhcmFtcy5lbmFibGVUb2tlbnMubGVuZ3RoID09PSAwKSB0aHJvdyBuZXcgRXJyb3IoJ01pc3NpbmcgZW5hYmxlIHRva2VuIGNvbmZpZycpO1xuICAgIHJldHVybiB0eFBhcmFtcy5lbmFibGVUb2tlbnM7XG4gIH1cblxuICB2ZXJpZnlUb2tlbk5hbWUodG9rZW5FbmFibGVtZW50c1ByZWJ1aWxkOiBJVG9rZW5FbmFibGVtZW50W10sIGVuYWJsZVRva2Vuc0NvbmZpZzogVG9rZW5FbmFibGVtZW50W10pOiB2b2lkIHtcbiAgICBlbmFibGVUb2tlbnNDb25maWcuZm9yRWFjaCgoZW5hYmxlVG9rZW5Db25maWcpID0+IHtcbiAgICAgIGNvbnN0IGV4cGVjdGVkVG9rZW5OYW1lID0gZW5hYmxlVG9rZW5Db25maWcubmFtZTtcbiAgICAgIHRva2VuRW5hYmxlbWVudHNQcmVidWlsZC5mb3JFYWNoKCh0b2tlbkVuYWJsZW1lbnQpID0+IHtcbiAgICAgICAgaWYgKCF0b2tlbkVuYWJsZW1lbnQudG9rZW5OYW1lKSB0aHJvdyBuZXcgRXJyb3IoJ01pc3NpbmcgdG9rZW4gbmFtZSBvbiB0b2tlbiBlbmFibGVtZW50IHR4Jyk7XG4gICAgICAgIGlmICh0b2tlbkVuYWJsZW1lbnQudG9rZW5OYW1lICE9PSBleHBlY3RlZFRva2VuTmFtZSlcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgICBgSW52YWxpZCB0b2tlbiBuYW1lOiBleHBlY3RlZCAke2V4cGVjdGVkVG9rZW5OYW1lfSwgZ290ICR7dG9rZW5FbmFibGVtZW50LnRva2VuTmFtZX0gb24gdG9rZW4gZW5hYmxlbWVudCB0eGBcbiAgICAgICAgICApO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICBhc3luYyB2ZXJpZnlUb2tlbkFkZHJlc3MoXG4gICAgdG9rZW5FbmFibGVtZW50c1ByZWJ1aWxkOiBJVG9rZW5FbmFibGVtZW50W10sXG4gICAgZW5hYmxlVG9rZW5zQ29uZmlnOiBUb2tlbkVuYWJsZW1lbnRbXVxuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBmb3IgKGNvbnN0IGVuYWJsZVRva2VuQ29uZmlnIG9mIGVuYWJsZVRva2Vuc0NvbmZpZykge1xuICAgICAgY29uc3QgZXhwZWN0ZWRUb2tlbkFkZHJlc3MgPSBlbmFibGVUb2tlbkNvbmZpZy5hZGRyZXNzO1xuICAgICAgY29uc3QgZXhwZWN0ZWRUb2tlbk5hbWUgPSBlbmFibGVUb2tlbkNvbmZpZy5uYW1lO1xuXG4gICAgICBpZiAoIWV4cGVjdGVkVG9rZW5BZGRyZXNzKSB0aHJvdyBuZXcgRXJyb3IoJ01pc3NpbmcgdG9rZW4gYWRkcmVzcyBvbiB0b2tlbiBlbmFibGVtZW50IHR4Jyk7XG4gICAgICBpZiAoIWV4cGVjdGVkVG9rZW5OYW1lKSB0aHJvdyBuZXcgRXJyb3IoJ01pc3NpbmcgdG9rZW4gbmFtZSBvbiB0b2tlbiBlbmFibGVtZW50IHR4Jyk7XG5cbiAgICAgIGZvciAoY29uc3QgdG9rZW5FbmFibGVtZW50IG9mIHRva2VuRW5hYmxlbWVudHNQcmVidWlsZCkge1xuICAgICAgICBsZXQgdG9rZW5NaW50QWRkcmVzczogUmVhZG9ubHk8U29sQ29pbj4gfCB1bmRlZmluZWQ7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgdG9rZW5NaW50QWRkcmVzcyA9IGdldFNvbFRva2VuRnJvbVRva2VuTmFtZShleHBlY3RlZFRva2VuTmFtZSk7XG4gICAgICAgIH0gY2F0Y2gge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgVW5hYmxlIHRvIGRlcml2ZSBBVEEgZm9yIHRva2VuIGFkZHJlc3M6ICR7ZXhwZWN0ZWRUb2tlbkFkZHJlc3N9YCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKFxuICAgICAgICAgICF0b2tlbk1pbnRBZGRyZXNzIHx8XG4gICAgICAgICAgdG9rZW5NaW50QWRkcmVzcy50b2tlbkFkZHJlc3MgPT09IHVuZGVmaW5lZCB8fFxuICAgICAgICAgIHRva2VuTWludEFkZHJlc3MucHJvZ3JhbUlkID09PSB1bmRlZmluZWRcbiAgICAgICAgKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbmFibGUgdG8gZ2V0IHRva2VuIG1pbnQgYWRkcmVzcyBmb3IgJHtleHBlY3RlZFRva2VuTmFtZX1gKTtcbiAgICAgICAgfVxuICAgICAgICBsZXQgYXRhOiBzdHJpbmc7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgYXRhID0gYXdhaXQgZ2V0QXNzb2NpYXRlZFRva2VuQWNjb3VudEFkZHJlc3MoXG4gICAgICAgICAgICB0b2tlbk1pbnRBZGRyZXNzLnRva2VuQWRkcmVzcyxcbiAgICAgICAgICAgIGV4cGVjdGVkVG9rZW5BZGRyZXNzLFxuICAgICAgICAgICAgdHJ1ZSxcbiAgICAgICAgICAgIHRva2VuTWludEFkZHJlc3MucHJvZ3JhbUlkXG4gICAgICAgICAgKTtcbiAgICAgICAgfSBjYXRjaCB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbmFibGUgdG8gZGVyaXZlIEFUQSBmb3IgdG9rZW4gYWRkcmVzczogJHtleHBlY3RlZFRva2VuQWRkcmVzc31gKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoYXRhICE9PSB0b2tlbkVuYWJsZW1lbnQuYWRkcmVzcykge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAgIGBJbnZhbGlkIHRva2VuIGFkZHJlc3M6IGV4cGVjdGVkICR7YXRhfSwgZ290ICR7dG9rZW5FbmFibGVtZW50LmFkZHJlc3N9IG9uIHRva2VuIGVuYWJsZW1lbnQgdHhgXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBGb3IgdHJhbnNhY3Rpb25zIHR5cGVkIGFzIGBDbG9zZUFzc29jaWF0ZWRUb2tlbkFjY291bnRgIChpbmNsdWRlcyBTUEwgY2xvc2UtYWNjb3VudCBhbmRcbiAgICogcmVjb3Zlci1uZXN0ZWQgZmxvd3MpLCBlbmZvcmNlIHRoYXQgcmVudCAvIGF1dGhvcml0eSBhbGlnbnMgd2l0aCB0aGUgd2FsbGV0IHJvb3Qgd2hlbiBrbm93bi5cbiAgICpcbiAgICogTm8tb3Agd2hlbiBgd2FsbGV0Um9vdEFkZHJlc3NgIGlzIG5vdCBwcm92aWRlZCAoZS5nLiB1bmluaXRpYWxpemVkIHdhbGxldHMpLlxuICAgKi9cbiAgcHJpdmF0ZSB2ZXJpZnlDbG9zZUFzc29jaWF0ZWRUb2tlbkFjY291bnRGYW1pbHlSb290cyhcbiAgICB0cmFuc2FjdGlvbjogVHJhbnNhY3Rpb24sXG4gICAgd2FsbGV0Um9vdEFkZHJlc3M6IHN0cmluZyB8IHVuZGVmaW5lZFxuICApOiB2b2lkIHtcbiAgICBpZiAoIXdhbGxldFJvb3RBZGRyZXNzKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgdHhKc29uID0gdHJhbnNhY3Rpb24udG9Kc29uKCk7XG5cbiAgICBmb3IgKGNvbnN0IGluc3RydWN0aW9uIG9mIHR4SnNvbi5pbnN0cnVjdGlvbnNEYXRhKSB7XG4gICAgICBpZiAoaW5zdHJ1Y3Rpb24udHlwZSA9PT0gSW5zdHJ1Y3Rpb25CdWlsZGVyVHlwZXMuQ2xvc2VBc3NvY2lhdGVkVG9rZW5BY2NvdW50KSB7XG4gICAgICAgIGNvbnN0IGNsb3NlSW5zdHJ1Y3Rpb24gPSBpbnN0cnVjdGlvbiBhcyBBdGFDbG9zZTtcbiAgICAgICAgaWYgKGNsb3NlSW5zdHJ1Y3Rpb24ucGFyYW1zLmRlc3RpbmF0aW9uQWRkcmVzcyAhPT0gd2FsbGV0Um9vdEFkZHJlc3MpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgICBgQ2xvc2UgQVRBIGRlc3RpbmF0aW9uIG11c3QgYmUgd2FsbGV0IHJvb3QgYWRkcmVzcy4gRXhwZWN0ZWQgJHt3YWxsZXRSb290QWRkcmVzc30sIGdvdCAke2Nsb3NlSW5zdHJ1Y3Rpb24ucGFyYW1zLmRlc3RpbmF0aW9uQWRkcmVzc31gXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmIChpbnN0cnVjdGlvbi50eXBlID09PSBJbnN0cnVjdGlvbkJ1aWxkZXJUeXBlcy5SZWNvdmVyTmVzdGVkQXNzb2NpYXRlZFRva2VuQWNjb3VudCkge1xuICAgICAgICBjb25zdCByZWNvdmVyTmVzdGVkSW5zdHJ1Y3Rpb24gPSBpbnN0cnVjdGlvbiBhcyBBdGFSZWNvdmVyTmVzdGVkO1xuICAgICAgICBpZiAocmVjb3Zlck5lc3RlZEluc3RydWN0aW9uLnBhcmFtcy53YWxsZXRBZGRyZXNzICE9PSB3YWxsZXRSb290QWRkcmVzcykge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAgIGBSZWNvdmVyIG5lc3RlZCB3YWxsZXQgYWRkcmVzcyBtdXN0IGJlIHdhbGxldCByb290IGFkZHJlc3MuIEV4cGVjdGVkICR7d2FsbGV0Um9vdEFkZHJlc3N9LCBnb3QgJHtyZWNvdmVyTmVzdGVkSW5zdHJ1Y3Rpb24ucGFyYW1zLndhbGxldEFkZHJlc3N9YFxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogV2hlbiB0aGUgY2FsbGVyIHN1cHBsaWVzIGByZWNpcGllbnRzYCBmb3IgYSBjbG9zZS1BVEEgcHJlYnVpbGQsIHJlcXVpcmUgdGhleSBtYXRjaCB0aGVcbiAgICogb24tY2hhaW4gQVRBIGFjY291bnRzIGJlaW5nIGNsb3NlZCAob3JkZXItaW5kZXBlbmRlbnQpIGFuZCBjYXJyeSB6ZXJvIGFtb3VudCAoaW50ZW50LW9ubHkpLlxuICAgKiBSZWNvdmVyLW5lc3RlZC1vbmx5IHR4cyBoYXZlIG5vIGNsb3NlIGluc3RydWN0aW9uczsgdGhpcyBpcyBhIG5vLW9wIGluIHRoYXQgY2FzZS5cbiAgICovXG4gIHByaXZhdGUgdmVyaWZ5Q2xvc2VBdGFSZWNpcGllbnRzTWF0Y2hDbG9zZUluc3RydWN0aW9ucyhcbiAgICB0cmFuc2FjdGlvbjogVHJhbnNhY3Rpb24sXG4gICAgcmVjaXBpZW50czogVHJhbnNhY3Rpb25SZWNpcGllbnRbXVxuICApOiB2b2lkIHtcbiAgICBjb25zdCB0eEpzb24gPSB0cmFuc2FjdGlvbi50b0pzb24oKTtcbiAgICBjb25zdCBjbG9zZUF0YUFjY291bnRBZGRyZXNzZXMgPSB0eEpzb24uaW5zdHJ1Y3Rpb25zRGF0YVxuICAgICAgLmZpbHRlcigoaW5zdCkgPT4gaW5zdC50eXBlID09PSBJbnN0cnVjdGlvbkJ1aWxkZXJUeXBlcy5DbG9zZUFzc29jaWF0ZWRUb2tlbkFjY291bnQpXG4gICAgICAubWFwKChpbnN0KSA9PiAoaW5zdCBhcyBBdGFDbG9zZSkucGFyYW1zLmFjY291bnRBZGRyZXNzKTtcblxuICAgIGlmIChjbG9zZUF0YUFjY291bnRBZGRyZXNzZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgZm9yIChjb25zdCByZWNpcGllbnQgb2YgcmVjaXBpZW50cykge1xuICAgICAgaWYgKHJlY2lwaWVudC50b2tlbk5hbWUpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdDbG9zZSBBVEEgcmVjaXBpZW50cyBtdXN0IG5vdCBzcGVjaWZ5IHRva2VuTmFtZScpO1xuICAgICAgfVxuICAgICAgaWYgKCFuZXcgQmlnTnVtYmVyKFN0cmluZyhyZWNpcGllbnQuYW1vdW50ID8/ICcwJykpLmlzWmVybygpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignQ2xvc2UgQVRBIHJlY2lwaWVudHMgbXVzdCBoYXZlIHplcm8gYW1vdW50Jyk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3Qgc29ydGVkUmVjaXBpZW50cyA9IFsuLi5yZWNpcGllbnRzLm1hcCgocikgPT4gci5hZGRyZXNzKV0uc29ydCgpO1xuICAgIGNvbnN0IHNvcnRlZENsb3NlcyA9IFsuLi5jbG9zZUF0YUFjY291bnRBZGRyZXNzZXNdLnNvcnQoKTtcbiAgICBpZiAoIV8uaXNFcXVhbChzb3J0ZWRSZWNpcGllbnRzLCBzb3J0ZWRDbG9zZXMpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICdDbG9zZSBBVEEgdHhQYXJhbXMucmVjaXBpZW50cyBhZGRyZXNzZXMgbXVzdCBtYXRjaCB0aGUgQVRBIGFjY291bnQgYWRkcmVzc2VzIGluIHRoZSB0cmFuc2FjdGlvbiBpbnN0cnVjdGlvbnMnXG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgaGFzU29sVmVyc2lvbmVkVHJhbnNhY3Rpb25EYXRhKFxuICAgIHR4UGFyYW1zOiBUcmFuc2FjdGlvblBhcmFtc1xuICApOiB0eFBhcmFtcyBpcyBUcmFuc2FjdGlvblBhcmFtcyAmIHsgc29sVmVyc2lvbmVkVHJhbnNhY3Rpb25EYXRhOiBTb2xWZXJzaW9uZWRUcmFuc2FjdGlvbkRhdGEgfSB7XG4gICAgcmV0dXJuICdzb2xWZXJzaW9uZWRUcmFuc2FjdGlvbkRhdGEnIGluIHR4UGFyYW1zICYmIHR4UGFyYW1zLnNvbFZlcnNpb25lZFRyYW5zYWN0aW9uRGF0YSAhPT0gdW5kZWZpbmVkO1xuICB9XG5cbiAgLyoqXG4gICAqIFZlcmlmeSBhIHZlcnNpb25lZCBTb2xhbmEgdHJhbnNhY3Rpb24gd2l0aCBiYXNpYyBzdHJ1Y3R1cmFsIHZhbGlkYXRpb25cbiAgICogQHBhcmFtIHBhcmFtcyAtIHZlcmlmaWNhdGlvbiBwYXJhbWV0ZXJzXG4gICAqIEByZXR1cm5zIHRydWUgaWYgdmVyaWZpY2F0aW9uIHBhc3Nlc1xuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyB2ZXJpZnlWZXJzaW9uZWRUcmFuc2FjdGlvbihwYXJhbXM6IFNvbFZlcmlmeVRyYW5zYWN0aW9uT3B0aW9ucyk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIGNvbnN0IHsgdHhQYXJhbXMsIHR4UHJlYnVpbGQgfSA9IHBhcmFtcztcbiAgICBjb25zdCByYXdUeCA9IHR4UHJlYnVpbGQudHhCYXNlNjQgfHwgdHhQcmVidWlsZC50eEhleDtcblxuICAgIGlmICghcmF3VHgpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignbWlzc2luZyByZXF1aXJlZCB0eCBwcmVidWlsZCBwcm9wZXJ0eSB0eEJhc2U2NCBvciB0eEhleCcpO1xuICAgIH1cblxuICAgIC8vIFZhbGlkYXRlIHRoYXQgdGhlIHZlcnNpb25lZCB0cmFuc2FjdGlvbiBkYXRhIGlzIHdlbGwtZm9ybWVkXG4gICAgaWYgKCF0aGlzLmhhc1NvbFZlcnNpb25lZFRyYW5zYWN0aW9uRGF0YSh0eFBhcmFtcykpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignc29sVmVyc2lvbmVkVHJhbnNhY3Rpb25EYXRhIGlzIHJlcXVpcmVkIGZvciB2ZXJzaW9uZWQgdHJhbnNhY3Rpb24gdmVyaWZpY2F0aW9uJyk7XG4gICAgfVxuXG4gICAgY29uc3QgdmVyc2lvbmVkRGF0YSA9IHR4UGFyYW1zLnNvbFZlcnNpb25lZFRyYW5zYWN0aW9uRGF0YTtcblxuICAgIGlmICghdmVyc2lvbmVkRGF0YS52ZXJzaW9uZWRJbnN0cnVjdGlvbnMgfHwgdmVyc2lvbmVkRGF0YS52ZXJzaW9uZWRJbnN0cnVjdGlvbnMubGVuZ3RoID09PSAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ3ZlcnNpb25lZCB0cmFuc2FjdGlvbiBtdXN0IGhhdmUgYXQgbGVhc3Qgb25lIGluc3RydWN0aW9uJyk7XG4gICAgfVxuXG4gICAgaWYgKCF2ZXJzaW9uZWREYXRhLnN0YXRpY0FjY291bnRLZXlzIHx8IHZlcnNpb25lZERhdGEuc3RhdGljQWNjb3VudEtleXMubGVuZ3RoID09PSAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ3ZlcnNpb25lZCB0cmFuc2FjdGlvbiBtdXN0IGhhdmUgYXQgbGVhc3Qgb25lIHN0YXRpYyBhY2NvdW50IGtleScpO1xuICAgIH1cblxuICAgIGlmICghdmVyc2lvbmVkRGF0YS5tZXNzYWdlSGVhZGVyKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ3ZlcnNpb25lZCB0cmFuc2FjdGlvbiBtdXN0IGhhdmUgYSBtZXNzYWdlIGhlYWRlcicpO1xuICAgIH1cblxuICAgIC8vIFZhbGlkYXRlIHRoYXQgd2UgY2FuIGRlc2VyaWFsaXplIHRoZSB0cmFuc2FjdGlvblxuICAgIGxldCByYXdUeEJhc2U2NCA9IHJhd1R4O1xuICAgIGlmIChIRVhfUkVHRVgudGVzdChyYXdUeCkpIHtcbiAgICAgIHJhd1R4QmFzZTY0ID0gQnVmZmVyLmZyb20ocmF3VHgsICdoZXgnKS50b1N0cmluZygnYmFzZTY0Jyk7XG4gICAgfVxuXG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHR4Qnl0ZXMgPSBCdWZmZXIuZnJvbShyYXdUeEJhc2U2NCwgJ2Jhc2U2NCcpO1xuICAgICAgaWYgKHR4Qnl0ZXMubGVuZ3RoIDwgMSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ3RyYW5zYWN0aW9uIGJ5dGVzIGFyZSBlbXB0eScpO1xuICAgICAgfVxuXG4gICAgICAvLyBDaGVjayB2ZXJzaW9uIGJ5dGUgKGFmdGVyIHNpZ25hdHVyZXMpXG4gICAgICBjb25zdCBudW1TaWduYXR1cmVzID0gdHhCeXRlc1swXTtcbiAgICAgIGNvbnN0IHNpZ25hdHVyZVNpemUgPSA2NDtcbiAgICAgIGNvbnN0IHZlcnNpb25CeXRlT2Zmc2V0ID0gMSArIG51bVNpZ25hdHVyZXMgKiBzaWduYXR1cmVTaXplO1xuXG4gICAgICBpZiAodHhCeXRlcy5sZW5ndGggPD0gdmVyc2lvbkJ5dGVPZmZzZXQpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCd0cmFuc2FjdGlvbiBieXRlcyBhcmUgdG9vIHNob3J0IHRvIGNvbnRhaW4gdmVyc2lvbiBieXRlJyk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHZlcnNpb25CeXRlID0gdHhCeXRlc1t2ZXJzaW9uQnl0ZU9mZnNldF07XG4gICAgICBjb25zdCBpc1ZlcnNpb25lZCA9ICh2ZXJzaW9uQnl0ZSAmIDB4ODApICE9PSAwO1xuXG4gICAgICBpZiAoIWlzVmVyc2lvbmVkKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcigndHJhbnNhY3Rpb24gZG9lcyBub3QgaGF2ZSB2ZXJzaW9uZWQgZm9ybWF0Jyk7XG4gICAgICB9XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgZmFpbGVkIHRvIHZhbGlkYXRlIHZlcnNpb25lZCB0cmFuc2FjdGlvbiBmb3JtYXQ6ICR7ZXJyb3IubWVzc2FnZX1gKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIGFzeW5jIHZlcmlmeVRyYW5zYWN0aW9uKHBhcmFtczogU29sVmVyaWZ5VHJhbnNhY3Rpb25PcHRpb25zKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgLy8gYXNzZXQgbmFtZSB0byB0cmFuc2ZlciBhbW91bnQgbWFwXG4gICAgY29uc3QgdG90YWxBbW91bnQ6IFJlY29yZDxzdHJpbmcsIEJpZ051bWJlcj4gPSB7fTtcbiAgICBjb25zdCBjb2luQ29uZmlnID0gY29pbnMuZ2V0KHRoaXMuZ2V0Q2hhaW4oKSk7XG4gICAgY29uc3Qge1xuICAgICAgdHhQYXJhbXM6IHR4UGFyYW1zLFxuICAgICAgdHhQcmVidWlsZDogdHhQcmVidWlsZCxcbiAgICAgIG1lbW86IG1lbW8sXG4gICAgICBkdXJhYmxlTm9uY2U6IGR1cmFibGVOb25jZSxcbiAgICAgIHZlcmlmaWNhdGlvbjogdmVyaWZpY2F0aW9uT3B0aW9ucyxcbiAgICB9ID0gcGFyYW1zO1xuXG4gICAgaWYgKHRoaXMuaGFzU29sVmVyc2lvbmVkVHJhbnNhY3Rpb25EYXRhKHR4UGFyYW1zKSkge1xuICAgICAgcmV0dXJuIHRoaXMudmVyaWZ5VmVyc2lvbmVkVHJhbnNhY3Rpb24ocGFyYW1zKTtcbiAgICB9XG5cbiAgICBjb25zdCB0cmFuc2FjdGlvbiA9IG5ldyBUcmFuc2FjdGlvbihjb2luQ29uZmlnKTtcbiAgICAvLyBBbGxvdyB1bnN1cHBvcnRlZCB0b2tlbnMgKG5vdCBpbiBzdGF0aWMgbWFwKSB0byB1c2UgdGhlaXIgbWludCBhZGRyZXNzIGFzIHRva2VuTmFtZSBkdXJpbmcgcGFyc2luZ1xuICAgIHRyYW5zYWN0aW9uLnNldFVzZVRva2VuQWRkcmVzc1Rva2VuTmFtZSh0cnVlKTtcbiAgICBjb25zdCByYXdUeCA9IHR4UHJlYnVpbGQudHhCYXNlNjQgfHwgdHhQcmVidWlsZC50eEhleDtcbiAgICBjb25zdCBjb25zb2xpZGF0ZUlkID0gdHhQcmVidWlsZC5jb25zb2xpZGF0ZUlkO1xuXG4gICAgY29uc3Qgd2FsbGV0Um9vdEFkZHJlc3MgPSBwYXJhbXMud2FsbGV0LmNvaW5TcGVjaWZpYygpPy5yb290QWRkcmVzcztcblxuICAgIGlmICghcmF3VHgpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignbWlzc2luZyByZXF1aXJlZCB0eCBwcmVidWlsZCBwcm9wZXJ0eSB0eEJhc2U2NCBvciB0eEhleCcpO1xuICAgIH1cblxuICAgIGxldCByYXdUeEJhc2U2NCA9IHJhd1R4O1xuICAgIGlmIChIRVhfUkVHRVgudGVzdChyYXdUeCkpIHtcbiAgICAgIHJhd1R4QmFzZTY0ID0gQnVmZmVyLmZyb20ocmF3VHgsICdoZXgnKS50b1N0cmluZygnYmFzZTY0Jyk7XG4gICAgfVxuICAgIHRyYW5zYWN0aW9uLmZyb21SYXdUcmFuc2FjdGlvbihyYXdUeEJhc2U2NCk7XG4gICAgY29uc3QgZXhwbGFpbmVkVHggPSB0cmFuc2FjdGlvbi5leHBsYWluVHJhbnNhY3Rpb24oKTtcbiAgICBjb25zdCBpc0Nsb3NlQXNzb2NpYXRlZFRva2VuQWNjb3VudFR4ID0gdHJhbnNhY3Rpb24udHlwZSA9PT0gVHJhbnNhY3Rpb25UeXBlLkNsb3NlQXNzb2NpYXRlZFRva2VuQWNjb3VudDtcblxuICAgIGlmICh0eFBhcmFtcy50eXBlID09PSAnZW5hYmxldG9rZW4nICYmIHZlcmlmaWNhdGlvbk9wdGlvbnM/LnZlcmlmeVRva2VuRW5hYmxlbWVudCkge1xuICAgICAgdGhpcy52ZXJpZnlUeFR5cGUodHhQYXJhbXMudHlwZSwgZXhwbGFpbmVkVHgudHlwZSk7XG4gICAgICBjb25zdCB0b2tlbkVuYWJsZW1lbnRzUHJlYnVpbGQgPSB0aGlzLnRocm93SWZNaXNzaW5nVG9rZW5FbmFibGVtZW50c09yUmV0dXJuKGV4cGxhaW5lZFR4KTtcbiAgICAgIGNvbnN0IGVuYWJsZVRva2Vuc0NvbmZpZyA9IHRoaXMudGhyb3dJZk1pc3NpbmdFbmFibGVUb2tlbkNvbmZpZ09yUmV0dXJuKHR4UGFyYW1zKTtcblxuICAgICAgdGhpcy52ZXJpZnlUb2tlbk5hbWUodG9rZW5FbmFibGVtZW50c1ByZWJ1aWxkLCBlbmFibGVUb2tlbnNDb25maWcpO1xuICAgICAgYXdhaXQgdGhpcy52ZXJpZnlUb2tlbkFkZHJlc3ModG9rZW5FbmFibGVtZW50c1ByZWJ1aWxkLCBlbmFibGVUb2tlbnNDb25maWcpO1xuICAgIH1cblxuICAgIGlmIChpc0Nsb3NlQXNzb2NpYXRlZFRva2VuQWNjb3VudFR4KSB7XG4gICAgICB0aGlzLnZlcmlmeUNsb3NlQXNzb2NpYXRlZFRva2VuQWNjb3VudEZhbWlseVJvb3RzKHRyYW5zYWN0aW9uLCB3YWxsZXRSb290QWRkcmVzcyk7XG4gICAgICBpZiAodHhQYXJhbXMucmVjaXBpZW50cyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHRoaXMudmVyaWZ5Q2xvc2VBdGFSZWNpcGllbnRzTWF0Y2hDbG9zZUluc3RydWN0aW9ucyh0cmFuc2FjdGlvbiwgdHhQYXJhbXMucmVjaXBpZW50cyk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3QgaXNUb2tlbkVuYWJsZW1lbnRUeCA9IHR4UGFyYW1zLnR5cGUgPT09ICdlbmFibGV0b2tlbic7XG4gICAgLy8gdXNlcnMgZG8gbm90IGlucHV0IHJlY2lwaWVudHMgZm9yIGNvbnNvbGlkYXRpb24gcmVxdWVzdHMgYXMgdGhleSBhcmUgZ2VuZXJhdGVkIGJ5IHRoZSBzZXJ2ZXJcbiAgICAvLyBDbG9zZS1BVEEgdHhzIGRvIG5vdCBwb3B1bGF0ZSBleHBsYWluZWRUeC5vdXRwdXRzOyByZWNpcGllbnRzIGNhcnJ5IEFUQSBhZGRyZXNzZXMgZm9yIGludGVudCBvbmx5LlxuICAgIGlmICh0eFBhcmFtcy5yZWNpcGllbnRzICE9PSB1bmRlZmluZWQgJiYgIWlzVG9rZW5FbmFibGVtZW50VHggJiYgIWlzQ2xvc2VBc3NvY2lhdGVkVG9rZW5BY2NvdW50VHgpIHtcbiAgICAgIGNvbnN0IGZpbHRlcmVkUmVjaXBpZW50cyA9IHR4UGFyYW1zLnJlY2lwaWVudHM/Lm1hcCgocmVjaXBpZW50KSA9PlxuICAgICAgICBfLnBpY2socmVjaXBpZW50LCBbJ2FkZHJlc3MnLCAnYW1vdW50JywgJ3Rva2VuTmFtZScsICd0b2tlbkFkZHJlc3MnLCAncHJvZ3JhbUlkJ10pXG4gICAgICApO1xuICAgICAgY29uc3QgZmlsdGVyZWRPdXRwdXRzID0gZXhwbGFpbmVkVHgub3V0cHV0cy5tYXAoKG91dHB1dCkgPT4gXy5waWNrKG91dHB1dCwgWydhZGRyZXNzJywgJ2Ftb3VudCcsICd0b2tlbk5hbWUnXSkpO1xuXG4gICAgICBpZiAoZmlsdGVyZWRSZWNpcGllbnRzLmxlbmd0aCAhPT0gZmlsdGVyZWRPdXRwdXRzLmxlbmd0aCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ051bWJlciBvZiB0eCBvdXRwdXRzIGRvZXMgbm90IG1hdGNoIHdpdGggbnVtYmVyIG9mIHR4UGFyYW1zIHJlY2lwaWVudHMnKTtcbiAgICAgIH1cblxuICAgICAgLy8gRm9yIGVhY2ggcmVjaXBpZW50LCBjaGVjayBpZiBpdCdzIGEgdG9rZW4gdHggKHRva2VuTmFtZSB3aWxsIGV4aXN0IGlmIHNvKVxuICAgICAgLy8gSWYgaXQgaXMgYSB0b2tlbiB0eCwgdmVyaWZ5IHRoYXQgdGhlIHJlY2lwaWVudCBhZGRyZXNzIGVxdWFscyB0aGUgZGVyaXZlZCBhZGRyZXNzIGZyb20gZXhwbGFpbmVkVHhcbiAgICAgIC8vIERlcml2ZSB0aGUgQVRBIGlmIGl0IGlzIGEgbmF0aXZlIGFkZHJlc3MgYW5kIGNvbmZpcm0gaXQgaXMgZXF1YWwgdG8gdGhlIGV4cGxhaW5lZCB0eCByZWNpcGllbnRcbiAgICAgIGNvbnN0IHJlY2lwaWVudENoZWNrcyA9IGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgICBmaWx0ZXJlZFJlY2lwaWVudHMubWFwKGFzeW5jIChyZWNpcGllbnRGcm9tVXNlciwgaW5kZXgpID0+IHtcbiAgICAgICAgICBjb25zdCByZWNpcGllbnRGcm9tVHggPSBmaWx0ZXJlZE91dHB1dHNbaW5kZXhdOyAvLyBUaGlzIGFkZHJlc3Mgc2hvdWxkIGJlIGFuIEFUQVxuXG4gICAgICAgICAgLy8gQ29tcGFyZSB0aGUgQmlnTnVtYmVyIHZhbHVlcyBiZWNhdXNlIGFtb3VudCBpcyAoc3RyaW5nIHwgbnVtYmVyKVxuICAgICAgICAgIC8vIEFwcGx5IHMzOTB4IGVuZGlhbm5lc3MgZml4IGlmIG5lZWRlZFxuICAgICAgICAgIGNvbnN0IHVzZXJBbW91bnRTdHIgPSBTdHJpbmcocmVjaXBpZW50RnJvbVVzZXIuYW1vdW50KTtcbiAgICAgICAgICBjb25zdCB0eEFtb3VudFN0ciA9IGdldEFtb3VudEJhc2VkT25FbmRpYW5uZXNzKHJlY2lwaWVudEZyb21UeC5hbW91bnQpO1xuXG4gICAgICAgICAgY29uc3QgdXNlckFtb3VudCA9IG5ldyBCaWdOdW1iZXIodXNlckFtb3VudFN0cik7XG4gICAgICAgICAgY29uc3QgdHhBbW91bnQgPSBuZXcgQmlnTnVtYmVyKHR4QW1vdW50U3RyKTtcbiAgICAgICAgICBpZiAoIXVzZXJBbW91bnQuaXNFcXVhbFRvKHR4QW1vdW50KSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIC8vIENvbXBhcmUgdGhlIGFkZHJlc3NlcyBhbmQgdG9rZW5OYW1lc1xuICAgICAgICAgIC8vIEVsc2UgaWYgdGhlIGFkZHJlc3NlcyBhcmUgbm90IHRoZSBzYW1lLCBjaGVjayB0aGUgZGVyaXZlZCBBVEEgZm9yIHBhcml0eVxuICAgICAgICAgIGlmIChcbiAgICAgICAgICAgIHJlY2lwaWVudEZyb21Vc2VyLmFkZHJlc3MgPT09IHJlY2lwaWVudEZyb21UeC5hZGRyZXNzICYmXG4gICAgICAgICAgICByZWNpcGllbnRGcm9tVXNlci50b2tlbk5hbWUgPT09IHJlY2lwaWVudEZyb21UeC50b2tlbk5hbWVcbiAgICAgICAgICApIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgIH0gZWxzZSBpZiAocmVjaXBpZW50RnJvbVVzZXIuYWRkcmVzcyAhPT0gcmVjaXBpZW50RnJvbVR4LmFkZHJlc3MgJiYgcmVjaXBpZW50RnJvbVVzZXIudG9rZW5OYW1lKSB7XG4gICAgICAgICAgICAvLyBUcnkgdG8gY2hlY2sgaWYgdGhlIHVzZXIncyBkZXJpdmVkIEFUQSBpcyBlcXVhbCB0byB0aGUgdHggcmVjaXBpZW50IGFkZHJlc3NcbiAgICAgICAgICAgIC8vIElmIGdldEFzc29jaWF0ZWRUb2tlbkFjY291bnRBZGRyZXNzIHRocm93cyBhbiBlcnJvciwgdGhlbiB3ZSBhcmUgdW5hYmxlIHRvIGRlcml2ZSB0aGUgQVRBIGZvciB0aGF0IGFkZHJlc3MuXG4gICAgICAgICAgICAvLyBSZXR1cm4gZmFsc2UgYW5kIHRocm93IGFuIGVycm9yIGlmIHRoYXQgaXMgdGhlIGNhc2UuXG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICBjb25zdCB0b2tlbkZyb21NYXAgPSBnZXRTb2xUb2tlbkZyb21Ub2tlbk5hbWUocmVjaXBpZW50RnJvbVVzZXIudG9rZW5OYW1lKTtcbiAgICAgICAgICAgICAgY29uc3QgbWludEFkZHJlc3MgPSB0b2tlbkZyb21NYXA/LnRva2VuQWRkcmVzcyA/PyByZWNpcGllbnRGcm9tVXNlci50b2tlbkFkZHJlc3M7XG4gICAgICAgICAgICAgIGNvbnN0IHByb2dyYW1JZCA9IHRva2VuRnJvbU1hcD8ucHJvZ3JhbUlkID8/IHJlY2lwaWVudEZyb21Vc2VyLnByb2dyYW1JZDtcblxuICAgICAgICAgICAgICBpZiAoIW1pbnRBZGRyZXNzKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgcmV0dXJuIGdldEFzc29jaWF0ZWRUb2tlbkFjY291bnRBZGRyZXNzKG1pbnRBZGRyZXNzLCByZWNpcGllbnRGcm9tVXNlci5hZGRyZXNzLCB0cnVlLCBwcm9ncmFtSWQpLnRoZW4oXG4gICAgICAgICAgICAgICAgKGF0YTogc3RyaW5nKSA9PiB7XG4gICAgICAgICAgICAgICAgICByZXR1cm4gYXRhID09PSByZWNpcGllbnRGcm9tVHguYWRkcmVzcztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9IGNhdGNoIHtcbiAgICAgICAgICAgICAgLy8gVW5hYmxlIHRvIGRlcml2ZSBBVEFcbiAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH0pXG4gICAgICApO1xuXG4gICAgICBpZiAocmVjaXBpZW50Q2hlY2tzLmluY2x1ZGVzKGZhbHNlKSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1R4IG91dHB1dHMgZG9lcyBub3QgbWF0Y2ggd2l0aCBleHBlY3RlZCB0eFBhcmFtcyByZWNpcGllbnRzJyk7XG4gICAgICB9XG4gICAgfSBlbHNlIGlmICh2ZXJpZmljYXRpb25PcHRpb25zPy5jb25zb2xpZGF0aW9uVG9CYXNlQWRkcmVzcykge1xuICAgICAgLy92ZXJpZnkgZnVuZHMgYXJlIHNlbnQgdG8gd2FsbGV0Um9vdEFkZHJlc3MgZm9yIGEgY29uc29saWRhdGlvblxuICAgICAgY29uc3QgZmlsdGVyZWRPdXRwdXRzID0gZXhwbGFpbmVkVHgub3V0cHV0cy5tYXAoKG91dHB1dCkgPT4gXy5waWNrKG91dHB1dCwgWydhZGRyZXNzJywgJ2Ftb3VudCcsICd0b2tlbk5hbWUnXSkpO1xuXG4gICAgICAvLyBDYWNoZSB0byBzdG9yZSBhbHJlYWR5IGRlcml2ZWQgQVRBIGFkZHJlc3Nlc1xuICAgICAgY29uc3QgYXRhQWRkcmVzc0NhY2hlOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0ge307XG5cbiAgICAgIGZvciAoY29uc3Qgb3V0cHV0IG9mIGZpbHRlcmVkT3V0cHV0cykge1xuICAgICAgICBpZiAob3V0cHV0LnRva2VuTmFtZSkge1xuICAgICAgICAgIC8vIENoZWNrIGNhY2hlIGZpcnN0IGJlZm9yZSBkZXJpdmluZyBBVEEgYWRkcmVzc1xuICAgICAgICAgIGlmICghYXRhQWRkcmVzc0NhY2hlW291dHB1dC50b2tlbk5hbWVdKSB7XG4gICAgICAgICAgICBjb25zdCB0b2tlbkZyb21NYXAgPSBnZXRTb2xUb2tlbkZyb21Ub2tlbk5hbWUob3V0cHV0LnRva2VuTmFtZSk7XG4gICAgICAgICAgICBpZiAodG9rZW5Gcm9tTWFwPy50b2tlbkFkZHJlc3MgJiYgdG9rZW5Gcm9tTWFwPy5wcm9ncmFtSWQpIHtcbiAgICAgICAgICAgICAgYXRhQWRkcmVzc0NhY2hlW291dHB1dC50b2tlbk5hbWVdID0gYXdhaXQgZ2V0QXNzb2NpYXRlZFRva2VuQWNjb3VudEFkZHJlc3MoXG4gICAgICAgICAgICAgICAgdG9rZW5Gcm9tTWFwLnRva2VuQWRkcmVzcyxcbiAgICAgICAgICAgICAgICB3YWxsZXRSb290QWRkcmVzcyBhcyBzdHJpbmcsXG4gICAgICAgICAgICAgICAgdHJ1ZSxcbiAgICAgICAgICAgICAgICB0b2tlbkZyb21NYXAucHJvZ3JhbUlkXG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAvLyBGb3IgdW5zdXBwb3J0ZWQgdG9rZW5zLCBleHBsYWluVHJhbnNhY3Rpb24gc2V0cyB0b2tlbk5hbWUgdG8gdGhlIG1pbnQgYWRkcmVzcyBpdHNlbGYuXG4gICAgICAgICAgICAgIC8vIEF0dGVtcHQgQVRBIGRlcml2YXRpb24gdXNpbmcgdG9rZW5OYW1lIGFzIHRoZSBtaW50IGFkZHJlc3M7IHByb2dyYW1JZCBkZWZhdWx0cyB0byBUT0tFTl9QUk9HUkFNX0lELlxuICAgICAgICAgICAgICBhdGFBZGRyZXNzQ2FjaGVbb3V0cHV0LnRva2VuTmFtZV0gPSBhd2FpdCBnZXRBc3NvY2lhdGVkVG9rZW5BY2NvdW50QWRkcmVzcyhcbiAgICAgICAgICAgICAgICBvdXRwdXQudG9rZW5OYW1lLFxuICAgICAgICAgICAgICAgIHdhbGxldFJvb3RBZGRyZXNzIGFzIHN0cmluZyxcbiAgICAgICAgICAgICAgICB0cnVlXG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKGF0YUFkZHJlc3NDYWNoZVtvdXRwdXQudG9rZW5OYW1lXSAhPT0gb3V0cHV0LmFkZHJlc3MpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigndHggb3V0cHV0cyBkb2VzIG5vdCBtYXRjaCB3aXRoIGV4cGVjdGVkIGFkZHJlc3MnKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAob3V0cHV0LmFkZHJlc3MgIT09IHdhbGxldFJvb3RBZGRyZXNzKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCd0eCBvdXRwdXRzIGRvZXMgbm90IG1hdGNoIHdpdGggZXhwZWN0ZWQgYWRkcmVzcycpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3QgdHJhbnNhY3Rpb25Kc29uID0gdHJhbnNhY3Rpb24udG9Kc29uKCk7XG4gICAgaWYgKG1lbW8gJiYgbWVtby52YWx1ZSAhPT0gZXhwbGFpbmVkVHgubWVtbykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdUeCBtZW1vIGRvZXMgbm90IG1hdGNoIHdpdGggZXhwZWN0ZWQgdHhQYXJhbXMgcmVjaXBpZW50IG1lbW8nKTtcbiAgICB9XG4gICAgaWYgKHR4UGFyYW1zLnJlY2lwaWVudHMgJiYgIWlzVG9rZW5FbmFibGVtZW50VHggJiYgIWlzQ2xvc2VBc3NvY2lhdGVkVG9rZW5BY2NvdW50VHgpIHtcbiAgICAgIGZvciAoY29uc3QgcmVjaXBpZW50cyBvZiB0eFBhcmFtcy5yZWNpcGllbnRzKSB7XG4gICAgICAgIC8vIHRvdGFsQW1vdW50IGJhc2VkIG9uIGVhY2ggdG9rZW5cbiAgICAgICAgY29uc3QgYXNzZXROYW1lID0gcmVjaXBpZW50cy50b2tlbk5hbWUgfHwgdGhpcy5nZXRDaGFpbigpO1xuICAgICAgICBjb25zdCBhbW91bnQgPSB0b3RhbEFtb3VudFthc3NldE5hbWVdIHx8IG5ldyBCaWdOdW1iZXIoMCk7XG4gICAgICAgIHRvdGFsQW1vdW50W2Fzc2V0TmFtZV0gPSBhbW91bnQucGx1cyhyZWNpcGllbnRzLmFtb3VudCk7XG4gICAgICB9XG5cbiAgICAgIC8vIHRvdGFsIG91dHB1dCBhbW91bnQgZnJvbSBleHBsYWluZWRUeFxuICAgICAgY29uc3QgZXhwbGFpbmVkVHhUb3RhbDogUmVjb3JkPHN0cmluZywgQmlnTnVtYmVyPiA9IHt9O1xuXG4gICAgICBmb3IgKGNvbnN0IG91dHB1dCBvZiBleHBsYWluZWRUeC5vdXRwdXRzKSB7XG4gICAgICAgIC8vIEFwcGx5IHMzOTB4IGVuZGlhbm5lc3MgZml4IHRvIG91dHB1dCBhbW91bnRzIGJlZm9yZSBzdW1taW5nXG4gICAgICAgIGNvbnN0IG91dHB1dEFtb3VudFN0ciA9IGdldEFtb3VudEJhc2VkT25FbmRpYW5uZXNzKG91dHB1dC5hbW91bnQpO1xuXG4gICAgICAgIC8vIHRvdGFsIG91dHB1dCBhbW91bnQgYmFzZWQgb24gZWFjaCB0b2tlblxuICAgICAgICBjb25zdCBhc3NldE5hbWUgPSBvdXRwdXQudG9rZW5OYW1lIHx8IHRoaXMuZ2V0Q2hhaW4oKTtcbiAgICAgICAgY29uc3QgYW1vdW50ID0gZXhwbGFpbmVkVHhUb3RhbFthc3NldE5hbWVdIHx8IG5ldyBCaWdOdW1iZXIoMCk7XG4gICAgICAgIGV4cGxhaW5lZFR4VG90YWxbYXNzZXROYW1lXSA9IGFtb3VudC5wbHVzKG91dHB1dEFtb3VudFN0cik7XG4gICAgICB9XG5cbiAgICAgIGlmICghXy5pc0VxdWFsKGV4cGxhaW5lZFR4VG90YWwsIHRvdGFsQW1vdW50KSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1R4IHRvdGFsIGFtb3VudCBkb2VzIG5vdCBtYXRjaCB3aXRoIGV4cGVjdGVkIHRvdGFsIGFtb3VudCBmaWVsZCcpO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIEZvciBub24tY29uc29saWRhdGUgdHJhbnNhY3Rpb25zLCBmZWVQYXllciBtdXN0IGJlIHRoZSB3YWxsZXQncyByb290IGFkZHJlc3NcbiAgICBpZiAoY29uc29saWRhdGVJZCA9PT0gdW5kZWZpbmVkICYmIHRyYW5zYWN0aW9uSnNvbi5mZWVQYXllciAhPT0gd2FsbGV0Um9vdEFkZHJlc3MpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignVHggZmVlIHBheWVyIGlzIG5vdCB0aGUgd2FsbGV0IHJvb3QgYWRkcmVzcycpO1xuICAgIH1cblxuICAgIGlmIChkdXJhYmxlTm9uY2UgJiYgIV8uaXNFcXVhbChleHBsYWluZWRUeC5kdXJhYmxlTm9uY2UsIGR1cmFibGVOb25jZSkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignVHggZHVyYWJsZU5vbmNlIGRvZXMgbm90IG1hdGNoIHdpdGggcGFyYW0gZHVyYWJsZU5vbmNlJyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICBhc3luYyBpc1dhbGxldEFkZHJlc3MocGFyYW1zOiBUc3NWZXJpZnlBZGRyZXNzT3B0aW9ucyk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHZlcmlmeUVkZHNhVHNzV2FsbGV0QWRkcmVzcyhcbiAgICAgIHBhcmFtcyxcbiAgICAgIChhZGRyZXNzKSA9PiB0aGlzLmlzVmFsaWRBZGRyZXNzKGFkZHJlc3MpLFxuICAgICAgKHB1YmxpY0tleSkgPT4gdGhpcy5nZXRBZGRyZXNzRnJvbVB1YmxpY0tleShwdWJsaWNLZXkpXG4gICAgKTtcblxuICAgIGlmICghcmVzdWx0KSB7XG4gICAgICB0aHJvdyBuZXcgVW5leHBlY3RlZEFkZHJlc3NFcnJvcihgYWRkcmVzcyB2YWxpZGF0aW9uIGZhaWx1cmU6ICR7cGFyYW1zLmFkZHJlc3N9IGlzIG5vdCBhIHdhbGxldCBhZGRyZXNzYCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICAvKipcbiAgICogTG9jYWxseSBkZXJpdmUgYSBTT0wgd2FsbGV0IHJlY2VpdmUgYWRkcmVzcyBmcm9tIGEgZGVyaXZhdGlvbiBwYXRoLCB1c2luZyB0aGUgd2FsbGV0J3NcbiAgICogY29tbW9uS2V5Y2hhaW4gb25seSAobm8gcHJpdmF0ZSBrZXlzLCBubyBuZXR3b3JrIGFjY2VzcykuIFRoaXMgaXMgdGhlIGludmVyc2Ugb2ZcbiAgICoge0BsaW5rIGlzV2FsbGV0QWRkcmVzc306IGl0ICpwcm9kdWNlcyogdGhlIGFkZHJlc3MgdmlhIHRoZSBzYW1lIEVkRFNBIFRTUyBkZXJpdmF0aW9uIHRoYXRcbiAgICogaXNXYWxsZXRBZGRyZXNzIGNoZWNrcyBhZ2FpbnN0LCBzbyB0aGUgdHdvIGNhbiBuZXZlciBkaXZlcmdlLlxuICAgKiBAcGFyYW0gcGFyYW1zIGtleWNoYWlucyAoY29tbW9uS2V5Y2hhaW4pLCBkZXJpdmF0aW9uIGluZGV4LCBhbmQgb3B0aW9uYWwgU01DIHNlZWRcbiAgICogQHJldHVybnMgdGhlIGRlcml2ZWQgYWRkcmVzcywgdGhlIGluZGV4IHVzZWQsIGFuZCB0aGUgSEQgZGVyaXZhdGlvbiBwYXRoXG4gICAqL1xuICBhc3luYyBkZXJpdmVBZGRyZXNzKHBhcmFtczogRGVyaXZlQWRkcmVzc09wdGlvbnMpOiBQcm9taXNlPERlcml2ZUFkZHJlc3NSZXN1bHQ+IHtcbiAgICAvLyBEZXJpdmUgdGhlIG5hdGl2ZSBvd25lciAod2FsbGV0KSBhZGRyZXNzIGZyb20gdGhlIGNvbW1vbktleWNoYWluLlxuICAgIGNvbnN0IHsgYWRkcmVzczogb3duZXJBZGRyZXNzLCBkZXJpdmF0aW9uUGF0aCB9ID0gYXdhaXQgZGVyaXZlTVBDV2FsbGV0QWRkcmVzcyhcbiAgICAgIHtcbiAgICAgICAgLy8gZXh0cmFjdENvbW1vbktleWNoYWluIHZhbGlkYXRlcyB0aGUgY29tbW9uS2V5Y2hhaW4gaXMgcHJlc2VudCBhdCBydW50aW1lXG4gICAgICAgIGtleWNoYWluczogKHBhcmFtcy5rZXljaGFpbnMgPz8gW10pIGFzIFRzc1ZlcmlmeUFkZHJlc3NPcHRpb25zWydrZXljaGFpbnMnXSxcbiAgICAgICAgaW5kZXg6IHBhcmFtcy5pbmRleCxcbiAgICAgICAgZGVyaXZlZEZyb21QYXJlbnRXaXRoU2VlZDogcGFyYW1zLmRlcml2ZWRGcm9tUGFyZW50V2l0aFNlZWQsXG4gICAgICAgIG11bHRpc2lnVHlwZVZlcnNpb246IHBhcmFtcy5tdWx0aXNpZ1R5cGVWZXJzaW9uLFxuICAgICAgICBrZXlDdXJ2ZTogJ2VkMjU1MTknLFxuICAgICAgfSxcbiAgICAgIChwdWJsaWNLZXkpID0+IHRoaXMuZ2V0QWRkcmVzc0Zyb21QdWJsaWNLZXkocHVibGljS2V5KVxuICAgICk7XG5cbiAgICAvLyBObyB0b2tlbiByZXF1ZXN0ZWQ6IHJldHVybiB0aGUgbmF0aXZlIFNPTCByZWNlaXZlIGFkZHJlc3MuXG4gICAgaWYgKCFwYXJhbXMudG9rZW5OYW1lKSB7XG4gICAgICByZXR1cm4geyBhZGRyZXNzOiBvd25lckFkZHJlc3MsIGluZGV4OiBwYXJhbXMuaW5kZXgsIGRlcml2YXRpb25QYXRoIH07XG4gICAgfVxuXG4gICAgLy8gVG9rZW4gcmVxdWVzdGVkOiB0aGUgZGVwb3NpdCBhZGRyZXNzIGlzIHRoZSBvd25lcidzIEFzc29jaWF0ZWQgVG9rZW4gQWNjb3VudCAoQVRBKSBmb3IgdGhlXG4gICAgLy8gdG9rZW4ncyBtaW50LCBkZXJpdmVkIHRoZSBzYW1lIHdheSBTT0wgdG9rZW4gYWRkcmVzc2VzIGFyZSBwcm9kdWNlZCBlbHNld2hlcmUgaW4gdGhpcyBjb2luLlxuICAgIGNvbnN0IHRva2VuID0gZ2V0U29sVG9rZW5Gcm9tVG9rZW5OYW1lKHBhcmFtcy50b2tlbk5hbWUpO1xuICAgIGlmICghdG9rZW4gfHwgdG9rZW4udG9rZW5BZGRyZXNzID09PSB1bmRlZmluZWQgfHwgdG9rZW4ucHJvZ3JhbUlkID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgdW5rbm93biBvciB1bnN1cHBvcnRlZCBTT0wgdG9rZW46ICR7cGFyYW1zLnRva2VuTmFtZX1gKTtcbiAgICB9XG4gICAgY29uc3QgYWRkcmVzcyA9IGF3YWl0IGdldEFzc29jaWF0ZWRUb2tlbkFjY291bnRBZGRyZXNzKHRva2VuLnRva2VuQWRkcmVzcywgb3duZXJBZGRyZXNzLCB0cnVlLCB0b2tlbi5wcm9ncmFtSWQpO1xuXG4gICAgcmV0dXJuIHsgYWRkcmVzcywgaW5kZXg6IHBhcmFtcy5pbmRleCwgZGVyaXZhdGlvblBhdGggfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDb252ZXJ0cyBhIFNvbGFuYSBwdWJsaWMga2V5IHRvIGFuIGFkZHJlc3NcbiAgICogQHBhcmFtIHB1YmxpY0tleSBIZXgtZW5jb2RlZCBwdWJsaWMga2V5ICg2NCBoZXggY2hhcmFjdGVycyA9IDMyIGJ5dGVzKVxuICAgKiBAcmV0dXJucyBCYXNlNTgtZW5jb2RlZCBTb2xhbmEgYWRkcmVzc1xuICAgKi9cbiAgZ2V0QWRkcmVzc0Zyb21QdWJsaWNLZXkocHVibGljS2V5OiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIGNvbnN0IHB1YmxpY0tleUJ1ZmZlciA9IEJ1ZmZlci5mcm9tKHB1YmxpY0tleSwgJ2hleCcpO1xuICAgIHJldHVybiBiYXNlNTguZW5jb2RlKHB1YmxpY0tleUJ1ZmZlcik7XG4gIH1cblxuICAvKipcbiAgICogR2VuZXJhdGUgU29sYW5hIGtleSBwYWlyXG4gICAqXG4gICAqIEBwYXJhbSB7QnVmZmVyfSBzZWVkIC0gU2VlZCBmcm9tIHdoaWNoIHRoZSBuZXcgU29sS2V5UGFpciBzaG91bGQgYmUgZ2VuZXJhdGVkLCBvdGhlcndpc2UgYSByYW5kb20gc2VlZCBpcyB1c2VkXG4gICAqIEByZXR1cm5zIHtPYmplY3R9IG9iamVjdCB3aXRoIGdlbmVyYXRlZCBwdWIgYW5kIHBydlxuICAgKi9cbiAgZ2VuZXJhdGVLZXlQYWlyKHNlZWQ/OiBCdWZmZXIgfCB1bmRlZmluZWQpOiBLZXlQYWlyIHtcbiAgICBjb25zdCByZXN1bHQgPSBzZWVkID8gbmV3IFNvbEtleVBhaXIoeyBzZWVkIH0pLmdldEtleXMoKSA6IG5ldyBTb2xLZXlQYWlyKCkuZ2V0S2V5cygpO1xuICAgIHJldHVybiByZXN1bHQgYXMgS2V5UGFpcjtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm4gYm9vbGVhbiBpbmRpY2F0aW5nIHdoZXRoZXIgaW5wdXQgaXMgdmFsaWQgcHVibGljIGtleSBmb3IgdGhlIGNvaW5cbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IHB1YiB0aGUgcHJ2IHRvIGJlIGNoZWNrZWRcbiAgICogQHJldHVybnMgaXMgaXQgdmFsaWQ/XG4gICAqL1xuICBpc1ZhbGlkUHViKHB1Yjogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIGlzVmFsaWRQdWJsaWNLZXkocHViKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm4gYm9vbGVhbiBpbmRpY2F0aW5nIHdoZXRoZXIgaW5wdXQgaXMgdmFsaWQgcHJpdmF0ZSBrZXkgZm9yIHRoZSBjb2luXG4gICAqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBwcnYgdGhlIHBydiB0byBiZSBjaGVja2VkXG4gICAqIEByZXR1cm5zIGlzIGl0IHZhbGlkP1xuICAgKi9cbiAgaXNWYWxpZFBydihwcnY6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIHJldHVybiBpc1ZhbGlkUHJpdmF0ZUtleShwcnYpO1xuICB9XG5cbiAgaXNWYWxpZEFkZHJlc3MoYWRkcmVzczogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIGlzVmFsaWRBZGRyZXNzKGFkZHJlc3MpO1xuICB9XG5cbiAgYXN5bmMgc2lnbk1lc3NhZ2Uoa2V5OiBLZXlQYWlyLCBtZXNzYWdlOiBzdHJpbmcgfCBCdWZmZXIpOiBQcm9taXNlPEJ1ZmZlcj4ge1xuICAgIGNvbnN0IHNvbEtleXBhaXIgPSBuZXcgU29sS2V5UGFpcih7IHBydjoga2V5LnBydiB9KTtcbiAgICBpZiAoQnVmZmVyLmlzQnVmZmVyKG1lc3NhZ2UpKSB7XG4gICAgICBtZXNzYWdlID0gYmFzZTU4LmVuY29kZShtZXNzYWdlKTtcbiAgICB9XG5cbiAgICByZXR1cm4gQnVmZmVyLmZyb20oc29sS2V5cGFpci5zaWduTWVzc2FnZShtZXNzYWdlKSk7XG4gIH1cblxuICAvKipcbiAgICogU2lnbnMgU29sYW5hIHRyYW5zYWN0aW9uXG4gICAqIEBwYXJhbSBwYXJhbXNcbiAgICogQHBhcmFtIGNhbGxiYWNrXG4gICAqL1xuICBhc3luYyBzaWduVHJhbnNhY3Rpb24ocGFyYW1zOiBTb2xTaWduVHJhbnNhY3Rpb25PcHRpb25zKTogUHJvbWlzZTxTaWduZWRUcmFuc2FjdGlvbj4ge1xuICAgIGNvbnN0IGZhY3RvcnkgPSB0aGlzLmdldEJ1aWxkZXIoKTtcbiAgICBjb25zdCByYXdUeCA9IHBhcmFtcy50eFByZWJ1aWxkLnR4SGV4IHx8IHBhcmFtcy50eFByZWJ1aWxkLnR4QmFzZTY0O1xuICAgIGNvbnN0IHR4QnVpbGRlciA9IGZhY3RvcnkuZnJvbShyYXdUeCk7XG4gICAgdHhCdWlsZGVyLnNpZ24oeyBrZXk6IHBhcmFtcy5wcnYgfSk7XG4gICAgY29uc3QgdHJhbnNhY3Rpb246IEJhc2VUcmFuc2FjdGlvbiA9IGF3YWl0IHR4QnVpbGRlci5idWlsZCgpO1xuXG4gICAgaWYgKCF0cmFuc2FjdGlvbikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIHRyYW5zYWN0aW9uJyk7XG4gICAgfVxuXG4gICAgY29uc3Qgc2VyaWFsaXplZFR4ID0gKHRyYW5zYWN0aW9uIGFzIEJhc2VUcmFuc2FjdGlvbikudG9Ccm9hZGNhc3RGb3JtYXQoKTtcblxuICAgIHJldHVybiB7XG4gICAgICB0eEhleDogc2VyaWFsaXplZFR4LFxuICAgIH0gYXMgYW55O1xuICB9XG5cbiAgYXN5bmMgcGFyc2VUcmFuc2FjdGlvbihwYXJhbXM6IFNvbFBhcnNlVHJhbnNhY3Rpb25PcHRpb25zKTogUHJvbWlzZTxTb2xQYXJzZWRUcmFuc2FjdGlvbj4ge1xuICAgIC8vIGV4cGxhaW5UcmFuc2FjdGlvbiBub3cgdXNlcyBXQVNNIGZvciB0ZXN0bmV0IGF1dG9tYXRpY2FsbHlcbiAgICBjb25zdCB0cmFuc2FjdGlvbkV4cGxhbmF0aW9uID0gYXdhaXQgdGhpcy5leHBsYWluVHJhbnNhY3Rpb24oe1xuICAgICAgdHhCYXNlNjQ6IHBhcmFtcy50eEJhc2U2NCxcbiAgICAgIGZlZUluZm86IHBhcmFtcy5mZWVJbmZvLFxuICAgICAgdG9rZW5BY2NvdW50UmVudEV4ZW1wdEFtb3VudDogcGFyYW1zLnRva2VuQWNjb3VudFJlbnRFeGVtcHRBbW91bnQsXG4gICAgfSk7XG5cbiAgICBpZiAoIXRyYW5zYWN0aW9uRXhwbGFuYXRpb24pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCB0cmFuc2FjdGlvbicpO1xuICAgIH1cblxuICAgIGNvbnN0IHNvbFRyYW5zYWN0aW9uID0gdHJhbnNhY3Rpb25FeHBsYW5hdGlvbiBhcyBTb2xUcmFuc2FjdGlvbkV4cGxhbmF0aW9uO1xuICAgIGlmIChzb2xUcmFuc2FjdGlvbi5vdXRwdXRzLmxlbmd0aCA8PSAwKSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBpbnB1dHM6IFtdLFxuICAgICAgICBvdXRwdXRzOiBbXSxcbiAgICAgIH07XG4gICAgfVxuXG4gICAgY29uc3Qgc2VuZGVyQWRkcmVzcyA9IHNvbFRyYW5zYWN0aW9uLm91dHB1dHNbMF0uYWRkcmVzcztcbiAgICBjb25zdCBmZWVBbW91bnQgPSBuZXcgQmlnTnVtYmVyKHNvbFRyYW5zYWN0aW9uLmZlZS5mZWUpO1xuXG4gICAgLy8gYXNzdW1lIDEgc2VuZGVyLCB3aG8gaXMgYWxzbyB0aGUgZmVlIHBheWVyXG4gICAgY29uc3QgaW5wdXRzID0gW1xuICAgICAge1xuICAgICAgICBhZGRyZXNzOiBzZW5kZXJBZGRyZXNzLFxuICAgICAgICBhbW91bnQ6IG5ldyBCaWdOdW1iZXIoc29sVHJhbnNhY3Rpb24ub3V0cHV0QW1vdW50KS5wbHVzKGZlZUFtb3VudCkudG9OdW1iZXIoKSxcbiAgICAgIH0sXG4gICAgXTtcblxuICAgIGNvbnN0IG91dHB1dHM6IFRyYW5zYWN0aW9uT3V0cHV0W10gPSBzb2xUcmFuc2FjdGlvbi5vdXRwdXRzLm1hcCgoeyBhZGRyZXNzLCBhbW91bnQsIHRva2VuTmFtZSB9KSA9PiB7XG4gICAgICBjb25zdCBvdXRwdXQ6IFRyYW5zYWN0aW9uT3V0cHV0ID0geyBhZGRyZXNzLCBhbW91bnQgfTtcbiAgICAgIGlmICh0b2tlbk5hbWUpIHtcbiAgICAgICAgb3V0cHV0LnRva2VuTmFtZSA9IHRva2VuTmFtZTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBvdXRwdXQ7XG4gICAgfSk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgaW5wdXRzLFxuICAgICAgb3V0cHV0cyxcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIEV4cGxhaW4gYSBTb2xhbmEgdHJhbnNhY3Rpb24gZnJvbSB0eEJhc2U2NFxuICAgKiBVc2VzIFdBU00tYmFzZWQgcGFyc2luZyBmb3IgdGVzdG5ldCwgd2l0aCBmYWxsYmFjayB0byBsZWdhY3kgYnVpbGRlciBhcHByb2FjaC5cbiAgICogQHBhcmFtIHBhcmFtc1xuICAgKi9cbiAgYXN5bmMgZXhwbGFpblRyYW5zYWN0aW9uKHBhcmFtczogRXhwbGFpblRyYW5zYWN0aW9uT3B0aW9ucyk6IFByb21pc2U8U29sVHJhbnNhY3Rpb25FeHBsYW5hdGlvbj4ge1xuICAgIC8vIFVzZSBXQVNNLWJhc2VkIHBhcnNpbmcgZm9yIHRlc3RuZXQgKHNpbXBsZXIsIGZhc3Rlciwgbm8gQHNvbGFuYS93ZWIzLmpzIHJlYnVpbGQpXG4gICAgaWYgKHRoaXMuZ2V0Q2hhaW4oKSA9PT0gJ3Rzb2wnKSB7XG4gICAgICByZXR1cm4gdGhpcy5leHBsYWluVHJhbnNhY3Rpb25XaXRoV2FzbShwYXJhbXMpIGFzIFNvbFRyYW5zYWN0aW9uRXhwbGFuYXRpb247XG4gICAgfVxuXG4gICAgLy8gTGVnYWN5IGFwcHJvYWNoIGZvciBtYWlubmV0ICh1bnRpbCBXQVNNIGlzIGZ1bGx5IHZhbGlkYXRlZClcbiAgICBjb25zdCBmYWN0b3J5ID0gdGhpcy5nZXRCdWlsZGVyKCk7XG4gICAgbGV0IHJlYnVpbHRUcmFuc2FjdGlvbjtcblxuICAgIHRyeSB7XG4gICAgICBjb25zdCB0cmFuc2FjdGlvbkJ1aWxkZXIgPSBmYWN0b3J5LmZyb20ocGFyYW1zLnR4QmFzZTY0KTtcbiAgICAgIGlmICh0cmFuc2FjdGlvbkJ1aWxkZXIgaW5zdGFuY2VvZiBUcmFuc2FjdGlvbkJ1aWxkZXIpIHtcbiAgICAgICAgY29uc3QgdHhCdWlsZGVyID0gdHJhbnNhY3Rpb25CdWlsZGVyIGFzIFRyYW5zYWN0aW9uQnVpbGRlcjtcbiAgICAgICAgdHhCdWlsZGVyLmZlZSh7IGFtb3VudDogcGFyYW1zLmZlZUluZm8uZmVlIH0pO1xuICAgICAgICBpZiAocGFyYW1zLnRva2VuQWNjb3VudFJlbnRFeGVtcHRBbW91bnQpIHtcbiAgICAgICAgICB0eEJ1aWxkZXIuYXNzb2NpYXRlZFRva2VuQWNjb3VudFJlbnQocGFyYW1zLnRva2VuQWNjb3VudFJlbnRFeGVtcHRBbW91bnQpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZWJ1aWx0VHJhbnNhY3Rpb24gPSBhd2FpdCB0cmFuc2FjdGlvbkJ1aWxkZXIuYnVpbGQoKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBsb2dnZXIuZXJyb3IoZSk7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgdHJhbnNhY3Rpb24nKTtcbiAgICB9XG5cbiAgICBjb25zdCBleHBsYWluZWRUcmFuc2FjdGlvbiA9IChyZWJ1aWx0VHJhbnNhY3Rpb24gYXMgQmFzZVRyYW5zYWN0aW9uKS5leHBsYWluVHJhbnNhY3Rpb24oKTtcblxuICAgIHJldHVybiBleHBsYWluZWRUcmFuc2FjdGlvbiBhcyBTb2xUcmFuc2FjdGlvbkV4cGxhbmF0aW9uO1xuICB9XG5cbiAgLyoqXG4gICAqIEV4cGxhaW4gYSBTb2xhbmEgdHJhbnNhY3Rpb24gdXNpbmcgV0FTTSBwYXJzaW5nIChieXBhc3NlcyBAc29sYW5hL3dlYjMuanMgcmVidWlsZCkuXG4gICAqIERlbGVnYXRlcyB0byBzdGFuZGFsb25lIGV4cGxhaW5Tb2xUcmFuc2FjdGlvbigpLlxuICAgKi9cbiAgZXhwbGFpblRyYW5zYWN0aW9uV2l0aFdhc20ocGFyYW1zOiBFeHBsYWluVHJhbnNhY3Rpb25PcHRpb25zKTogU29sTGliVHJhbnNhY3Rpb25FeHBsYW5hdGlvbiB7XG4gICAgcmV0dXJuIGV4cGxhaW5Tb2xUcmFuc2FjdGlvbih7IC4uLnBhcmFtcywgY29pbk5hbWU6IHBhcmFtcy5jb2luTmFtZSA/PyB0aGlzLmdldENoYWluKCkgfSk7XG4gIH1cblxuICAvKiogQGluaGVyaXREb2MgKi9cbiAgYXN5bmMgZ2V0U2lnbmFibGVQYXlsb2FkKHNlcmlhbGl6ZWRUeDogc3RyaW5nKTogUHJvbWlzZTxCdWZmZXI+IHtcbiAgICBjb25zdCBmYWN0b3J5ID0gdGhpcy5nZXRCdWlsZGVyKCk7XG4gICAgY29uc3QgcmVidWlsdFRyYW5zYWN0aW9uID0gYXdhaXQgZmFjdG9yeS5mcm9tKHNlcmlhbGl6ZWRUeCkuYnVpbGQoKTtcbiAgICByZXR1cm4gcmVidWlsdFRyYW5zYWN0aW9uLnNpZ25hYmxlUGF5bG9hZDtcbiAgfVxuXG4gIC8qKiBAaW5oZXJpdERvYyAqL1xuICBhc3luYyBwcmVzaWduVHJhbnNhY3Rpb24ocGFyYW1zOiBQcmVzaWduVHJhbnNhY3Rpb25PcHRpb25zKTogUHJvbWlzZTxQcmVzaWduVHJhbnNhY3Rpb25PcHRpb25zPiB7XG4gICAgLy8gSG90IHdhbGxldCB0eG5zIGFyZSBvbmx5IHZhbGlkIGZvciAxLTIgbWludXRlcy5cbiAgICAvLyBUbyBidXkgbW9yZSB0aW1lLCB3ZSByZWJ1aWxkIHRoZSB0cmFuc2FjdGlvbiB3aXRoIGEgbmV3IGJsb2NraGFzaCByaWdodCBiZWZvcmUgd2Ugc2lnbi5cbiAgICBpZiAocGFyYW1zLndhbGxldERhdGEudHlwZSAhPT0gJ2hvdCcpIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUocGFyYW1zKTtcbiAgICB9XG5cbiAgICBjb25zdCB0eFJlcXVlc3RJZCA9IHBhcmFtcy50eFByZWJ1aWxkPy50eFJlcXVlc3RJZDtcbiAgICBpZiAodHhSZXF1ZXN0SWQgPT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdNaXNzaW5nIHR4UmVxdWVzdElkJyk7XG4gICAgfVxuXG4gICAgY29uc3QgeyB0c3NVdGlscyB9ID0gcGFyYW1zO1xuXG4gICAgYXdhaXQgdHNzVXRpbHMhLmRlbGV0ZVNpZ25hdHVyZVNoYXJlcyh0eFJlcXVlc3RJZCk7XG4gICAgY29uc3QgcmVjcmVhdGVkID0gYXdhaXQgdHNzVXRpbHMhLmdldFR4UmVxdWVzdCh0eFJlcXVlc3RJZCk7XG4gICAgbGV0IHR4SGV4ID0gJyc7XG4gICAgaWYgKHJlY3JlYXRlZC51bnNpZ25lZFR4cykge1xuICAgICAgdHhIZXggPSByZWNyZWF0ZWQudW5zaWduZWRUeHNbMF0/LnNlcmlhbGl6ZWRUeEhleDtcbiAgICB9IGVsc2Uge1xuICAgICAgdHhIZXggPSByZWNyZWF0ZWQudHJhbnNhY3Rpb25zID8gcmVjcmVhdGVkLnRyYW5zYWN0aW9uc1swXT8udW5zaWduZWRUeC5zZXJpYWxpemVkVHhIZXggOiAnJztcbiAgICB9XG5cbiAgICBpZiAoIXR4SGV4KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ01pc3Npbmcgc2VyaWFsaXplZCB0eCBoZXgnKTtcbiAgICB9XG5cbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHtcbiAgICAgIC4uLnBhcmFtcyxcbiAgICAgIHR4UHJlYnVpbGQ6IHJlY3JlYXRlZCxcbiAgICAgIHR4SGV4LFxuICAgIH0pO1xuICB9XG5cbiAgcHJvdGVjdGVkIGdldFB1YmxpY05vZGVVcmwoYXBpS2V5Pzogc3RyaW5nKTogc3RyaW5nIHtcbiAgICBpZiAoYXBpS2V5KSB7XG4gICAgICByZXR1cm4gRW52aXJvbm1lbnRzW3RoaXMuYml0Z28uZ2V0RW52KCldLnNvbEFsY2hlbXlOb2RlVXJsICsgYC8ke2FwaUtleX1gO1xuICAgIH1cbiAgICByZXR1cm4gRW52aXJvbm1lbnRzW3RoaXMuYml0Z28uZ2V0RW52KCldLnNvbE5vZGVVcmw7XG4gIH1cblxuICAvKipcbiAgICogTWFrZSBhIHJlcXVlc3QgdG8gb25lIG9mIHRoZSBwdWJsaWMgU09MIG5vZGVzIGF2YWlsYWJsZVxuICAgKiBAcGFyYW0gcGFyYW1zLnBheWxvYWRcbiAgICovXG4gIHByb3RlY3RlZCBhc3luYyBnZXREYXRhRnJvbU5vZGUoXG4gICAgcGFyYW1zOiB7IHBheWxvYWQ/OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiB9LFxuICAgIGFwaUtleT86IHN0cmluZ1xuICApOiBQcm9taXNlPHJlcXVlc3QuUmVzcG9uc2U+IHtcbiAgICBjb25zdCBub2RlVXJsID0gdGhpcy5nZXRQdWJsaWNOb2RlVXJsKGFwaUtleSk7XG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiBhd2FpdCByZXF1ZXN0LnBvc3Qobm9kZVVybCkuc2VuZChwYXJhbXMucGF5bG9hZCk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgY29uc29sZS5kZWJ1ZyhlKTtcbiAgICB9XG4gICAgdGhyb3cgbmV3IEVycm9yKGBVbmFibGUgdG8gY2FsbCBlbmRwb2ludDogJy8nIGZyb20gbm9kZTogJHtub2RlVXJsfWApO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIGdldEJsb2NraGFzaChhcGlLZXk/OiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5nZXREYXRhRnJvbU5vZGUoXG4gICAgICB7XG4gICAgICAgIHBheWxvYWQ6IHtcbiAgICAgICAgICBpZDogJzEnLFxuICAgICAgICAgIGpzb25ycGM6ICcyLjAnLFxuICAgICAgICAgIG1ldGhvZDogJ2dldExhdGVzdEJsb2NraGFzaCcsXG4gICAgICAgICAgcGFyYW1zOiBbXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIGNvbW1pdG1lbnQ6ICdmaW5hbGl6ZWQnLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICBdLFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICAgIGFwaUtleVxuICAgICk7XG4gICAgaWYgKHJlc3BvbnNlLnN0YXR1cyAhPT0gMjAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0FjY291bnQgbm90IGZvdW5kJyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlc3BvbnNlLmJvZHkucmVzdWx0LnZhbHVlLmJsb2NraGFzaDtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBnZXRGZWVGb3JNZXNzYWdlKG1lc3NhZ2U6IHN0cmluZywgYXBpS2V5Pzogc3RyaW5nKTogUHJvbWlzZTxudW1iZXI+IHtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMuZ2V0RGF0YUZyb21Ob2RlKFxuICAgICAge1xuICAgICAgICBwYXlsb2FkOiB7XG4gICAgICAgICAgaWQ6ICcxJyxcbiAgICAgICAgICBqc29ucnBjOiAnMi4wJyxcbiAgICAgICAgICBtZXRob2Q6ICdnZXRGZWVGb3JNZXNzYWdlJyxcbiAgICAgICAgICBwYXJhbXM6IFtcbiAgICAgICAgICAgIG1lc3NhZ2UsXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIGNvbW1pdG1lbnQ6ICdmaW5hbGl6ZWQnLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICBdLFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICAgIGFwaUtleVxuICAgICk7XG4gICAgaWYgKHJlc3BvbnNlLnN0YXR1cyAhPT0gMjAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0FjY291bnQgbm90IGZvdW5kJyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlc3BvbnNlLmJvZHkucmVzdWx0LnZhbHVlO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIGdldFJlbnRFeGVtcHRBbW91bnQoYXBpS2V5Pzogc3RyaW5nKTogUHJvbWlzZTxudW1iZXI+IHtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMuZ2V0RGF0YUZyb21Ob2RlKFxuICAgICAge1xuICAgICAgICBwYXlsb2FkOiB7XG4gICAgICAgICAganNvbnJwYzogJzIuMCcsXG4gICAgICAgICAgaWQ6ICcxJyxcbiAgICAgICAgICBtZXRob2Q6ICdnZXRNaW5pbXVtQmFsYW5jZUZvclJlbnRFeGVtcHRpb24nLFxuICAgICAgICAgIHBhcmFtczogWzE2NV0sXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgICAgYXBpS2V5XG4gICAgKTtcbiAgICBpZiAocmVzcG9uc2Uuc3RhdHVzICE9PSAyMDAgfHwgcmVzcG9uc2UuZXJyb3IpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihKU09OLnN0cmluZ2lmeShyZXNwb25zZS5lcnJvcikpO1xuICAgIH1cblxuICAgIHJldHVybiByZXNwb25zZS5ib2R5LnJlc3VsdDtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBnZXRBY2NvdW50QmFsYW5jZShwdWJLZXk6IHN0cmluZywgYXBpS2V5Pzogc3RyaW5nKTogUHJvbWlzZTxudW1iZXI+IHtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMuZ2V0RGF0YUZyb21Ob2RlKFxuICAgICAge1xuICAgICAgICBwYXlsb2FkOiB7XG4gICAgICAgICAgaWQ6ICcxJyxcbiAgICAgICAgICBqc29ucnBjOiAnMi4wJyxcbiAgICAgICAgICBtZXRob2Q6ICdnZXRCYWxhbmNlJyxcbiAgICAgICAgICBwYXJhbXM6IFtwdWJLZXldLFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICAgIGFwaUtleVxuICAgICk7XG4gICAgaWYgKHJlc3BvbnNlLnN0YXR1cyAhPT0gMjAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0FjY291bnQgbm90IGZvdW5kJyk7XG4gICAgfVxuICAgIHJldHVybiByZXNwb25zZS5ib2R5LnJlc3VsdC52YWx1ZTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBnZXRBY2NvdW50SW5mbyhwdWJLZXk6IHN0cmluZywgYXBpS2V5Pzogc3RyaW5nKTogUHJvbWlzZTxTb2xEdXJhYmxlTm9uY2VGcm9tTm9kZT4ge1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5nZXREYXRhRnJvbU5vZGUoXG4gICAgICB7XG4gICAgICAgIHBheWxvYWQ6IHtcbiAgICAgICAgICBpZDogJzEnLFxuICAgICAgICAgIGpzb25ycGM6ICcyLjAnLFxuICAgICAgICAgIG1ldGhvZDogJ2dldEFjY291bnRJbmZvJyxcbiAgICAgICAgICBwYXJhbXM6IFtcbiAgICAgICAgICAgIHB1YktleSxcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgZW5jb2Rpbmc6ICdqc29uUGFyc2VkJyxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgXSxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgICBhcGlLZXlcbiAgICApO1xuICAgIGlmIChyZXNwb25zZS5zdGF0dXMgIT09IDIwMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdBY2NvdW50IG5vdCBmb3VuZCcpO1xuICAgIH1cbiAgICByZXR1cm4ge1xuICAgICAgYXV0aG9yaXR5OiByZXNwb25zZS5ib2R5LnJlc3VsdC52YWx1ZS5kYXRhLnBhcnNlZC5pbmZvLmF1dGhvcml0eSxcbiAgICAgIGJsb2NraGFzaDogcmVzcG9uc2UuYm9keS5yZXN1bHQudmFsdWUuZGF0YS5wYXJzZWQuaW5mby5ibG9ja2hhc2gsXG4gICAgfTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBnZXRUb2tlbkFjY291bnRzQnlPd25lcihwdWJLZXkgPSAnJywgcHJvZ3JhbUlkID0gJycsIGFwaUtleT86IHN0cmluZyk6IFByb21pc2U8W10gfCBUb2tlbkFjY291bnRbXT4ge1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5nZXREYXRhRnJvbU5vZGUoXG4gICAgICB7XG4gICAgICAgIHBheWxvYWQ6IHtcbiAgICAgICAgICBpZDogJzEnLFxuICAgICAgICAgIGpzb25ycGM6ICcyLjAnLFxuICAgICAgICAgIG1ldGhvZDogJ2dldFRva2VuQWNjb3VudHNCeU93bmVyJyxcbiAgICAgICAgICBwYXJhbXM6IFtcbiAgICAgICAgICAgIHB1YktleSxcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgcHJvZ3JhbUlkOlxuICAgICAgICAgICAgICAgIHByb2dyYW1JZC50b1N0cmluZygpLnRvTG93ZXJDYXNlKCkgPT09IFRPS0VOXzIwMjJfUFJPR1JBTV9JRC50b1N0cmluZygpLnRvTG93ZXJDYXNlKClcbiAgICAgICAgICAgICAgICAgID8gVE9LRU5fMjAyMl9QUk9HUkFNX0lELnRvU3RyaW5nKClcbiAgICAgICAgICAgICAgICAgIDogVE9LRU5fUFJPR1JBTV9JRC50b1N0cmluZygpLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgZW5jb2Rpbmc6ICdqc29uUGFyc2VkJyxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgXSxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgICBhcGlLZXlcbiAgICApO1xuICAgIGlmIChyZXNwb25zZS5zdGF0dXMgIT09IDIwMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdBY2NvdW50IG5vdCBmb3VuZCcpO1xuICAgIH1cblxuICAgIGlmIChyZXNwb25zZS5ib2R5LnJlc3VsdC52YWx1ZS5sZW5ndGggIT09IDApIHtcbiAgICAgIGNvbnN0IHRva2VuQWNjb3VudHM6IFRva2VuQWNjb3VudFtdID0gW107XG4gICAgICBmb3IgKGNvbnN0IHRva2VuQWNjb3VudCBvZiByZXNwb25zZS5ib2R5LnJlc3VsdC52YWx1ZSkge1xuICAgICAgICB0b2tlbkFjY291bnRzLnB1c2goeyBpbmZvOiB0b2tlbkFjY291bnQuYWNjb3VudC5kYXRhLnBhcnNlZC5pbmZvLCBwdWJLZXk6IHRva2VuQWNjb3VudC5wdWJLZXkgfSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gdG9rZW5BY2NvdW50cztcbiAgICB9XG5cbiAgICByZXR1cm4gW107XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgZ2V0VG9rZW5BY2NvdW50SW5mbyhwdWJLZXk6IHN0cmluZywgYXBpS2V5Pzogc3RyaW5nKTogUHJvbWlzZTxUb2tlbkFjY291bnQ+IHtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMuZ2V0RGF0YUZyb21Ob2RlKFxuICAgICAge1xuICAgICAgICBwYXlsb2FkOiB7XG4gICAgICAgICAgaWQ6ICcxJyxcbiAgICAgICAgICBqc29ucnBjOiAnMi4wJyxcbiAgICAgICAgICBtZXRob2Q6ICdnZXRBY2NvdW50SW5mbycsXG4gICAgICAgICAgcGFyYW1zOiBbXG4gICAgICAgICAgICBwdWJLZXksXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIGVuY29kaW5nOiAnanNvblBhcnNlZCcsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIF0sXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgICAgYXBpS2V5XG4gICAgKTtcbiAgICBpZiAocmVzcG9uc2Uuc3RhdHVzICE9PSAyMDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQWNjb3VudCBub3QgZm91bmQnKTtcbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgIHB1YktleTogcHViS2V5LFxuICAgICAgaW5mbzogcmVzcG9uc2UuYm9keS5yZXN1bHQudmFsdWUuZGF0YS5wYXJzZWQuaW5mbyxcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIEJ1aWxkIGEgbWluaW1hbCBgQ29ubmVjdGlvbmAtbGlrZSBzaGltIGJhY2tlZCBieSB7QGxpbmsgZ2V0RGF0YUZyb21Ob2RlfS5cbiAgICpcbiAgICogYEBzb2xhbmEvc3BsLXRva2VuYCdzIHRyYW5zZmVyLWhvb2sgcmVzb2x1dGlvbiBoZWxwZXJzIG9ubHkgcmVxdWlyZVxuICAgKiBgZ2V0QWNjb3VudEluZm8ocHVibGljS2V5KWAgcmV0dXJuaW5nIGFuIGBBY2NvdW50SW5mbzxCdWZmZXI+YC4gUmF0aGVyIHRoYW5cbiAgICogb3BlbiBhIHNlY29uZCBSUEMgdHJhbnNwb3J0LCB3ZSByZXVzZSB0aGUgZXhpc3RpbmcgcHVibGljLW5vZGUgcmVxdWVzdCBwYXRoXG4gICAqIGFzIHRoZSB7QGxpbmsgU29sQWNjb3VudEZldGNoZXJ9IChiYXNlNjQtZGVjb2RpbmcgdGhlIEpTT04tUlBDIHJlc3BvbnNlIGhlcmUpLFxuICAgKiB0aGVuIGFkYXB0IGl0IHZpYSB7QGxpbmsgYnVpbGRTb2xBY2NvdW50Q29ubmVjdGlvbn0uXG4gICAqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbYXBpS2V5XSAtIG9wdGlvbmFsIEFsY2hlbXkgQVBJIGtleSB0aHJlYWRlZCB0byB0aGUgbm9kZSBVUkxcbiAgICogQHJldHVybnMge0Nvbm5lY3Rpb259IGEgc2hpbSBleHBvc2luZyBgZ2V0QWNjb3VudEluZm9gLCBjYXN0IHRvIGBDb25uZWN0aW9uYFxuICAgKi9cbiAgcHJvdGVjdGVkIGJ1aWxkVHJhbnNmZXJIb29rQ29ubmVjdGlvbihhcGlLZXk/OiBzdHJpbmcpOiBDb25uZWN0aW9uIHtcbiAgICBjb25zdCBmZXRjaDogU29sQWNjb3VudEZldGNoZXIgPSBhc3luYyAoYWRkcmVzczogc3RyaW5nKTogUHJvbWlzZTxBY2NvdW50SW5mbzxCdWZmZXI+IHwgbnVsbD4gPT4ge1xuICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLmdldERhdGFGcm9tTm9kZShcbiAgICAgICAge1xuICAgICAgICAgIHBheWxvYWQ6IHtcbiAgICAgICAgICAgIGlkOiAnMScsXG4gICAgICAgICAgICBqc29ucnBjOiAnMi4wJyxcbiAgICAgICAgICAgIG1ldGhvZDogJ2dldEFjY291bnRJbmZvJyxcbiAgICAgICAgICAgIHBhcmFtczogW2FkZHJlc3MsIHsgZW5jb2Rpbmc6ICdiYXNlNjQnIH1dLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICAgIGFwaUtleVxuICAgICAgKTtcbiAgICAgIGlmIChyZXNwb25zZS5zdGF0dXMgIT09IDIwMCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0FjY291bnQgbm90IGZvdW5kJyk7XG4gICAgICB9XG4gICAgICBjb25zdCB2YWx1ZSA9IHJlc3BvbnNlLmJvZHk/LnJlc3VsdD8udmFsdWU7XG4gICAgICBpZiAoIXZhbHVlKSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgfVxuICAgICAgY29uc3QgW2RhdGFdID0gdmFsdWUuZGF0YSBhcyBbc3RyaW5nLCBzdHJpbmddO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgZXhlY3V0YWJsZTogdmFsdWUuZXhlY3V0YWJsZSxcbiAgICAgICAgb3duZXI6IG5ldyBTb2xQdWJsaWNLZXkodmFsdWUub3duZXIpLFxuICAgICAgICBsYW1wb3J0czogdmFsdWUubGFtcG9ydHMsXG4gICAgICAgIGRhdGE6IEJ1ZmZlci5mcm9tKGRhdGEsICdiYXNlNjQnKSxcbiAgICAgICAgcmVudEVwb2NoOiB2YWx1ZS5yZW50RXBvY2gsXG4gICAgICB9O1xuICAgIH07XG4gICAgcmV0dXJuIGJ1aWxkU29sQWNjb3VudENvbm5lY3Rpb24oZmV0Y2gpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlc29sdmUgdGhlIFRva2VuLTIwMjIgVHJhbnNmZXIgSG9vayBleHRyYSBhY2NvdW50cyBmb3IgYSBzcGVjaWZpYyB0cmFuc2Zlci5cbiAgICpcbiAgICogVGhpbiB3cmFwcGVyIGFyb3VuZCB7QGxpbmsgcmVzb2x2ZVRyYW5zZmVySG9va0FjY291bnRzTGlifTogYnVpbGRzIGEgY29ubmVjdGlvblxuICAgKiBvdmVyIHRoaXMgY29pbidzIG5vZGUgdHJhbnNwb3J0IGFuZCBkZWxlZ2F0ZXMgdGhlIHJlc29sdXRpb24uIFNlZSB0aGUgc3RhbmRhbG9uZVxuICAgKiBmdW5jdGlvbiBpbiBgLi9saWIvdG9rZW4yMDIyUmVzb2x2ZWAgZm9yIHRoZSBmdWxsIGJlaGF2aW9yLlxuICAgKlxuICAgKiBCdWlsZGVycyByZW1haW4gb2ZmbGluZSwgc28gdGhlIGNhbGxlciAoZS5nLiB3YWxsZXQtcGxhdGZvcm0pIGlzIHJlc3BvbnNpYmxlXG4gICAqIGZvciBpbnZva2luZyB0aGlzIGFuZCB0aHJlYWRpbmcgdGhlIHJlc3VsdCBpbnRvIHRoZSB0b2tlbi10cmFuc2ZlciBidWlsZGVyIHZpYVxuICAgKiBgdHJhbnNmZXJIb29rQWNjb3VudHMoLi4uKWAuIFdoZW4gdGhlIG1pbnQgaGFzIG5vIFRyYW5zZmVyIEhvb2ssIHRoaXMgcmV0dXJuc1xuICAgKiBhbiBlbXB0eSBhcnJheSBhbmQgY2FsbGVycyBjYW4gb21pdCB0aGUgcGFyYW0uXG4gICAqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBtaW50IC0gdGhlIFRva2VuLTIwMjIgbWludCBhZGRyZXNzXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBzb3VyY2UgLSB0aGUgc291cmNlIHRva2VuIGFjY291bnQgKHNlbmRlciBBVEEpXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBkZXN0aW5hdGlvbiAtIHRoZSBkZXN0aW5hdGlvbiB0b2tlbiBhY2NvdW50IChyZWNpcGllbnQgQVRBKVxuICAgKiBAcGFyYW0ge3N0cmluZ30gb3duZXIgLSB0aGUgc291cmNlIGFjY291bnQgb3duZXIgLyB0cmFuc2ZlciBhdXRob3JpdHlcbiAgICogQHBhcmFtIHtzdHJpbmd9IGFtb3VudCAtIHRoZSByYXcgdHJhbnNmZXIgYW1vdW50IGluIGJhc2UgdW5pdHNcbiAgICogQHBhcmFtIHtzdHJpbmd9IFthcGlLZXldIC0gb3B0aW9uYWwgQWxjaGVteSBBUEkga2V5IHRocmVhZGVkIHRvIHRoZSBub2RlIFVSTFxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxFeHRyYUFjY291bnRNZXRhW10+fSBvcmRlcmVkIGV4dHJhIGFjY291bnQgbWV0YXMsIG9yIFtdIHdoZW4gbm8gaG9va1xuICAgKi9cbiAgYXN5bmMgcmVzb2x2ZVRyYW5zZmVySG9va0FjY291bnRzKFxuICAgIG1pbnQ6IHN0cmluZyxcbiAgICBzb3VyY2U6IHN0cmluZyxcbiAgICBkZXN0aW5hdGlvbjogc3RyaW5nLFxuICAgIG93bmVyOiBzdHJpbmcsXG4gICAgYW1vdW50OiBzdHJpbmcsXG4gICAgYXBpS2V5Pzogc3RyaW5nXG4gICk6IFByb21pc2U8RXh0cmFBY2NvdW50TWV0YVtdPiB7XG4gICAgY29uc3QgY29ubmVjdGlvbiA9IHRoaXMuYnVpbGRUcmFuc2Zlckhvb2tDb25uZWN0aW9uKGFwaUtleSk7XG4gICAgcmV0dXJuIHJlc29sdmVUcmFuc2Zlckhvb2tBY2NvdW50c0xpYihjb25uZWN0aW9uLCB7IG1pbnQsIHNvdXJjZSwgZGVzdGluYXRpb24sIG93bmVyLCBhbW91bnQgfSk7XG4gIH1cblxuICAvKipcbiAgICogUmVzb2x2ZSB0aGUgc1JGQy0zNyBUb2tlbiBBQ0wgcGVybWlzc2lvbmxlc3MtdGhhdyBkZXBlbmRlbmNpZXMgZm9yIGEgdG9rZW4gYWNjb3VudC5cbiAgICpcbiAgICogVGhpbiB3cmFwcGVyIGFyb3VuZCB7QGxpbmsgcmVzb2x2ZVBlcm1pc3Npb25sZXNzVGhhd0xpYn06IGJ1aWxkcyBhIGNvbm5lY3Rpb25cbiAgICogb3ZlciB0aGlzIGNvaW4ncyBub2RlIHRyYW5zcG9ydCBhbmQgZGVsZWdhdGVzIHRoZSByZXNvbHV0aW9uLiBTZWUgdGhlIHN0YW5kYWxvbmVcbiAgICogZnVuY3Rpb24gaW4gYC4vbGliL3Rva2VuMjAyMlJlc29sdmVgIGZvciB0aGUgZnVsbCBiZWhhdmlvci5cbiAgICpcbiAgICogQnVpbGRlcnMgcmVtYWluIG9mZmxpbmUsIHNvIHRoZSBjYWxsZXIgKGUuZy4gd2FsbGV0LXBsYXRmb3JtKSBpbnZva2VzIHRoaXMgYW5kIHRocmVhZHMgdGhlXG4gICAqIHJlc3VsdCBpbnRvIHRoZSB0b2tlbi10cmFuc2ZlciBidWlsZGVyIHZpYSBgcGVybWlzc2lvbmxlc3NUaGF3KC4uLilgLCB3aGljaCBidW5kbGVzIHRoZSB0aGF3XG4gICAqIGF0b21pY2FsbHkgd2l0aCBhbnkgQVRBIGNyZWF0aW9uIGFuZCB0aGUgdHJhbnNmZXIuIFdoZW4gdGhlIG1pbnQgaXMgbm90IGEgVG9rZW4gQUNMIG1pbnQsIG9yXG4gICAqIHBlcm1pc3Npb25sZXNzIHRoYXcgaXMgZGlzYWJsZWQsIHRoaXMgcmV0dXJucyBgeyBhcHBsaWNhYmxlOiBmYWxzZSB9YCBhbmQgY2FsbGVycyBza2lwIHRoZSB0aGF3LlxuICAgKlxuICAgKiBAcGFyYW0ge3N0cmluZ30gbWludCAtIHRoZSBUb2tlbi0yMDIyIG1pbnQgYWRkcmVzc1xuICAgKiBAcGFyYW0ge3N0cmluZ30gdG9rZW5BY2NvdW50IC0gdGhlIHRva2VuIGFjY291bnQgKEFUQSkgdG8gdGhhd1xuICAgKiBAcGFyYW0ge3N0cmluZ30gdG9rZW5BY2NvdW50T3duZXIgLSB0aGUgb3duZXIgb2YgdGhlIHRva2VuIGFjY291bnRcbiAgICogQHBhcmFtIHtzdHJpbmd9IGF1dGhvcml0eSAtIHRoZSBzaWduZXIgaW52b2tpbmcgdGhlIHRoYXcgKGZlZSBwYXllciAvIGF1dGhvcml0eSlcbiAgICogQHBhcmFtIHtzdHJpbmd9IFthcGlLZXldIC0gb3B0aW9uYWwgQWxjaGVteSBBUEkga2V5IHRocmVhZGVkIHRvIHRoZSBub2RlIFVSTFxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxSZXNvbHZlUGVybWlzc2lvbmxlc3NUaGF3UmVzdWx0Pn0gdGhlIHJlc29sdmVkIHRoYXcgcGFyYW1zLCBvciBgeyBhcHBsaWNhYmxlOiBmYWxzZSB9YFxuICAgKi9cbiAgYXN5bmMgcmVzb2x2ZVBlcm1pc3Npb25sZXNzVGhhdyhcbiAgICBtaW50OiBzdHJpbmcsXG4gICAgdG9rZW5BY2NvdW50OiBzdHJpbmcsXG4gICAgdG9rZW5BY2NvdW50T3duZXI6IHN0cmluZyxcbiAgICBhdXRob3JpdHk6IHN0cmluZyxcbiAgICBhcGlLZXk/OiBzdHJpbmdcbiAgKTogUHJvbWlzZTxSZXNvbHZlUGVybWlzc2lvbmxlc3NUaGF3UmVzdWx0PiB7XG4gICAgY29uc3QgY29ubmVjdGlvbiA9IHRoaXMuYnVpbGRUcmFuc2Zlckhvb2tDb25uZWN0aW9uKGFwaUtleSk7XG4gICAgcmV0dXJuIHJlc29sdmVQZXJtaXNzaW9ubGVzc1RoYXdMaWIoY29ubmVjdGlvbiwgeyBtaW50LCB0b2tlbkFjY291bnQsIHRva2VuQWNjb3VudE93bmVyLCBhdXRob3JpdHkgfSk7XG4gIH1cblxuICAvKiogaW5oZXJpdGVkIGRvYyAqL1xuICBhc3luYyBjcmVhdGVCcm9hZGNhc3RhYmxlU3dlZXBUcmFuc2FjdGlvbihwYXJhbXM6IE1QQ1N3ZWVwUmVjb3ZlcnlPcHRpb25zKTogUHJvbWlzZTxNUENUeHM+IHtcbiAgICBpZiAoIXBhcmFtcy5zaWduYXR1cmVTaGFyZXMpIHtcbiAgICAgICgnTWlzc2luZyB0cmFuc2FjdGlvbihzKScpO1xuICAgIH1cbiAgICBjb25zdCByZXEgPSBwYXJhbXMuc2lnbmF0dXJlU2hhcmVzO1xuICAgIGNvbnN0IGJyb2FkY2FzdGFibGVUcmFuc2FjdGlvbnM6IE1QQ1R4W10gPSBbXTtcbiAgICBsZXQgbGFzdFNjYW5JbmRleCA9IDA7XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHJlcS5sZW5ndGg7IGkrKykge1xuICAgICAgY29uc3QgTVBDID0gYXdhaXQgRUREU0FNZXRob2RzLmdldEluaXRpYWxpemVkTXBjSW5zdGFuY2UoKTtcbiAgICAgIGNvbnN0IHRyYW5zYWN0aW9uID0gcmVxW2ldLnR4UmVxdWVzdC50cmFuc2FjdGlvbnNbMF0udW5zaWduZWRUeDtcbiAgICAgIGlmICghcmVxW2ldLm92YyB8fCAhcmVxW2ldLm92Y1swXS5lZGRzYVNpZ25hdHVyZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ01pc3Npbmcgc2lnbmF0dXJlKHMpJyk7XG4gICAgICB9XG4gICAgICBjb25zdCBzaWduYXR1cmUgPSByZXFbaV0ub3ZjWzBdLmVkZHNhU2lnbmF0dXJlO1xuICAgICAgaWYgKCF0cmFuc2FjdGlvbi5zaWduYWJsZUhleCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ01pc3Npbmcgc2lnbmFibGUgaGV4Jyk7XG4gICAgICB9XG4gICAgICBjb25zdCBtZXNzYWdlQnVmZmVyID0gQnVmZmVyLmZyb20odHJhbnNhY3Rpb24uc2lnbmFibGVIZXghLCAnaGV4Jyk7XG4gICAgICBjb25zdCByZXN1bHQgPSBNUEMudmVyaWZ5KG1lc3NhZ2VCdWZmZXIsIHNpZ25hdHVyZSk7XG4gICAgICBpZiAoIXJlc3VsdCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgc2lnbmF0dXJlJyk7XG4gICAgICB9XG4gICAgICBjb25zdCBzaWduYXR1cmVIZXggPSBCdWZmZXIuY29uY2F0KFtCdWZmZXIuZnJvbShzaWduYXR1cmUuUiwgJ2hleCcpLCBCdWZmZXIuZnJvbShzaWduYXR1cmUuc2lnbWEsICdoZXgnKV0pO1xuICAgICAgY29uc3QgdHhCdWlsZGVyID0gdGhpcy5nZXRCdWlsZGVyKCkuZnJvbSh0cmFuc2FjdGlvbi5zZXJpYWxpemVkVHggYXMgc3RyaW5nKTtcbiAgICAgIGlmICghdHJhbnNhY3Rpb24uY29pblNwZWNpZmljPy5jb21tb25LZXljaGFpbikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ01pc3NpbmcgY29tbW9uIGtleWNoYWluJyk7XG4gICAgICB9XG4gICAgICBjb25zdCBjb21tb25LZXljaGFpbiA9IHRyYW5zYWN0aW9uLmNvaW5TcGVjaWZpYyEuY29tbW9uS2V5Y2hhaW4hIGFzIHN0cmluZztcbiAgICAgIGlmICghdHJhbnNhY3Rpb24uZGVyaXZhdGlvblBhdGgpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdNaXNzaW5nIGRlcml2YXRpb24gcGF0aCcpO1xuICAgICAgfVxuICAgICAgY29uc3QgZGVyaXZhdGlvblBhdGggPSB0cmFuc2FjdGlvbi5kZXJpdmF0aW9uUGF0aCBhcyBzdHJpbmc7XG4gICAgICBjb25zdCBhY2NvdW50SWQgPSBNUEMuZGVyaXZlVW5oYXJkZW5lZChjb21tb25LZXljaGFpbiwgZGVyaXZhdGlvblBhdGgpLnNsaWNlKDAsIDY0KTtcbiAgICAgIGNvbnN0IGJzNThFbmNvZGVkUHVibGljS2V5ID0gbmV3IFNvbEtleVBhaXIoeyBwdWI6IGFjY291bnRJZCB9KS5nZXRBZGRyZXNzKCk7XG5cbiAgICAgIC8vIGFkZCBjb21iaW5lZCBzaWduYXR1cmUgZnJvbSBvdmNcbiAgICAgIGNvbnN0IHB1YmxpY0tleU9iaiA9IHsgcHViOiBiczU4RW5jb2RlZFB1YmxpY0tleSB9O1xuICAgICAgdHhCdWlsZGVyLmFkZFNpZ25hdHVyZShwdWJsaWNLZXlPYmogYXMgUHVibGljS2V5LCBzaWduYXR1cmVIZXgpO1xuXG4gICAgICBjb25zdCBzaWduZWRUcmFuc2FjdGlvbiA9IGF3YWl0IHR4QnVpbGRlci5idWlsZCgpO1xuICAgICAgY29uc3Qgc2VyaWFsaXplZFR4ID0gc2lnbmVkVHJhbnNhY3Rpb24udG9Ccm9hZGNhc3RGb3JtYXQoKTtcblxuICAgICAgYnJvYWRjYXN0YWJsZVRyYW5zYWN0aW9ucy5wdXNoKHtcbiAgICAgICAgc2VyaWFsaXplZFR4OiBzZXJpYWxpemVkVHgsXG4gICAgICAgIHNjYW5JbmRleDogdHJhbnNhY3Rpb24uc2NhbkluZGV4LFxuICAgICAgfSk7XG5cbiAgICAgIGlmIChpID09PSByZXEubGVuZ3RoIC0gMSAmJiB0cmFuc2FjdGlvbi5jb2luU3BlY2lmaWMhLmxhc3RTY2FuSW5kZXgpIHtcbiAgICAgICAgbGFzdFNjYW5JbmRleCA9IHRyYW5zYWN0aW9uLmNvaW5TcGVjaWZpYyEubGFzdFNjYW5JbmRleCBhcyBudW1iZXI7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHsgdHJhbnNhY3Rpb25zOiBicm9hZGNhc3RhYmxlVHJhbnNhY3Rpb25zLCBsYXN0U2NhbkluZGV4IH07XG4gIH1cblxuICAvKipcbiAgICogQnVpbGRzIGEgZnVuZHMgcmVjb3ZlcnkgdHJhbnNhY3Rpb24gd2l0aG91dCBCaXRHb1xuICAgKiBAcGFyYW0ge1NvbFJlY292ZXJ5T3B0aW9uc30gcGFyYW1zIHBhcmFtZXRlcnMgbmVlZGVkIHRvIGNvbnN0cnVjdCBhbmRcbiAgICogKG1heWJlKSBzaWduIHRoZSB0cmFuc2FjdGlvblxuICAgKlxuICAgKiBAcmV0dXJucyB7TVBDVHggfCBNUENTd2VlcFR4c30gdGhlIHNlcmlhbGl6ZWQgdHJhbnNhY3Rpb24gaGV4IHN0cmluZyBhbmQgaW5kZXhcbiAgICogb2YgdGhlIGFkZHJlc3MgYmVpbmcgc3dlcHRcbiAgICovXG4gIGFzeW5jIHJlY292ZXIocGFyYW1zOiBTb2xSZWNvdmVyeU9wdGlvbnMpOiBQcm9taXNlPE1QQ1R4IHwgTVBDU3dlZXBUeHM+IHtcbiAgICBpZiAoIXBhcmFtcy5iaXRnb0tleSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdtaXNzaW5nIGJpdGdvS2V5Jyk7XG4gICAgfVxuXG4gICAgaWYgKCFwYXJhbXMucmVjb3ZlcnlEZXN0aW5hdGlvbiB8fCAhdGhpcy5pc1ZhbGlkQWRkcmVzcyhwYXJhbXMucmVjb3ZlcnlEZXN0aW5hdGlvbikpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignaW52YWxpZCByZWNvdmVyeURlc3RpbmF0aW9uJyk7XG4gICAgfVxuXG4gICAgY29uc3QgYml0Z29LZXkgPSBwYXJhbXMuYml0Z29LZXkucmVwbGFjZSgvXFxzL2csICcnKTtcbiAgICBjb25zdCBpc1Vuc2lnbmVkU3dlZXAgPSAhcGFyYW1zLndhbGxldFBhc3NwaHJhc2U7XG5cbiAgICAvLyBWYWxpZGF0ZSBzaWduaW5nIGtleXMgYW5kIGRldGVjdCBNUEN2MiBmb3JtYXQgZWFybHkgZm9yIHNpZ25lZCByZWNvdmVyeS5cbiAgICAvLyBXaGVuIG11bHRpc2lnVHlwZVZlcnNpb24gaXMgcHJlLXJlc29sdmVkIGJ5IHRoZSBjYWxsZXIgKGUuZy4gcmVjb3ZlckNvbnNvbGlkYXRpb25zKSxcbiAgICAvLyBza2lwIGtleWNhcmQgZGVjcnlwdGlvbiB0byBhdm9pZCByZWR1bmRhbnQgd29yayBvbiBlYWNoIGxvb3AgaXRlcmF0aW9uLlxuICAgIGNvbnN0IGlzTXBjVjIgPVxuICAgICAgcGFyYW1zLm11bHRpc2lnVHlwZVZlcnNpb24gPT09ICdNUEN2MidcbiAgICAgICAgPyB0cnVlXG4gICAgICAgIDogYXdhaXQgdGhpcy5pc01wY3YyU2lnbmluZ01hdGVyaWFsKHBhcmFtcy51c2VyS2V5LCBwYXJhbXMuYmFja3VwS2V5LCBwYXJhbXMud2FsbGV0UGFzc3BocmFzZSk7XG5cbiAgICBsZXQgYmFsYW5jZSA9IDA7XG5cbiAgICBjb25zdCBpbmRleCA9IHBhcmFtcy5pbmRleCB8fCAwO1xuICAgIGNvbnN0IGN1cnJQYXRoID0gcGFyYW1zLnNlZWQgPyBnZXREZXJpdmF0aW9uUGF0aChwYXJhbXMuc2VlZCkgKyBgLyR7aW5kZXh9YCA6IGBtLyR7aW5kZXh9YDtcblxuICAgIGNvbnN0IE1QQyA9IGF3YWl0IEVERFNBTWV0aG9kcy5nZXRJbml0aWFsaXplZE1wY0luc3RhbmNlKCk7XG4gICAgY29uc3QgYWNjb3VudElkID0gTVBDLmRlcml2ZVVuaGFyZGVuZWQoYml0Z29LZXksIGN1cnJQYXRoKS5zbGljZSgwLCA2NCk7XG4gICAgY29uc3QgYnM1OEVuY29kZWRQdWJsaWNLZXkgPSBuZXcgU29sS2V5UGFpcih7IHB1YjogYWNjb3VudElkIH0pLmdldEFkZHJlc3MoKTtcblxuICAgIGJhbGFuY2UgPSBhd2FpdCB0aGlzLmdldEFjY291bnRCYWxhbmNlKGJzNThFbmNvZGVkUHVibGljS2V5LCBwYXJhbXMuYXBpS2V5KTtcblxuICAgIGNvbnN0IGZhY3RvcnkgPSB0aGlzLmdldEJ1aWxkZXIoKTtcbiAgICBjb25zdCB3YWxsZXRDb2luID0gdGhpcy5nZXRDaGFpbigpO1xuXG4gICAgbGV0IHR4QnVpbGRlcjtcbiAgICBsZXQgYmxvY2toYXNoID0gYXdhaXQgdGhpcy5nZXRCbG9ja2hhc2gocGFyYW1zLmFwaUtleSk7XG4gICAgbGV0IHJlbnRFeGVtcHRBbW91bnQ7XG4gICAgbGV0IGF1dGhvcml0eSA9ICcnO1xuICAgIGxldCB0b3RhbEZlZSA9IG5ldyBCaWdOdW1iZXIoMCk7XG4gICAgbGV0IHRvdGFsRmVlRm9yVG9rZW5SZWNvdmVyeSA9IG5ldyBCaWdOdW1iZXIoMCk7XG5cbiAgICAvLyBjaGVjayBmb3IgcG9zc2libGUgdG9rZW4gcmVjb3ZlcnksIHJlY292ZXIgdGhlIHRva2VuIHByb3ZpZGUgYnkgdXNlclxuICAgIGlmIChwYXJhbXMudG9rZW5Db250cmFjdEFkZHJlc3MpIHtcbiAgICAgIGxldCBpc1Vuc3VwcG9ydGVkVG9rZW4gPSBmYWxzZTtcbiAgICAgIGNvbnN0IHRva2VuQWNjb3VudHMgPSBhd2FpdCB0aGlzLmdldFRva2VuQWNjb3VudHNCeU93bmVyKGJzNThFbmNvZGVkUHVibGljS2V5LCBwYXJhbXMucHJvZ3JhbUlkLCBwYXJhbXMuYXBpS2V5KTtcbiAgICAgIGlmICh0b2tlbkFjY291bnRzLmxlbmd0aCAhPT0gMCkge1xuICAgICAgICAvLyB0aGVyZSBleGlzdHMgdG9rZW4gYWNjb3VudHMgb24gdGhlIGdpdmVuIGFkZHJlc3MsIGJ1dCBuZWVkIHRvIGNoZWNrIGNlcnRhaW4gY29uZGl0aW9uczpcbiAgICAgICAgLy8gMS4gaWYgdGhlcmUgaXMgYSByZWNvdmVyYWJsZSBiYWxhbmNlXG4gICAgICAgIC8vIDIuIGlmIHRoZSB0b2tlbiBpcyBzdXBwb3J0ZWQgYnkgYml0Z29cbiAgICAgICAgY29uc3QgcmVjb3ZlcmVhYmxlVG9rZW5BY2NvdW50czogVG9rZW5BY2NvdW50W10gPSBbXTtcbiAgICAgICAgZm9yIChjb25zdCB0b2tlbkFjY291bnQgb2YgdG9rZW5BY2NvdW50cykge1xuICAgICAgICAgIGlmIChwYXJhbXMudG9rZW5Db250cmFjdEFkZHJlc3MgPT09IHRva2VuQWNjb3VudC5pbmZvLm1pbnQpIHtcbiAgICAgICAgICAgIGNvbnN0IHRva2VuQW1vdW50ID0gbmV3IEJpZ051bWJlcih0b2tlbkFjY291bnQuaW5mby50b2tlbkFtb3VudC5hbW91bnQpO1xuICAgICAgICAgICAgY29uc3QgbmV0d29yayA9IHRoaXMuZ2V0TmV0d29yaygpO1xuICAgICAgICAgICAgY29uc3QgdG9rZW4gPSBnZXRTb2xUb2tlbkZyb21BZGRyZXNzKHRva2VuQWNjb3VudC5pbmZvLm1pbnQsIG5ldHdvcmspOyAvLyB0b2RvKFdJTi01ODk0KSBmaXggZm9yIGFtc1xuXG4gICAgICAgICAgICBpZiAoIXRva2VuKSB7XG4gICAgICAgICAgICAgIGlzVW5zdXBwb3J0ZWRUb2tlbiA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodG9rZW5BbW91bnQuZ3QobmV3IEJpZ051bWJlcigwKSkpIHtcbiAgICAgICAgICAgICAgdG9rZW5BY2NvdW50LnRva2VuTmFtZSA9IHRva2VuPy5uYW1lIHx8ICdVbnN1cHBvcnRlZCBUb2tlbic7XG4gICAgICAgICAgICAgIHJlY292ZXJlYWJsZVRva2VuQWNjb3VudHMucHVzaCh0b2tlbkFjY291bnQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHJlY292ZXJlYWJsZVRva2VuQWNjb3VudHMubGVuZ3RoICE9PSAwKSB7XG4gICAgICAgICAgcmVudEV4ZW1wdEFtb3VudCA9IGF3YWl0IHRoaXMuZ2V0UmVudEV4ZW1wdEFtb3VudChwYXJhbXMuYXBpS2V5KTtcblxuICAgICAgICAgIHR4QnVpbGRlciA9IGZhY3RvcnlcbiAgICAgICAgICAgIC5nZXRUb2tlblRyYW5zZmVyQnVpbGRlcigpXG4gICAgICAgICAgICAubm9uY2UoYmxvY2toYXNoKVxuICAgICAgICAgICAgLnNlbmRlcihiczU4RW5jb2RlZFB1YmxpY0tleSlcbiAgICAgICAgICAgIC5hc3NvY2lhdGVkVG9rZW5BY2NvdW50UmVudChyZW50RXhlbXB0QW1vdW50LnRvU3RyaW5nKCkpXG4gICAgICAgICAgICAuZmVlUGF5ZXIoYnM1OEVuY29kZWRQdWJsaWNLZXkpO1xuXG4gICAgICAgICAgLy8gbmVlZCB0byBnZXQgYWxsIHRva2VuIGFjY291bnRzIG9mIHRoZSByZWNpcGllbnQgYWRkcmVzcyBhbmQgbmVlZCB0byBjcmVhdGUgdGhlbSBpZiB0aGV5IGRvIG5vdCBleGlzdFxuICAgICAgICAgIGNvbnN0IHJlY2lwaWVudFRva2VuQWNjb3VudHMgPSBhd2FpdCB0aGlzLmdldFRva2VuQWNjb3VudHNCeU93bmVyKFxuICAgICAgICAgICAgcGFyYW1zLnJlY292ZXJ5RGVzdGluYXRpb24sXG4gICAgICAgICAgICBwYXJhbXMucHJvZ3JhbUlkLFxuICAgICAgICAgICAgcGFyYW1zLmFwaUtleVxuICAgICAgICAgICk7XG5cbiAgICAgICAgICBmb3IgKGNvbnN0IHRva2VuQWNjb3VudCBvZiByZWNvdmVyZWFibGVUb2tlbkFjY291bnRzKSB7XG4gICAgICAgICAgICBsZXQgcmVjaXBpZW50VG9rZW5BY2NvdW50RXhpc3RzID0gZmFsc2U7XG4gICAgICAgICAgICBmb3IgKGNvbnN0IHJlY2lwaWVudFRva2VuQWNjb3VudCBvZiByZWNpcGllbnRUb2tlbkFjY291bnRzIGFzIFRva2VuQWNjb3VudFtdKSB7XG4gICAgICAgICAgICAgIGlmIChyZWNpcGllbnRUb2tlbkFjY291bnQuaW5mby5taW50ID09PSB0b2tlbkFjY291bnQuaW5mby5taW50KSB7XG4gICAgICAgICAgICAgICAgcmVjaXBpZW50VG9rZW5BY2NvdW50RXhpc3RzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBjb25zdCByZWNpcGllbnRUb2tlbkFjY291bnQgPSBhd2FpdCBnZXRBc3NvY2lhdGVkVG9rZW5BY2NvdW50QWRkcmVzcyhcbiAgICAgICAgICAgICAgdG9rZW5BY2NvdW50LmluZm8ubWludCxcbiAgICAgICAgICAgICAgcGFyYW1zLnJlY292ZXJ5RGVzdGluYXRpb24sXG4gICAgICAgICAgICAgIGZhbHNlLFxuICAgICAgICAgICAgICBwYXJhbXMucHJvZ3JhbUlkPy50b1N0cmluZygpXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgY29uc3QgdG9rZW5OYW1lID0gdG9rZW5BY2NvdW50LnRva2VuTmFtZSBhcyBzdHJpbmc7XG4gICAgICAgICAgICBjb25zdCBzZW5kUGFyYW1zID0ge1xuICAgICAgICAgICAgICBhZGRyZXNzOiByZWNpcGllbnRUb2tlbkFjY291bnQsXG4gICAgICAgICAgICAgIGFtb3VudDogdG9rZW5BY2NvdW50LmluZm8udG9rZW5BbW91bnQuYW1vdW50LFxuICAgICAgICAgICAgICB0b2tlbk5hbWUsXG4gICAgICAgICAgICAgIC4uLihpc1Vuc3VwcG9ydGVkVG9rZW5cbiAgICAgICAgICAgICAgICA/IHtcbiAgICAgICAgICAgICAgICAgICAgdG9rZW5BZGRyZXNzOiB0b2tlbkFjY291bnQuaW5mby5taW50LFxuICAgICAgICAgICAgICAgICAgICBwcm9ncmFtSWQ6IHBhcmFtcy5wcm9ncmFtSWQ/LnRvU3RyaW5nKCksXG4gICAgICAgICAgICAgICAgICAgIGRlY2ltYWxQbGFjZXM6IHRva2VuQWNjb3VudC5pbmZvLnRva2VuQW1vdW50LmRlY2ltYWxzLFxuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIDoge30pLFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHR4QnVpbGRlci5zZW5kKHNlbmRQYXJhbXMpO1xuXG4gICAgICAgICAgICBpZiAoIXJlY2lwaWVudFRva2VuQWNjb3VudEV4aXN0cykge1xuICAgICAgICAgICAgICAvLyByZWNpcGllbnQgdG9rZW4gYWNjb3VudCBkb2VzIG5vdCBleGlzdCBmb3IgdG9rZW4gYW5kIG11c3QgYmUgY3JlYXRlZFxuICAgICAgICAgICAgICB0eEJ1aWxkZXIuY3JlYXRlQXNzb2NpYXRlZFRva2VuQWNjb3VudCh7XG4gICAgICAgICAgICAgICAgb3duZXJBZGRyZXNzOiBwYXJhbXMucmVjb3ZlcnlEZXN0aW5hdGlvbixcbiAgICAgICAgICAgICAgICB0b2tlbk5hbWU6IHRva2VuTmFtZSxcbiAgICAgICAgICAgICAgICAuLi4oaXNVbnN1cHBvcnRlZFRva2VuID8geyB0b2tlbkFkZHJlc3M6IHRva2VuQWNjb3VudC5pbmZvLm1pbnQgfSA6IHt9KSxcbiAgICAgICAgICAgICAgICBwcm9ncmFtSWQ6XG4gICAgICAgICAgICAgICAgICBwYXJhbXMucHJvZ3JhbUlkPy50b1N0cmluZygpLnRvTG93ZXJDYXNlKCkgPT09IFRPS0VOXzIwMjJfUFJPR1JBTV9JRC50b1N0cmluZygpLnRvTG93ZXJDYXNlKClcbiAgICAgICAgICAgICAgICAgICAgPyBUT0tFTl8yMDIyX1BST0dSQU1fSUQudG9TdHJpbmcoKVxuICAgICAgICAgICAgICAgICAgICA6IFRPS0VOX1BST0dSQU1fSUQudG9TdHJpbmcoKSxcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgIC8vIGFkZCByZW50IGV4ZW1wdCBhbW91bnQgdG8gdG90YWwgZmVlIGZvciBlYWNoIHRva2VuIGFjY291bnQgdGhhdCBoYXMgdG8gYmUgY3JlYXRlZFxuICAgICAgICAgICAgICB0b3RhbEZlZUZvclRva2VuUmVjb3ZlcnkgPSB0b3RhbEZlZUZvclRva2VuUmVjb3ZlcnkucGx1cyhyZW50RXhlbXB0QW1vdW50KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhyb3cgRXJyb3IoJ05vdCBlbm91Z2ggdG9rZW4gZnVuZHMgdG8gcmVjb3ZlcicpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyB0aGVyZSBhcmUgbm8gcmVjb3ZlcmFibGUgdG9rZW4gYWNjb3VudHMgLCBuZWVkIHRvIGNoZWNrIGlmIHRoZXJlIGFyZSB0b2tlbnMgdG8gcmVjb3ZlclxuICAgICAgICB0aHJvdyBFcnJvcignRGlkIG5vdCBmaW5kIHRva2VuIGFjY291bnQgdG8gcmVjb3ZlciB0b2tlbnMsIHBsZWFzZSBjaGVjayB0b2tlbiBhY2NvdW50Jyk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHR4QnVpbGRlciA9IGZhY3RvcnlcbiAgICAgICAgLmdldFRyYW5zZmVyQnVpbGRlcigpXG4gICAgICAgIC5ub25jZShibG9ja2hhc2gpXG4gICAgICAgIC5zZW5kZXIoYnM1OEVuY29kZWRQdWJsaWNLZXkpXG4gICAgICAgIC5zZW5kKHsgYWRkcmVzczogcGFyYW1zLnJlY292ZXJ5RGVzdGluYXRpb24sIGFtb3VudDogYmFsYW5jZS50b1N0cmluZygpIH0pXG4gICAgICAgIC5mZWVQYXllcihiczU4RW5jb2RlZFB1YmxpY0tleSk7XG4gICAgfVxuXG4gICAgaWYgKHBhcmFtcy5kdXJhYmxlTm9uY2UpIHtcbiAgICAgIGNvbnN0IGR1cmFibGVOb25jZUluZm8gPSBhd2FpdCB0aGlzLmdldEFjY291bnRJbmZvKHBhcmFtcy5kdXJhYmxlTm9uY2UucHVibGljS2V5LCBwYXJhbXMuYXBpS2V5KTtcbiAgICAgIGJsb2NraGFzaCA9IGR1cmFibGVOb25jZUluZm8uYmxvY2toYXNoO1xuICAgICAgYXV0aG9yaXR5ID0gZHVyYWJsZU5vbmNlSW5mby5hdXRob3JpdHk7XG5cbiAgICAgIHR4QnVpbGRlci5ub25jZShibG9ja2hhc2gsIHtcbiAgICAgICAgd2FsbGV0Tm9uY2VBZGRyZXNzOiBwYXJhbXMuZHVyYWJsZU5vbmNlLnB1YmxpY0tleSxcbiAgICAgICAgYXV0aFdhbGxldEFkZHJlc3M6IGF1dGhvcml0eSxcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8vIGJ1aWxkIHRoZSB0cmFuc2FjdGlvbiB3aXRob3V0IGZlZVxuICAgIGNvbnN0IHVuc2lnbmVkVHJhbnNhY3Rpb25XaXRob3V0RmVlID0gKGF3YWl0IHR4QnVpbGRlci5idWlsZCgpKSBhcyBUcmFuc2FjdGlvbjtcbiAgICBjb25zdCBzZXJpYWxpemVkTWVzc2FnZSA9IHVuc2lnbmVkVHJhbnNhY3Rpb25XaXRob3V0RmVlLnNvbFRyYW5zYWN0aW9uLnNlcmlhbGl6ZU1lc3NhZ2UoKS50b1N0cmluZygnYmFzZTY0Jyk7XG5cbiAgICBjb25zdCBiYXNlRmVlID0gYXdhaXQgdGhpcy5nZXRGZWVGb3JNZXNzYWdlKHNlcmlhbGl6ZWRNZXNzYWdlLCBwYXJhbXMuYXBpS2V5KTtcbiAgICBjb25zdCBmZWVQZXJTaWduYXR1cmUgPSBwYXJhbXMuZHVyYWJsZU5vbmNlID8gYmFzZUZlZSAvIDIgOiBiYXNlRmVlO1xuICAgIHRvdGFsRmVlID0gdG90YWxGZWUucGx1cyhuZXcgQmlnTnVtYmVyKGJhc2VGZWUpKTtcbiAgICB0b3RhbEZlZUZvclRva2VuUmVjb3ZlcnkgPSB0b3RhbEZlZUZvclRva2VuUmVjb3ZlcnkucGx1cyhuZXcgQmlnTnVtYmVyKGJhc2VGZWUpKTtcbiAgICBpZiAodG90YWxGZWUuZ3QoYmFsYW5jZSkpIHtcbiAgICAgIHRocm93IEVycm9yKCdEaWQgbm90IGZpbmQgYWRkcmVzcyB3aXRoIGZ1bmRzIHRvIHJlY292ZXInKTtcbiAgICB9XG5cbiAgICBpZiAocGFyYW1zLnRva2VuQ29udHJhY3RBZGRyZXNzKSB7XG4gICAgICAvLyBDaGVjayBpZiB0aGVyZSBpcyBzdWZmaWNpZW50IG5hdGl2ZSBzb2xhbmEgdG8gcmVjb3ZlciB0b2tlbnNcbiAgICAgIGlmIChuZXcgQmlnTnVtYmVyKGJhbGFuY2UpLmx0KHRvdGFsRmVlRm9yVG9rZW5SZWNvdmVyeSkpIHtcbiAgICAgICAgdGhyb3cgRXJyb3IoXG4gICAgICAgICAgJ05vdCBlbm91Z2ggZnVuZHMgdG8gcGF5IGZvciByZWNvdmVyIHRva2VucyBmZWVzLCBoYXZlOiAnICtcbiAgICAgICAgICAgIGJhbGFuY2UgK1xuICAgICAgICAgICAgJyBuZWVkOiAnICtcbiAgICAgICAgICAgIHRvdGFsRmVlRm9yVG9rZW5SZWNvdmVyeS50b1N0cmluZygpXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICB0eEJ1aWxkZXIuZmVlKHsgYW1vdW50OiBmZWVQZXJTaWduYXR1cmUgfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IG5ldEFtb3VudCA9IG5ldyBCaWdOdW1iZXIoYmFsYW5jZSkubWludXModG90YWxGZWUpO1xuICAgICAgdHhCdWlsZGVyID0gZmFjdG9yeVxuICAgICAgICAuZ2V0VHJhbnNmZXJCdWlsZGVyKClcbiAgICAgICAgLm5vbmNlKGJsb2NraGFzaClcbiAgICAgICAgLnNlbmRlcihiczU4RW5jb2RlZFB1YmxpY0tleSlcbiAgICAgICAgLnNlbmQoeyBhZGRyZXNzOiBwYXJhbXMucmVjb3ZlcnlEZXN0aW5hdGlvbiwgYW1vdW50OiBuZXRBbW91bnQudG9TdHJpbmcoKSB9KVxuICAgICAgICAuZmVlUGF5ZXIoYnM1OEVuY29kZWRQdWJsaWNLZXkpXG4gICAgICAgIC5mZWUoeyBhbW91bnQ6IGZlZVBlclNpZ25hdHVyZSB9KTtcblxuICAgICAgaWYgKHBhcmFtcy5kdXJhYmxlTm9uY2UpIHtcbiAgICAgICAgdHhCdWlsZGVyLm5vbmNlKGJsb2NraGFzaCwge1xuICAgICAgICAgIHdhbGxldE5vbmNlQWRkcmVzczogcGFyYW1zLmR1cmFibGVOb25jZS5wdWJsaWNLZXksXG4gICAgICAgICAgYXV0aFdhbGxldEFkZHJlc3M6IGF1dGhvcml0eSxcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKCFpc1Vuc2lnbmVkU3dlZXApIHtcbiAgICAgIC8vIFNpZ24gdGhlIHR4blxuICAgICAgaWYgKCFwYXJhbXMudXNlcktleSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ21pc3NpbmcgdXNlcktleScpO1xuICAgICAgfVxuXG4gICAgICBpZiAoIXBhcmFtcy5iYWNrdXBLZXkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdtaXNzaW5nIGJhY2t1cEtleScpO1xuICAgICAgfVxuXG4gICAgICBpZiAoIXBhcmFtcy53YWxsZXRQYXNzcGhyYXNlKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignbWlzc2luZyB3YWxsZXQgcGFzc3BocmFzZScpO1xuICAgICAgfVxuXG4gICAgICAvLyBidWlsZCB0aGUgdHJhbnNhY3Rpb24gd2l0aCBmZWVcbiAgICAgIGNvbnN0IHVuc2lnbmVkVHJhbnNhY3Rpb24gPSAoYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCkpIGFzIFRyYW5zYWN0aW9uO1xuXG4gICAgICBhd2FpdCB0aGlzLmFkZFJlY292ZXJ5U2lnbmF0dXJlKFxuICAgICAgICBwYXJhbXMsXG4gICAgICAgIHR4QnVpbGRlcixcbiAgICAgICAgYnM1OEVuY29kZWRQdWJsaWNLZXksXG4gICAgICAgIGlzTXBjVjIsXG4gICAgICAgIHVuc2lnbmVkVHJhbnNhY3Rpb24sXG4gICAgICAgIGN1cnJQYXRoLFxuICAgICAgICBiaXRnb0tleVxuICAgICAgKTtcbiAgICB9XG5cbiAgICBpZiAocGFyYW1zLmR1cmFibGVOb25jZSkge1xuICAgICAgLy8gYWRkIGR1cmFibGUgbm9uY2UgYWNjb3VudCBzaWduYXR1cmVcbiAgICAgIHR4QnVpbGRlci5zaWduKHsga2V5OiBwYXJhbXMuZHVyYWJsZU5vbmNlLnNlY3JldEtleSB9KTtcbiAgICB9XG5cbiAgICBjb25zdCBjb21wbGV0ZWRUcmFuc2FjdGlvbiA9IGF3YWl0IHR4QnVpbGRlci5idWlsZCgpO1xuICAgIGNvbnN0IHNlcmlhbGl6ZWRUeCA9IGNvbXBsZXRlZFRyYW5zYWN0aW9uLnRvQnJvYWRjYXN0Rm9ybWF0KCk7XG4gICAgY29uc3QgZGVyaXZhdGlvblBhdGggPSBwYXJhbXMuc2VlZCA/IGdldERlcml2YXRpb25QYXRoKHBhcmFtcy5zZWVkKSArIGAvJHtpbmRleH1gIDogYG0vJHtpbmRleH1gO1xuICAgIGNvbnN0IGlucHV0czogT3ZjSW5wdXRbXSA9IFtdO1xuICAgIGZvciAoY29uc3QgaW5wdXQgb2YgY29tcGxldGVkVHJhbnNhY3Rpb24uaW5wdXRzKSB7XG4gICAgICBpbnB1dHMucHVzaCh7XG4gICAgICAgIGFkZHJlc3M6IGlucHV0LmFkZHJlc3MsXG4gICAgICAgIHZhbHVlU3RyaW5nOiBpbnB1dC52YWx1ZSxcbiAgICAgICAgdmFsdWU6IG5ldyBCaWdOdW1iZXIoaW5wdXQudmFsdWUpLnRvTnVtYmVyKCksXG4gICAgICB9KTtcbiAgICB9XG4gICAgY29uc3Qgb3V0cHV0czogT3ZjT3V0cHV0W10gPSBbXTtcbiAgICBmb3IgKGNvbnN0IG91dHB1dCBvZiBjb21wbGV0ZWRUcmFuc2FjdGlvbi5vdXRwdXRzKSB7XG4gICAgICBvdXRwdXRzLnB1c2goe1xuICAgICAgICBhZGRyZXNzOiBvdXRwdXQuYWRkcmVzcyxcbiAgICAgICAgdmFsdWVTdHJpbmc6IG91dHB1dC52YWx1ZSxcbiAgICAgICAgY29pbk5hbWU6IG91dHB1dC5jb2luID8gb3V0cHV0LmNvaW4gOiB3YWxsZXRDb2luLFxuICAgICAgfSk7XG4gICAgfVxuICAgIGNvbnN0IHNwZW5kQW1vdW50ID0gY29tcGxldGVkVHJhbnNhY3Rpb24uaW5wdXRzLmxlbmd0aCA9PT0gMSA/IGNvbXBsZXRlZFRyYW5zYWN0aW9uLmlucHV0c1swXS52YWx1ZSA6IDA7XG4gICAgY29uc3QgcGFyc2VkVHggPSB7IGlucHV0czogaW5wdXRzLCBvdXRwdXRzOiBvdXRwdXRzLCBzcGVuZEFtb3VudDogc3BlbmRBbW91bnQsIHR5cGU6ICcnIH07XG4gICAgY29uc3QgZmVlSW5mbyA9IHsgZmVlOiB0b3RhbEZlZUZvclRva2VuUmVjb3ZlcnkudG9OdW1iZXIoKSwgZmVlU3RyaW5nOiB0b3RhbEZlZS50b1N0cmluZygpIH07XG4gICAgY29uc3QgY29pblNwZWNpZmljID0geyBjb21tb25LZXljaGFpbjogYml0Z29LZXkgfTtcbiAgICBpZiAoaXNVbnNpZ25lZFN3ZWVwKSB7XG4gICAgICBjb25zdCB0cmFuc2FjdGlvbjogTVBDVHggPSB7XG4gICAgICAgIHNlcmlhbGl6ZWRUeDogc2VyaWFsaXplZFR4LFxuICAgICAgICBzY2FuSW5kZXg6IGluZGV4LFxuICAgICAgICBjb2luOiB3YWxsZXRDb2luLFxuICAgICAgICBzaWduYWJsZUhleDogY29tcGxldGVkVHJhbnNhY3Rpb24uc2lnbmFibGVQYXlsb2FkLnRvU3RyaW5nKCdoZXgnKSxcbiAgICAgICAgZGVyaXZhdGlvblBhdGg6IGRlcml2YXRpb25QYXRoLFxuICAgICAgICBwYXJzZWRUeDogcGFyc2VkVHgsXG4gICAgICAgIGZlZUluZm86IGZlZUluZm8sXG4gICAgICAgIGNvaW5TcGVjaWZpYzogY29pblNwZWNpZmljLFxuICAgICAgfTtcbiAgICAgIGNvbnN0IHVuc2lnbmVkVHg6IE1QQ1Vuc2lnbmVkVHggPSB7IHVuc2lnbmVkVHg6IHRyYW5zYWN0aW9uLCBzaWduYXR1cmVTaGFyZXM6IFtdIH07XG4gICAgICBjb25zdCB0cmFuc2FjdGlvbnM6IE1QQ1Vuc2lnbmVkVHhbXSA9IFt1bnNpZ25lZFR4XTtcbiAgICAgIGNvbnN0IHR4UmVxdWVzdDogUmVjb3ZlcnlUeFJlcXVlc3QgPSB7XG4gICAgICAgIHRyYW5zYWN0aW9uczogdHJhbnNhY3Rpb25zLFxuICAgICAgICB3YWxsZXRDb2luOiB3YWxsZXRDb2luLFxuICAgICAgfTtcbiAgICAgIGNvbnN0IHR4UmVxdWVzdHM6IE1QQ1N3ZWVwVHhzID0geyB0eFJlcXVlc3RzOiBbdHhSZXF1ZXN0XSB9O1xuICAgICAgcmV0dXJuIHR4UmVxdWVzdHM7XG4gICAgfVxuICAgIGNvbnN0IHRyYW5zYWN0aW9uOiBNUENUeCA9IHtcbiAgICAgIHNlcmlhbGl6ZWRUeDogc2VyaWFsaXplZFR4LFxuICAgICAgc2NhbkluZGV4OiBpbmRleCxcbiAgICB9O1xuICAgIHJldHVybiB0cmFuc2FjdGlvbjtcbiAgfVxuXG4gIC8qKlxuICAgKiBCdWlsZHMgYSBmdW5kcyByZWNvdmVyeSB0cmFuc2FjdGlvbiB3aXRob3V0IEJpdEdvXG4gICAqIEBwYXJhbSB7U29sUmVjb3ZlcnlPcHRpb25zfSBwYXJhbXMgcGFyYW1ldGVycyBuZWVkZWQgdG8gY29uc3RydWN0IGFuZFxuICAgKiAobWF5YmUpIHNpZ24gdGhlIHRyYW5zYWN0aW9uXG4gICAqXG4gICAqIEByZXR1cm5zIHtCYXNlQnJvYWRjYXN0VHJhbnNhY3Rpb25SZXN1bHRbXX0gdGhlIHNlcmlhbGl6ZWQgdHJhbnNhY3Rpb24gaGV4IHN0cmluZyBhbmQgaW5kZXhcbiAgICogb2YgdGhlIGFkZHJlc3MgYmVpbmcgc3dlcHRcbiAgICovXG4gIGFzeW5jIHJlY292ZXJDbG9zZUFUQShwYXJhbXM6IFNvbFJlY292ZXJ5T3B0aW9ucyk6IFByb21pc2U8QmFzZUJyb2FkY2FzdFRyYW5zYWN0aW9uUmVzdWx0W10+IHtcbiAgICBpZiAoIXBhcmFtcy5iaXRnb0tleSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdtaXNzaW5nIGJpdGdvS2V5Jyk7XG4gICAgfVxuXG4gICAgaWYgKCFwYXJhbXMucmVjb3ZlcnlEZXN0aW5hdGlvbiB8fCAhdGhpcy5pc1ZhbGlkQWRkcmVzcyhwYXJhbXMucmVjb3ZlcnlEZXN0aW5hdGlvbikpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignaW52YWxpZCByZWNvdmVyeURlc3RpbmF0aW9uJyk7XG4gICAgfVxuXG4gICAgaWYgKCFwYXJhbXMuY2xvc2VBdGFBZGRyZXNzIHx8ICF0aGlzLmlzVmFsaWRBZGRyZXNzKHBhcmFtcy5jbG9zZUF0YUFkZHJlc3MpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2ludmFsaWQgY2xvc2VBdGFBZGRyZXNzJyk7XG4gICAgfVxuXG4gICAgY29uc3QgYml0Z29LZXkgPSBwYXJhbXMuYml0Z29LZXkucmVwbGFjZSgvXFxzL2csICcnKTtcblxuICAgIC8vIFZhbGlkYXRlIHNpZ25pbmcga2V5cyBhbmQgZGV0ZWN0IE1QQ3YyIGZvcm1hdCBlYXJseVxuICAgIGNvbnN0IGlzTXBjVjIgPSBhd2FpdCB0aGlzLmlzTXBjdjJTaWduaW5nTWF0ZXJpYWwocGFyYW1zLnVzZXJLZXksIHBhcmFtcy5iYWNrdXBLZXksIHBhcmFtcy53YWxsZXRQYXNzcGhyYXNlKTtcblxuICAgIC8vIEJ1aWxkIHRoZSB0cmFuc2FjdGlvblxuICAgIGxldCBiYWxhbmNlID0gMDtcblxuICAgIGNvbnN0IGluZGV4ID0gcGFyYW1zLmluZGV4IHx8IDA7XG4gICAgY29uc3QgY3VyclBhdGggPSBwYXJhbXMuc2VlZCA/IGdldERlcml2YXRpb25QYXRoKHBhcmFtcy5zZWVkKSArIGAvJHtpbmRleH1gIDogYG0vJHtpbmRleH1gO1xuXG4gICAgY29uc3QgTVBDID0gYXdhaXQgRUREU0FNZXRob2RzLmdldEluaXRpYWxpemVkTXBjSW5zdGFuY2UoKTtcbiAgICBjb25zdCBhY2NvdW50SWQgPSBNUEMuZGVyaXZlVW5oYXJkZW5lZChiaXRnb0tleSwgY3VyclBhdGgpLnNsaWNlKDAsIDY0KTtcbiAgICBjb25zdCBiczU4RW5jb2RlZFB1YmxpY0tleSA9IG5ldyBTb2xLZXlQYWlyKHsgcHViOiBhY2NvdW50SWQgfSkuZ2V0QWRkcmVzcygpO1xuXG4gICAgY29uc3QgYWNjb3VudEJhbGFuY2UgPSBhd2FpdCB0aGlzLmdldEFjY291bnRCYWxhbmNlKGJzNThFbmNvZGVkUHVibGljS2V5KTtcblxuICAgIGJhbGFuY2UgPSBhd2FpdCB0aGlzLmdldEFjY291bnRCYWxhbmNlKHBhcmFtcy5jbG9zZUF0YUFkZHJlc3MpO1xuICAgIGlmIChiYWxhbmNlIDw9IDApIHtcbiAgICAgIHRocm93IEVycm9yKCdEaWQgbm90IGZpbmQgY2xvc2VBdGFBZGRyZXNzIHdpdGggc29sIGZ1bmRzIHRvIHJlY292ZXInKTtcbiAgICB9XG5cbiAgICBjb25zdCBmYWN0b3J5ID0gdGhpcy5nZXRCdWlsZGVyKCk7XG5cbiAgICBsZXQgdHhCdWlsZGVyO1xuICAgIGxldCBibG9ja2hhc2g7XG4gICAgY29uc3QgcmVjb3ZlcnRUeG5zOiBCYXNlQnJvYWRjYXN0VHJhbnNhY3Rpb25SZXN1bHRbXSA9IFtdO1xuXG4gICAgY29uc3QgcmVudEV4ZW1wdEFtb3VudCA9IGF3YWl0IHRoaXMuZ2V0UmVudEV4ZW1wdEFtb3VudCgpO1xuXG4gICAgLy8gZG8gdG9rZW4gcmVjb3ZlcnkgYmVmb3JlIGNsb3NpbmcgQVRBIGFkZHJlc3NcbiAgICAvLyBjaGVjayBpZiBhbnkgdG9rZW4gaXMgcHJlc2VudCBvbiB0aGUgY2xvc2VBdGFBZGRyZXNzXG4gICAgY29uc3QgdG9rZW5JbmZvID0gYXdhaXQgdGhpcy5nZXRUb2tlbkFjY291bnRJbmZvKHBhcmFtcy5jbG9zZUF0YUFkZHJlc3MpO1xuICAgIGNvbnN0IHRva2VuQmFsYW5jZSA9IE51bWJlcih0b2tlbkluZm8uaW5mby50b2tlbkFtb3VudC5hbW91bnQpO1xuXG4gICAgaWYgKHRva2VuQmFsYW5jZSA+IDApIHtcbiAgICAgIC8vIGNsb3NlQVRBIGFkZHJlc3MgaGFzIHNvbWUgdG9rZW4gYmFsYW5jZSwgaXQgbmVlZHMgdG8gYmUgd2l0aGRyYXduIGJlZm9yZSBjbG9zaW5nIEFUQVxuICAgICAgY29uc29sZS5sb2coXG4gICAgICAgIGBjbG9zZUFUQSBhZGRyZXNzICR7cGFyYW1zLmNsb3NlQXRhQWRkcmVzc30gaGFzIHRva2VuIGJhbGFuY2UgJHt0b2tlbkJhbGFuY2V9LCBpdCBuZWVkcyB0byBiZSB3aXRoZHJhd24gYmVmb3JlIGNsb3NpbmcgQVRBIGFkZHJlc3NgXG4gICAgICApO1xuXG4gICAgICBpZiAoIXBhcmFtcy5yZWNvdmVyeURlc3RpbmF0aW9uQXRhQWRkcmVzcyB8fCAhdGhpcy5pc1ZhbGlkQWRkcmVzcyhwYXJhbXMucmVjb3ZlcnlEZXN0aW5hdGlvbkF0YUFkZHJlc3MpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignaW52YWxpZCByZWNvdmVyeURlc3RpbmF0aW9uQXRhQWRkcmVzcycpO1xuICAgICAgfVxuXG4gICAgICBibG9ja2hhc2ggPSBhd2FpdCB0aGlzLmdldEJsb2NraGFzaChwYXJhbXMuYXBpS2V5KTtcblxuICAgICAgdHhCdWlsZGVyID0gZmFjdG9yeVxuICAgICAgICAuZ2V0VG9rZW5UcmFuc2ZlckJ1aWxkZXIoKVxuICAgICAgICAubm9uY2UoYmxvY2toYXNoKVxuICAgICAgICAuc2VuZGVyKGJzNThFbmNvZGVkUHVibGljS2V5KVxuICAgICAgICAuYXNzb2NpYXRlZFRva2VuQWNjb3VudFJlbnQocmVudEV4ZW1wdEFtb3VudC50b1N0cmluZygpKVxuICAgICAgICAuZmVlUGF5ZXIoYnM1OEVuY29kZWRQdWJsaWNLZXkpO1xuICAgICAgY29uc3QgdW5zaWduZWRUcmFuc2FjdGlvbiA9IChhd2FpdCB0eEJ1aWxkZXIuYnVpbGQoKSkgYXMgVHJhbnNhY3Rpb247XG4gICAgICBjb25zdCBzZXJpYWxpemVkTWVzc2FnZSA9IHVuc2lnbmVkVHJhbnNhY3Rpb24uc29sVHJhbnNhY3Rpb24uc2VyaWFsaXplTWVzc2FnZSgpLnRvU3RyaW5nKCdiYXNlNjQnKTtcbiAgICAgIGNvbnN0IGZlZVBlclNpZ25hdHVyZSA9IGF3YWl0IHRoaXMuZ2V0RmVlRm9yTWVzc2FnZShzZXJpYWxpemVkTWVzc2FnZSwgcGFyYW1zLmFwaUtleSk7XG4gICAgICBjb25zdCBiYXNlRmVlID0gcGFyYW1zLmR1cmFibGVOb25jZSA/IGZlZVBlclNpZ25hdHVyZSAqIDIgOiBmZWVQZXJTaWduYXR1cmU7XG4gICAgICBjb25zdCB0b3RhbEZlZSA9IG5ldyBCaWdOdW1iZXIoYmFzZUZlZSk7XG4gICAgICBpZiAodG90YWxGZWUuZ3QoYWNjb3VudEJhbGFuY2UpKSB7XG4gICAgICAgIHRocm93IEVycm9yKCdEaWQgbm90IGZpbmQgYWRkcmVzcyB3aXRoIGZ1bmRzIHRvIHJlY292ZXInKTtcbiAgICAgIH1cbiAgICAgIHR4QnVpbGRlci5mZWUoeyBhbW91bnQ6IGZlZVBlclNpZ25hdHVyZSB9KTtcblxuICAgICAgY29uc3QgbmV0d29yayA9IHRoaXMuZ2V0TmV0d29yaygpO1xuICAgICAgY29uc3QgdG9rZW4gPSBnZXRTb2xUb2tlbkZyb21BZGRyZXNzKHRva2VuSW5mby5pbmZvLm1pbnQsIG5ldHdvcmspOyAvLyB0b2RvKFdJTi01ODk0KSBmaXggZm9yIGFtc1xuICAgICAgdHhCdWlsZGVyLnNlbmQoe1xuICAgICAgICBhZGRyZXNzOiBwYXJhbXMucmVjb3ZlcnlEZXN0aW5hdGlvbkF0YUFkZHJlc3MsXG4gICAgICAgIGFtb3VudDogdG9rZW5CYWxhbmNlLFxuICAgICAgICB0b2tlbk5hbWU6IHRva2VuPy5uYW1lLFxuICAgICAgfSk7XG5cbiAgICAgIGNvbnN0IHRva2VuUmVjb3ZlcnlUeG4gPSBhd2FpdCB0aGlzLnNpZ25BbmRHZW5lcmF0ZUJyb2FkY2FzdGFibGVUcmFuc2FjdGlvbihcbiAgICAgICAgcGFyYW1zLFxuICAgICAgICB0eEJ1aWxkZXIsXG4gICAgICAgIGJzNThFbmNvZGVkUHVibGljS2V5LFxuICAgICAgICBpc01wY1YyXG4gICAgICApO1xuICAgICAgY29uc3Qgc2VyaWFsaXplZFRva2VuUmVjb3ZlcnlUeG4gPSAoYXdhaXQgdG9rZW5SZWNvdmVyeVR4bikuc2VyaWFsaXplZFR4O1xuICAgICAgY29uc3QgYnJvYWRjYXN0VG9rZW5SZWNvdmVyeVR4biA9IGF3YWl0IHRoaXMuYnJvYWRjYXN0VHJhbnNhY3Rpb24oe1xuICAgICAgICBzZXJpYWxpemVkU2lnbmVkVHJhbnNhY3Rpb246IHNlcmlhbGl6ZWRUb2tlblJlY292ZXJ5VHhuLFxuICAgICAgfSk7XG4gICAgICBsb2dnZXIubG9nKGJyb2FkY2FzdFRva2VuUmVjb3ZlcnlUeG4pO1xuICAgICAgcmVjb3ZlcnRUeG5zLnB1c2goYnJvYWRjYXN0VG9rZW5SZWNvdmVyeVR4bik7XG4gICAgfVxuXG4gICAgLy8gYWZ0ZXIgcmVjb3ZlcmluZyB0aGUgdG9rZW4gYW1vdW50LCBhdHRlbXB0aW5nIHRvIGNsb3NlIHRoZSBBVEEgYWRkcmVzc1xuICAgIGlmIChwYXJhbXMuY2xvc2VBdGFBZGRyZXNzKSB7XG4gICAgICBibG9ja2hhc2ggPSBhd2FpdCB0aGlzLmdldEJsb2NraGFzaChwYXJhbXMuYXBpS2V5KTtcblxuICAgICAgY29uc3QgYXRhQ2xvc2VCdWlsZGVyID0gKCkgPT4ge1xuICAgICAgICBjb25zdCB0eEJ1aWxkZXIgPSBmYWN0b3J5LmdldENsb3NlQXRhSW5pdGlhbGl6YXRpb25CdWlsZGVyKCk7XG4gICAgICAgIHR4QnVpbGRlci5ub25jZShibG9ja2hhc2gpO1xuICAgICAgICB0eEJ1aWxkZXIuc2VuZGVyKGJzNThFbmNvZGVkUHVibGljS2V5KTtcbiAgICAgICAgdHhCdWlsZGVyLmFjY291bnRBZGRyZXNzKHBhcmFtcy5jbG9zZUF0YUFkZHJlc3MgPz8gJycpO1xuICAgICAgICB0eEJ1aWxkZXIuZGVzdGluYXRpb25BZGRyZXNzKHBhcmFtcy5yZWNvdmVyeURlc3RpbmF0aW9uKTtcbiAgICAgICAgdHhCdWlsZGVyLmF1dGhvcml0eUFkZHJlc3MoYnM1OEVuY29kZWRQdWJsaWNLZXkpO1xuICAgICAgICB0eEJ1aWxkZXIuYXNzb2NpYXRlZFRva2VuQWNjb3VudFJlbnQocmVudEV4ZW1wdEFtb3VudC50b1N0cmluZygpKTtcbiAgICAgICAgcmV0dXJuIHR4QnVpbGRlcjtcbiAgICAgIH07XG4gICAgICB0eEJ1aWxkZXIgPSBhdGFDbG9zZUJ1aWxkZXIoKTtcbiAgICB9XG4gICAgY29uc3QgY2xvc2VBVEFSZWNvdmVyeVR4biA9IGF3YWl0IHRoaXMuc2lnbkFuZEdlbmVyYXRlQnJvYWRjYXN0YWJsZVRyYW5zYWN0aW9uKFxuICAgICAgcGFyYW1zLFxuICAgICAgdHhCdWlsZGVyLFxuICAgICAgYnM1OEVuY29kZWRQdWJsaWNLZXksXG4gICAgICBpc01wY1YyXG4gICAgKTtcbiAgICBjb25zdCBzZXJpYWxpemVkQ2xvc2VBVEFSZWNvdmVyeVR4biA9IChhd2FpdCBjbG9zZUFUQVJlY292ZXJ5VHhuKS5zZXJpYWxpemVkVHg7XG4gICAgY29uc3QgYnJvYWRjYXN0Q2xvc2VBVEFSZWNvdmVyeVR4biA9IGF3YWl0IHRoaXMuYnJvYWRjYXN0VHJhbnNhY3Rpb24oe1xuICAgICAgc2VyaWFsaXplZFNpZ25lZFRyYW5zYWN0aW9uOiBzZXJpYWxpemVkQ2xvc2VBVEFSZWNvdmVyeVR4bixcbiAgICB9KTtcbiAgICBsb2dnZXIubG9nKGJyb2FkY2FzdENsb3NlQVRBUmVjb3ZlcnlUeG4pO1xuICAgIHJlY292ZXJ0VHhucy5wdXNoKGJyb2FkY2FzdENsb3NlQVRBUmVjb3ZlcnlUeG4pO1xuXG4gICAgcmV0dXJuIHJlY292ZXJ0VHhucztcbiAgfVxuXG4gIC8qKlxuICAgKiBSZWNvdmVycyB0b2tlbnMgZnJvbSBhIG5lc3RlZCBBVEEg4oCUIGFuIEFUQSB3aG9zZSBvd25lciBpcyBhbm90aGVyIEFUQSByYXRoZXIgdGhhbiBhIHdhbGxldCBhZGRyZXNzLlxuICAgKlxuICAgKiBUaGlzIHNpdHVhdGlvbiBvY2N1cnMgd2hlbiBhbiBleHRlcm5hbCBzZW5kZXIgbWlzdGFrZW5seSBjYWxscyBjcmVhdGVBc3NvY2lhdGVkVG9rZW5BY2NvdW50IHdpdGhcbiAgICogYW4gQVRBIGFkZHJlc3MgYXMgdGhlIG93bmVyIGluc3RlYWQgb2YgdGhlIHJvb3Qgd2FsbGV0IGFkZHJlc3MuIFRoZSByZXN1bHQgaXMgYSBcIm5lc3RlZCBBVEFcIlxuICAgKiAoQVRBLTIpIG93bmVkIGJ5IHRoZSB3YWxsZXQncyBub3JtYWwgQVRBIChBVEEtMSkuIEJlY2F1c2UgQVRBLTEgaXMgYSBQREEgd2l0aCBubyBwcml2YXRlIGtleSxcbiAgICogdGhlIHN0YW5kYXJkIHJlY292ZXJDbG9zZUFUQSBmbG93IGNhbm5vdCBzaWduIGZvciBBVEEtMi5cbiAgICpcbiAgICogVGhpcyBtZXRob2QgdXNlcyB0aGUgQXNzb2NpYXRlZCBUb2tlbiBBY2NvdW50IHByb2dyYW0ncyBSZWNvdmVyTmVzdGVkIGluc3RydWN0aW9uLCB3aGljaCBhbGxvd3NcbiAgICogdGhlIHJvb3Qgd2FsbGV0IG93bmVyIHRvIHNpZ24gYW5kIGF0b21pY2FsbHkgbW92ZSB0b2tlbnMgZnJvbSBBVEEtMiDihpIgQVRBLTEgYW5kIGNsb3NlIEFUQS0yLFxuICAgKiByZXR1cm5pbmcgdGhlIHJlbnQtZXhlbXB0IFNPTCB0byB0aGUgd2FsbGV0IGFkZHJlc3MuXG4gICAqXG4gICAqIEBwYXJhbSB7U29sUmVjb3ZlcnlPcHRpb25zfSBwYXJhbXMgLSByZWNvdmVyeSBwYXJhbXMsIHJlcXVpcmVzIG5lc3RlZEF0YUFkZHJlc3MsIG93bmVyQXRhQWRkcmVzcyxcbiAgICogICBhbmQgdG9rZW5NaW50QWRkcmVzcyBpbiBhZGRpdGlvbiB0byB0aGUgc3RhbmRhcmQga2V5Y2hhaW4gZmllbGRzXG4gICAqL1xuICBhc3luYyByZWNvdmVyTmVzdGVkQXRhKHBhcmFtczogU29sUmVjb3ZlcnlPcHRpb25zKTogUHJvbWlzZTxCYXNlQnJvYWRjYXN0VHJhbnNhY3Rpb25SZXN1bHQ+IHtcbiAgICBpZiAoIXBhcmFtcy5iaXRnb0tleSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdtaXNzaW5nIGJpdGdvS2V5Jyk7XG4gICAgfVxuXG4gICAgaWYgKCFwYXJhbXMucmVjb3ZlcnlEZXN0aW5hdGlvbiB8fCAhdGhpcy5pc1ZhbGlkQWRkcmVzcyhwYXJhbXMucmVjb3ZlcnlEZXN0aW5hdGlvbikpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignaW52YWxpZCByZWNvdmVyeURlc3RpbmF0aW9uJyk7XG4gICAgfVxuXG4gICAgaWYgKCFwYXJhbXMubmVzdGVkQXRhQWRkcmVzcyB8fCAhdGhpcy5pc1ZhbGlkQWRkcmVzcyhwYXJhbXMubmVzdGVkQXRhQWRkcmVzcykpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignaW52YWxpZCBuZXN0ZWRBdGFBZGRyZXNzJyk7XG4gICAgfVxuXG4gICAgaWYgKCFwYXJhbXMub3duZXJBdGFBZGRyZXNzIHx8ICF0aGlzLmlzVmFsaWRBZGRyZXNzKHBhcmFtcy5vd25lckF0YUFkZHJlc3MpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2ludmFsaWQgb3duZXJBdGFBZGRyZXNzJyk7XG4gICAgfVxuXG4gICAgaWYgKCFwYXJhbXMudG9rZW5NaW50QWRkcmVzcyB8fCAhdGhpcy5pc1ZhbGlkQWRkcmVzcyhwYXJhbXMudG9rZW5NaW50QWRkcmVzcykpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignaW52YWxpZCB0b2tlbk1pbnRBZGRyZXNzJyk7XG4gICAgfVxuXG4gICAgY29uc3QgYml0Z29LZXkgPSBwYXJhbXMuYml0Z29LZXkucmVwbGFjZSgvXFxzL2csICcnKTtcbiAgICBjb25zdCB1c2VyS2V5ID0gcGFyYW1zLnVzZXJLZXk/LnJlcGxhY2UoL1xccy9nLCAnJykgPz8gJyc7XG5cbiAgICBjb25zdCBpc01wY1YyID0gcGFyYW1zLndhbGxldFBhc3NwaHJhc2VcbiAgICAgID8gKGF3YWl0IGdldEVkZHNhU2lnbmluZ01hdGVyaWFsKHVzZXJLZXksIHBhcmFtcy53YWxsZXRQYXNzcGhyYXNlLCB0aGlzLmJpdGdvKSkudmVyc2lvbiA9PT0gJ3YyJ1xuICAgICAgOiBmYWxzZTtcblxuICAgIGNvbnN0IGluZGV4ID0gcGFyYW1zLmluZGV4IHx8IDA7XG4gICAgY29uc3QgY3VyclBhdGggPSBwYXJhbXMuc2VlZCA/IGdldERlcml2YXRpb25QYXRoKHBhcmFtcy5zZWVkKSArIGAvJHtpbmRleH1gIDogYG0vJHtpbmRleH1gO1xuICAgIGNvbnN0IGFjY291bnRJZCA9IChhd2FpdCBFRERTQU1ldGhvZHMuZ2V0SW5pdGlhbGl6ZWRNcGNJbnN0YW5jZSgpKVxuICAgICAgLmRlcml2ZVVuaGFyZGVuZWQoYml0Z29LZXksIGN1cnJQYXRoKVxuICAgICAgLnNsaWNlKDAsIDY0KTtcbiAgICBjb25zdCBiczU4RW5jb2RlZFB1YmxpY0tleSA9IG5ldyBTb2xLZXlQYWlyKHsgcHViOiBhY2NvdW50SWQgfSkuZ2V0QWRkcmVzcygpO1xuXG4gICAgY29uc3QgYmxvY2toYXNoID0gYXdhaXQgdGhpcy5nZXRCbG9ja2hhc2gocGFyYW1zLmFwaUtleSk7XG4gICAgY29uc3QgcmVudEV4ZW1wdEFtb3VudCA9IGF3YWl0IHRoaXMuZ2V0UmVudEV4ZW1wdEFtb3VudCgpO1xuXG4gICAgY29uc3QgZmFjdG9yeSA9IHRoaXMuZ2V0QnVpbGRlcigpO1xuICAgIGNvbnN0IHR4QnVpbGRlciA9IGZhY3RvcnkuZ2V0UmVjb3Zlck5lc3RlZEF0YUJ1aWxkZXIoKTtcbiAgICB0eEJ1aWxkZXIubm9uY2UoYmxvY2toYXNoKTtcbiAgICB0eEJ1aWxkZXIuc2VuZGVyKGJzNThFbmNvZGVkUHVibGljS2V5KTtcbiAgICB0eEJ1aWxkZXIuZmVlUGF5ZXIoYnM1OEVuY29kZWRQdWJsaWNLZXkpO1xuICAgIHR4QnVpbGRlci5hc3NvY2lhdGVkVG9rZW5BY2NvdW50UmVudChyZW50RXhlbXB0QW1vdW50LnRvU3RyaW5nKCkpO1xuICAgIHR4QnVpbGRlci5uZXN0ZWRBY2NvdW50QWRkcmVzcyhwYXJhbXMubmVzdGVkQXRhQWRkcmVzcyk7XG4gICAgdHhCdWlsZGVyLm5lc3RlZE1pbnRBZGRyZXNzKHBhcmFtcy50b2tlbk1pbnRBZGRyZXNzKTtcbiAgICB0eEJ1aWxkZXIuZGVzdGluYXRpb25BY2NvdW50QWRkcmVzcyhwYXJhbXMub3duZXJBdGFBZGRyZXNzKTtcbiAgICB0eEJ1aWxkZXIub3duZXJBY2NvdW50QWRkcmVzcyhwYXJhbXMub3duZXJBdGFBZGRyZXNzKTtcbiAgICB0eEJ1aWxkZXIub3duZXJNaW50QWRkcmVzcyhwYXJhbXMudG9rZW5NaW50QWRkcmVzcyk7XG4gICAgdHhCdWlsZGVyLndhbGxldEFkZHJlc3MoYnM1OEVuY29kZWRQdWJsaWNLZXkpO1xuXG4gICAgY29uc3QgcmVjb3Zlck5lc3RlZFR4biA9IGF3YWl0IHRoaXMuc2lnbkFuZEdlbmVyYXRlQnJvYWRjYXN0YWJsZVRyYW5zYWN0aW9uKFxuICAgICAgcGFyYW1zLFxuICAgICAgdHhCdWlsZGVyLFxuICAgICAgYnM1OEVuY29kZWRQdWJsaWNLZXksXG4gICAgICBpc01wY1YyXG4gICAgKTtcblxuICAgIGNvbnN0IHNlcmlhbGl6ZWRUeG4gPSAoYXdhaXQgcmVjb3Zlck5lc3RlZFR4bikuc2VyaWFsaXplZFR4O1xuICAgIGNvbnN0IGJyb2FkY2FzdFJlc3VsdCA9IGF3YWl0IHRoaXMuYnJvYWRjYXN0VHJhbnNhY3Rpb24oe1xuICAgICAgc2VyaWFsaXplZFNpZ25lZFRyYW5zYWN0aW9uOiBzZXJpYWxpemVkVHhuLFxuICAgIH0pO1xuICAgIGxvZ2dlci5sb2coYnJvYWRjYXN0UmVzdWx0KTtcblxuICAgIHJldHVybiBicm9hZGNhc3RSZXN1bHQ7XG4gIH1cblxuICBhc3luYyBzaWduQW5kR2VuZXJhdGVCcm9hZGNhc3RhYmxlVHJhbnNhY3Rpb24oXG4gICAgcGFyYW1zOiBTb2xSZWNvdmVyeU9wdGlvbnMsXG4gICAgdHhCdWlsZGVyOiBUcmFuc2FjdGlvbkJ1aWxkZXIsXG4gICAgYnM1OEVuY29kZWRQdWJsaWNLZXk6IHN0cmluZyxcbiAgICBpc01wY1YyID0gZmFsc2VcbiAgKTogUHJvbWlzZTxNUENUeD4ge1xuICAgIGlmICghcGFyYW1zLnVzZXJLZXkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignbWlzc2luZyB1c2VyS2V5Jyk7XG4gICAgfVxuXG4gICAgaWYgKCFwYXJhbXMuYmFja3VwS2V5KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ21pc3NpbmcgYmFja3VwS2V5Jyk7XG4gICAgfVxuXG4gICAgaWYgKCFwYXJhbXMud2FsbGV0UGFzc3BocmFzZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdtaXNzaW5nIHdhbGxldCBwYXNzcGhyYXNlJyk7XG4gICAgfVxuXG4gICAgY29uc3QgdW5zaWduZWRUcmFuc2FjdGlvbiA9IChhd2FpdCB0eEJ1aWxkZXIuYnVpbGQoKSkgYXMgVHJhbnNhY3Rpb247XG4gICAgY29uc3QgaW5kZXggPSBwYXJhbXMuaW5kZXggfHwgMDtcbiAgICBjb25zdCBjdXJyUGF0aCA9IHBhcmFtcy5zZWVkID8gZ2V0RGVyaXZhdGlvblBhdGgocGFyYW1zLnNlZWQpICsgYC8ke2luZGV4fWAgOiBgbS8ke2luZGV4fWA7XG5cbiAgICBhd2FpdCB0aGlzLmFkZFJlY292ZXJ5U2lnbmF0dXJlKFxuICAgICAgcGFyYW1zLFxuICAgICAgdHhCdWlsZGVyLFxuICAgICAgYnM1OEVuY29kZWRQdWJsaWNLZXksXG4gICAgICBpc01wY1YyLFxuICAgICAgdW5zaWduZWRUcmFuc2FjdGlvbixcbiAgICAgIGN1cnJQYXRoLFxuICAgICAgcGFyYW1zLmJpdGdvS2V5LnJlcGxhY2UoL1xccy9nLCAnJylcbiAgICApO1xuXG4gICAgY29uc3QgY29tcGxldGVkVHJhbnNhY3Rpb24gPSBhd2FpdCB0eEJ1aWxkZXIuYnVpbGQoKTtcbiAgICBjb25zdCBzZXJpYWxpemVkVHggPSBjb21wbGV0ZWRUcmFuc2FjdGlvbi50b0Jyb2FkY2FzdEZvcm1hdCgpO1xuICAgIGNvbnN0IHRyYW5zYWN0aW9uOiBNUENUeCA9IHtcbiAgICAgIHNlcmlhbGl6ZWRUeDogc2VyaWFsaXplZFR4LFxuICAgICAgc2NhbkluZGV4OiBpbmRleCxcbiAgICB9O1xuICAgIHJldHVybiB0cmFuc2FjdGlvbjtcbiAgfVxuXG4gIC8qKlxuICAgKiBCdWlsZHMgbmF0aXZlIFNPTCByZWNvdmVyaWVzIG9mIHJlY2VpdmUgYWRkcmVzc2VzIGluIGJhdGNoIHdpdGhvdXQgQml0R28uXG4gICAqIEZ1bmRzIHdpbGwgYmUgcmVjb3ZlcmVkIHRvIGJhc2UgYWRkcmVzcyBmaXJzdC4gWW91IG5lZWQgdG8gaW5pdGlhdGUgYW5vdGhlciBzd2VlcCB0eG4gYWZ0ZXIgdGhhdC5cbiAgICpcbiAgICogQHBhcmFtIHtTb2xDb25zb2xpZGF0aW9uUmVjb3ZlcnlPcHRpb25zfSBwYXJhbXMgLSBvcHRpb25zIGZvciBjb25zb2xpZGF0aW9uIHJlY292ZXJ5LlxuICAgKiBAcGFyYW0ge3N0cmluZ30gW3BhcmFtcy5zdGFydGluZ1NjYW5JbmRleF0gLSByZWNlaXZlIGFkZHJlc3MgaW5kZXggdG8gc3RhcnQgc2Nhbm5pbmcgZnJvbS4gZGVmYXVsdCB0byAxIChpbmNsdXNpdmUpLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gW3BhcmFtcy5lbmRpbmdTY2FuSW5kZXhdIC0gcmVjZWl2ZSBhZGRyZXNzIGluZGV4IHRvIGVuZCBzY2FubmluZyBhdC4gZGVmYXVsdCB0byBzdGFydGluZ1NjYW5JbmRleCArIDIwIChleGNsdXNpdmUpLlxuICAgKi9cbiAgYXN5bmMgcmVjb3ZlckNvbnNvbGlkYXRpb25zKHBhcmFtczogU29sQ29uc29saWRhdGlvblJlY292ZXJ5T3B0aW9ucyk6IFByb21pc2U8TVBDVHhzIHwgTVBDU3dlZXBUeHM+IHtcbiAgICBpZiAoIXBhcmFtcy5iaXRnb0tleSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdtaXNzaW5nIGJpdGdvS2V5Jyk7XG4gICAgfVxuXG4gICAgY29uc3QgaXNVbnNpZ25lZFN3ZWVwID0gIXBhcmFtcy53YWxsZXRQYXNzcGhyYXNlO1xuICAgIGNvbnN0IHN0YXJ0SWR4ID0gcGFyYW1zLnN0YXJ0aW5nU2NhbkluZGV4IHx8IDE7XG4gICAgY29uc3QgZW5kSWR4ID0gcGFyYW1zLmVuZGluZ1NjYW5JbmRleCB8fCBzdGFydElkeCArIERFRkFVTFRfU0NBTl9GQUNUT1I7XG5cbiAgICBpZiAoc3RhcnRJZHggPCAxIHx8IGVuZElkeCA8PSBzdGFydElkeCB8fCBlbmRJZHggLSBzdGFydElkeCA+IDEwICogREVGQVVMVF9TQ0FOX0ZBQ1RPUikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgSW52YWxpZCBzdGFydGluZyBvciBlbmRpbmcgaW5kZXggdG8gc2NhbiBmb3IgYWRkcmVzc2VzLiBzdGFydGluZ1NjYW5JbmRleDogJHtzdGFydElkeH0sIGVuZGluZ1NjYW5JbmRleDogJHtlbmRJZHh9LmBcbiAgICAgICk7XG4gICAgfVxuXG4gICAgLy8gdmFsaWRhdGUgZHVyYWJsZSBub25jZXMgYXJyYXlcbiAgICBpZiAoIXBhcmFtcy5kdXJhYmxlTm9uY2VzKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ01pc3NpbmcgZHVyYWJsZSBub25jZXMnKTtcbiAgICB9XG4gICAgaWYgKCFwYXJhbXMuZHVyYWJsZU5vbmNlcy5wdWJsaWNLZXlzKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgZHVyYWJsZSBub25jZXM6IG1pc3NpbmcgcHVibGljIGtleXMnKTtcbiAgICB9XG4gICAgaWYgKCFwYXJhbXMuZHVyYWJsZU5vbmNlcy5zZWNyZXRLZXkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBkdXJhYmxlIG5vbmNlcyBhcnJheTogbWlzc2luZyBzZWNyZXQga2V5Jyk7XG4gICAgfVxuXG4gICAgY29uc3QgYml0Z29LZXkgPSBwYXJhbXMuYml0Z29LZXkucmVwbGFjZSgvXFxzL2csICcnKTtcbiAgICBjb25zdCB1c2VyS2V5ID0gcGFyYW1zLnVzZXJLZXk/LnJlcGxhY2UoL1xccy9nLCAnJykgPz8gJyc7XG5cbiAgICAvLyBEZXRlY3Qgb25jZSBhdCB0aGUgdG9wIHRvIGF2b2lkIGRlY3J5cHRpbmcgdGhlIGtleWNhcmQgb24gZXZlcnkgaXRlcmF0aW9uIG9mIHRoZSBzY2FuIGxvb3AuXG4gICAgLy8gRm9yIHVuc2lnbmVkIHN3ZWVwIChubyBwYXNzcGhyYXNlKSwgaXNNcGNWMiBpcyBmYWxzZSDigJQgY29sZCBNUEN2MiBpcyBvdXQgb2Ygc2NvcGUuXG4gICAgY29uc3QgaXNNcGNWMiA9IHBhcmFtcy53YWxsZXRQYXNzcGhyYXNlXG4gICAgICA/IChhd2FpdCBnZXRFZGRzYVNpZ25pbmdNYXRlcmlhbCh1c2VyS2V5LCBwYXJhbXMud2FsbGV0UGFzc3BocmFzZSwgdGhpcy5iaXRnbykpLnZlcnNpb24gPT09ICd2MidcbiAgICAgIDogZmFsc2U7XG5cbiAgICBjb25zdCBiYXNlQWRkcmVzc0luZGV4ID0gMDtcbiAgICBjb25zdCBiYXNlQWRkcmVzc1BhdGggPSBwYXJhbXMuc2VlZFxuICAgICAgPyBnZXREZXJpdmF0aW9uUGF0aChwYXJhbXMuc2VlZCkgKyBgLyR7YmFzZUFkZHJlc3NJbmRleH1gXG4gICAgICA6IGBtLyR7YmFzZUFkZHJlc3NJbmRleH1gO1xuICAgIGNvbnN0IGJhc2VBY2NvdW50SWQgPSAoYXdhaXQgRUREU0FNZXRob2RzLmdldEluaXRpYWxpemVkTXBjSW5zdGFuY2UoKSlcbiAgICAgIC5kZXJpdmVVbmhhcmRlbmVkKGJpdGdvS2V5LCBiYXNlQWRkcmVzc1BhdGgpXG4gICAgICAuc2xpY2UoMCwgNjQpO1xuICAgIGNvbnN0IGJhc2VBZGRyZXNzID0gbmV3IFNvbEtleVBhaXIoeyBwdWI6IGJhc2VBY2NvdW50SWQgfSkuZ2V0QWRkcmVzcygpO1xuXG4gICAgbGV0IGR1cmFibGVOb25jZVB1YktleXNJbmRleCA9IDA7XG4gICAgY29uc3QgZHVyYWJsZU5vbmNlUHViS2V5c0xlbmd0aCA9IHBhcmFtcy5kdXJhYmxlTm9uY2VzLnB1YmxpY0tleXMubGVuZ3RoO1xuICAgIGNvbnN0IGNvbnNvbGlkYXRpb25UcmFuc2FjdGlvbnM6IGFueVtdID0gW107XG4gICAgbGV0IGxhc3RTY2FuSW5kZXggPSBzdGFydElkeDtcblxuICAgIGZvciAobGV0IGkgPSBzdGFydElkeDsgaSA8IGVuZElkeDsgaSsrKSB7XG4gICAgICBjb25zdCByZWNvdmVyUGFyYW1zID0ge1xuICAgICAgICB1c2VyS2V5OiBwYXJhbXMudXNlcktleSxcbiAgICAgICAgYmFja3VwS2V5OiBwYXJhbXMuYmFja3VwS2V5LFxuICAgICAgICBiaXRnb0tleTogcGFyYW1zLmJpdGdvS2V5LFxuICAgICAgICB3YWxsZXRQYXNzcGhyYXNlOiBwYXJhbXMud2FsbGV0UGFzc3BocmFzZSxcbiAgICAgICAgbXVsdGlzaWdUeXBlVmVyc2lvbjogaXNNcGNWMiA/ICgnTVBDdjInIGFzIGNvbnN0KSA6IHVuZGVmaW5lZCxcbiAgICAgICAgcmVjb3ZlcnlEZXN0aW5hdGlvbjogYmFzZUFkZHJlc3MsXG4gICAgICAgIHNlZWQ6IHBhcmFtcy5zZWVkLFxuICAgICAgICBpbmRleDogaSxcbiAgICAgICAgZHVyYWJsZU5vbmNlOiB7XG4gICAgICAgICAgcHVibGljS2V5OiBwYXJhbXMuZHVyYWJsZU5vbmNlcy5wdWJsaWNLZXlzW2R1cmFibGVOb25jZVB1YktleXNJbmRleF0sXG4gICAgICAgICAgc2VjcmV0S2V5OiBwYXJhbXMuZHVyYWJsZU5vbmNlcy5zZWNyZXRLZXksXG4gICAgICAgIH0sXG4gICAgICAgIHRva2VuQ29udHJhY3RBZGRyZXNzOiBwYXJhbXMudG9rZW5Db250cmFjdEFkZHJlc3MsXG4gICAgICAgIGFwaUtleTogcGFyYW1zLmFwaUtleSxcbiAgICAgICAgcHJvZ3JhbUlkOiBwYXJhbXMucHJvZ3JhbUlkLFxuICAgICAgfTtcblxuICAgICAgbGV0IHJlY292ZXJ5VHJhbnNhY3Rpb247XG4gICAgICB0cnkge1xuICAgICAgICByZWNvdmVyeVRyYW5zYWN0aW9uID0gYXdhaXQgdGhpcy5yZWNvdmVyKHJlY292ZXJQYXJhbXMpO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBpZiAoXG4gICAgICAgICAgZS5tZXNzYWdlID09PSAnRGlkIG5vdCBmaW5kIGFkZHJlc3Mgd2l0aCBmdW5kcyB0byByZWNvdmVyJyB8fFxuICAgICAgICAgIGUubWVzc2FnZSA9PT0gJ0RpZCBub3QgZmluZCB0b2tlbiBhY2NvdW50IHRvIHJlY292ZXIgdG9rZW5zLCBwbGVhc2UgY2hlY2sgdG9rZW4gYWNjb3VudCcgfHxcbiAgICAgICAgICBlLm1lc3NhZ2UgPT09ICdOb3QgZW5vdWdoIHRva2VuIGZ1bmRzIHRvIHJlY292ZXInXG4gICAgICAgICkge1xuICAgICAgICAgIGxhc3RTY2FuSW5kZXggPSBpO1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG5cbiAgICAgIGlmIChpc1Vuc2lnbmVkU3dlZXApIHtcbiAgICAgICAgY29uc29saWRhdGlvblRyYW5zYWN0aW9ucy5wdXNoKChyZWNvdmVyeVRyYW5zYWN0aW9uIGFzIE1QQ1N3ZWVwVHhzKS50eFJlcXVlc3RzWzBdKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnNvbGlkYXRpb25UcmFuc2FjdGlvbnMucHVzaChyZWNvdmVyeVRyYW5zYWN0aW9uKTtcbiAgICAgIH1cblxuICAgICAgbGFzdFNjYW5JbmRleCA9IGk7XG4gICAgICBkdXJhYmxlTm9uY2VQdWJLZXlzSW5kZXgrKztcbiAgICAgIGlmIChkdXJhYmxlTm9uY2VQdWJLZXlzSW5kZXggPj0gZHVyYWJsZU5vbmNlUHViS2V5c0xlbmd0aCkge1xuICAgICAgICAvLyBubyBtb3JlIGF2YWlsYWJsZSBub25jZSBhY2NvdW50cyB0byBjcmVhdGUgdHJhbnNhY3Rpb25zXG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChjb25zb2xpZGF0aW9uVHJhbnNhY3Rpb25zLmxlbmd0aCA9PT0gMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdEaWQgbm90IGZpbmQgYW4gYWRkcmVzcyB3aXRoIGZ1bmRzIHRvIHJlY292ZXInKTtcbiAgICB9XG5cbiAgICBpZiAoaXNVbnNpZ25lZFN3ZWVwKSB7XG4gICAgICAvLyBsYXN0U2NhbkluZGV4IHdpbGwgYmUgdXNlZCB0byBpbmZvcm0gdXNlciB0aGUgbGFzdCBhZGRyZXNzIGluZGV4IHNjYW5uZWQgZm9yIGF2YWlsYWJsZSBmdW5kcyAoc28gdGhleSBjYW5cbiAgICAgIC8vIGFwcHJvcHJpYXRlbHkgYWRqdXN0IHRoZSBzY2FuIHJhbmdlIG9uIHRoZSBuZXh0IGl0ZXJhdGlvbiBvZiBjb25zb2xpZGF0aW9uIHJlY292ZXJpZXMpLiBJbiB0aGUgY2FzZSBvZiB1bnNpZ25lZFxuICAgICAgLy8gc3dlZXAgY29uc29saWRhdGlvbnMsIHRoaXMgbGFzdFNjYW5JbmRleCB3aWxsIGJlIHByb3ZpZGVkIGluIHRoZSBjb2luU3BlY2lmaWMgb2YgdGhlIGxhc3QgdHhuIG1hZGUuXG4gICAgICBjb25zdCBsYXN0VHJhbnNhY3Rpb25Db2luU3BlY2lmaWMgPSB7XG4gICAgICAgIGNvbW1vbktleWNoYWluOlxuICAgICAgICAgIGNvbnNvbGlkYXRpb25UcmFuc2FjdGlvbnNbY29uc29saWRhdGlvblRyYW5zYWN0aW9ucy5sZW5ndGggLSAxXS50cmFuc2FjdGlvbnNbMF0udW5zaWduZWRUeC5jb2luU3BlY2lmaWNcbiAgICAgICAgICAgIC5jb21tb25LZXljaGFpbixcbiAgICAgICAgbGFzdFNjYW5JbmRleDogbGFzdFNjYW5JbmRleCxcbiAgICAgIH07XG4gICAgICBjb25zb2xpZGF0aW9uVHJhbnNhY3Rpb25zW2NvbnNvbGlkYXRpb25UcmFuc2FjdGlvbnMubGVuZ3RoIC0gMV0udHJhbnNhY3Rpb25zWzBdLnVuc2lnbmVkVHguY29pblNwZWNpZmljID1cbiAgICAgICAgbGFzdFRyYW5zYWN0aW9uQ29pblNwZWNpZmljO1xuICAgICAgY29uc3QgY29uc29saWRhdGlvblN3ZWVwVHJhbnNhY3Rpb25zOiBNUENTd2VlcFR4cyA9IHsgdHhSZXF1ZXN0czogY29uc29saWRhdGlvblRyYW5zYWN0aW9ucyB9O1xuICAgICAgcmV0dXJuIGNvbnNvbGlkYXRpb25Td2VlcFRyYW5zYWN0aW9ucztcbiAgICB9XG5cbiAgICByZXR1cm4geyB0cmFuc2FjdGlvbnM6IGNvbnNvbGlkYXRpb25UcmFuc2FjdGlvbnMsIGxhc3RTY2FuSW5kZXggfTtcbiAgfVxuXG4gIGdldFRva2VuRW5hYmxlbWVudENvbmZpZygpOiBUb2tlbkVuYWJsZW1lbnRDb25maWcge1xuICAgIHJldHVybiB7XG4gICAgICByZXF1aXJlc1Rva2VuRW5hYmxlbWVudDogdHJ1ZSxcbiAgICAgIHN1cHBvcnRzTXVsdGlwbGVUb2tlbkVuYWJsZW1lbnRzOiB0cnVlLFxuICAgIH07XG4gIH1cblxuICBwcml2YXRlIGdldEJ1aWxkZXIoKTogVHJhbnNhY3Rpb25CdWlsZGVyRmFjdG9yeSB7XG4gICAgcmV0dXJuIG5ldyBUcmFuc2FjdGlvbkJ1aWxkZXJGYWN0b3J5KGNvaW5zLmdldCh0aGlzLmdldENoYWluKCkpKTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgYWRkUmVjb3ZlcnlTaWduYXR1cmUoXG4gICAgcGFyYW1zOiBTb2xSZWNvdmVyeU9wdGlvbnMsXG4gICAgdHhCdWlsZGVyOiBUcmFuc2FjdGlvbkJ1aWxkZXIsXG4gICAgYnM1OEVuY29kZWRQdWJsaWNLZXk6IHN0cmluZyxcbiAgICBpc01wY1YyOiBib29sZWFuLFxuICAgIHVuc2lnbmVkVHJhbnNhY3Rpb246IFRyYW5zYWN0aW9uLFxuICAgIGN1cnJQYXRoOiBzdHJpbmcsXG4gICAgYml0Z29LZXk6IHN0cmluZ1xuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBhc3NlcnQocGFyYW1zLnVzZXJLZXksICdtaXNzaW5nIHVzZXJLZXknKTtcbiAgICBhc3NlcnQocGFyYW1zLmJhY2t1cEtleSwgJ21pc3NpbmcgYmFja3VwS2V5Jyk7XG4gICAgY29uc3QgdXNlcktleSA9IHBhcmFtcy51c2VyS2V5LnJlcGxhY2UoL1xccy9nLCAnJyk7XG4gICAgY29uc3QgYmFja3VwS2V5ID0gcGFyYW1zLmJhY2t1cEtleS5yZXBsYWNlKC9cXHMvZywgJycpO1xuXG4gICAgaWYgKCFpc01wY1YyKSB7XG4gICAgICBsZXQgdXNlclBydjogc3RyaW5nO1xuICAgICAgdHJ5IHtcbiAgICAgICAgdXNlclBydiA9IGF3YWl0IHRoaXMuYml0Z28uZGVjcnlwdCh7XG4gICAgICAgICAgaW5wdXQ6IHVzZXJLZXksXG4gICAgICAgICAgcGFzc3dvcmQ6IHBhcmFtcy53YWxsZXRQYXNzcGhyYXNlISxcbiAgICAgICAgfSk7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgRXJyb3IgZGVjcnlwdGluZyB1c2VyIGtleWNoYWluOiAke2UubWVzc2FnZX1gKTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IHVzZXJTaWduaW5nTWF0ZXJpYWwgPSBKU09OLnBhcnNlKHVzZXJQcnYpIGFzIEVERFNBTWV0aG9kVHlwZXMuVXNlclNpZ25pbmdNYXRlcmlhbDtcblxuICAgICAgbGV0IGJhY2t1cFBydjogc3RyaW5nO1xuICAgICAgdHJ5IHtcbiAgICAgICAgYmFja3VwUHJ2ID0gYXdhaXQgdGhpcy5iaXRnby5kZWNyeXB0KHtcbiAgICAgICAgICBpbnB1dDogYmFja3VwS2V5LFxuICAgICAgICAgIHBhc3N3b3JkOiBwYXJhbXMud2FsbGV0UGFzc3BocmFzZSEsXG4gICAgICAgIH0pO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEVycm9yIGRlY3J5cHRpbmcgYmFja3VwIGtleWNoYWluOiAke2UubWVzc2FnZX1gKTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGJhY2t1cFNpZ25pbmdNYXRlcmlhbCA9IEpTT04ucGFyc2UoYmFja3VwUHJ2KSBhcyBFRERTQU1ldGhvZFR5cGVzLkJhY2t1cFNpZ25pbmdNYXRlcmlhbDtcblxuICAgICAgY29uc3Qgc2lnbmF0dXJlSGV4ID0gYXdhaXQgRUREU0FNZXRob2RzLmdldFRTU1NpZ25hdHVyZShcbiAgICAgICAgdXNlclNpZ25pbmdNYXRlcmlhbCxcbiAgICAgICAgYmFja3VwU2lnbmluZ01hdGVyaWFsLFxuICAgICAgICBjdXJyUGF0aCxcbiAgICAgICAgdW5zaWduZWRUcmFuc2FjdGlvblxuICAgICAgKTtcbiAgICAgIHR4QnVpbGRlci5hZGRTaWduYXR1cmUoeyBwdWI6IGJzNThFbmNvZGVkUHVibGljS2V5IH0gYXMgUHVibGljS2V5LCBzaWduYXR1cmVIZXgpO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCBzaWduYXR1cmUgPSBhd2FpdCBzaWduRWRkc2FNcGNWMlJlY292ZXJ5VHgoe1xuICAgICAgICBtZXNzYWdlOiB1bnNpZ25lZFRyYW5zYWN0aW9uLnNpZ25hYmxlUGF5bG9hZCxcbiAgICAgICAgdXNlcktleSxcbiAgICAgICAgYmFja3VwS2V5LFxuICAgICAgICB3YWxsZXRQYXNzcGhyYXNlOiBwYXJhbXMud2FsbGV0UGFzc3BocmFzZSEsXG4gICAgICAgIGJpdGdvS2V5LFxuICAgICAgICBkZXJpdmF0aW9uUGF0aDogY3VyclBhdGgsXG4gICAgICAgIGJpdGdvOiB0aGlzLmJpdGdvLFxuICAgICAgfSk7XG4gICAgICB0eEJ1aWxkZXIuYWRkU2lnbmF0dXJlKHsgcHViOiBiczU4RW5jb2RlZFB1YmxpY0tleSB9IGFzIFB1YmxpY0tleSwgc2lnbmF0dXJlKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGlzTXBjdjJTaWduaW5nTWF0ZXJpYWwoXG4gICAgdXNlcktleT86IHN0cmluZyxcbiAgICBiYWNrdXBLZXk/OiBzdHJpbmcsXG4gICAgd2FsbGV0UGFzc3BocmFzZT86IHN0cmluZ1xuICApOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICBpZiAoIXdhbGxldFBhc3NwaHJhc2UpIHJldHVybiBmYWxzZTtcbiAgICBpZiAoIXVzZXJLZXkpIHRocm93IG5ldyBFcnJvcignbWlzc2luZyB1c2VyS2V5Jyk7XG4gICAgaWYgKCFiYWNrdXBLZXkpIHRocm93IG5ldyBFcnJvcignbWlzc2luZyBiYWNrdXBLZXknKTtcbiAgICBjb25zdCBtYXRlcmlhbCA9IGF3YWl0IGdldEVkZHNhU2lnbmluZ01hdGVyaWFsKHVzZXJLZXkucmVwbGFjZSgvXFxzL2csICcnKSwgd2FsbGV0UGFzc3BocmFzZSwgdGhpcy5iaXRnbyk7XG4gICAgcmV0dXJuIG1hdGVyaWFsLnZlcnNpb24gPT09ICd2Mic7XG4gIH1cblxuICBhc3luYyBicm9hZGNhc3RUcmFuc2FjdGlvbih7XG4gICAgc2VyaWFsaXplZFNpZ25lZFRyYW5zYWN0aW9uLFxuICB9OiBCYXNlQnJvYWRjYXN0VHJhbnNhY3Rpb25PcHRpb25zKTogUHJvbWlzZTxCYXNlQnJvYWRjYXN0VHJhbnNhY3Rpb25SZXN1bHQ+IHtcbiAgICB2YWxpZGF0ZVJhd1RyYW5zYWN0aW9uKHNlcmlhbGl6ZWRTaWduZWRUcmFuc2FjdGlvbiwgdHJ1ZSwgdHJ1ZSk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLmdldERhdGFGcm9tTm9kZSh7XG4gICAgICBwYXlsb2FkOiB7XG4gICAgICAgIGlkOiAnMScsXG4gICAgICAgIGpzb25ycGM6ICcyLjAnLFxuICAgICAgICBtZXRob2Q6ICdzZW5kVHJhbnNhY3Rpb24nLFxuICAgICAgICBwYXJhbXM6IFtcbiAgICAgICAgICBzZXJpYWxpemVkU2lnbmVkVHJhbnNhY3Rpb24sXG4gICAgICAgICAge1xuICAgICAgICAgICAgZW5jb2Rpbmc6ICdiYXNlNjQnLFxuICAgICAgICAgIH0sXG4gICAgICAgIF0sXG4gICAgICB9LFxuICAgIH0pO1xuXG4gICAgaWYgKHJlc3BvbnNlLmJvZHkuZXJyb3IpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignRXJyb3IgYnJvYWRjYXN0aW5nIHRyYW5zYWN0aW9uOiAnICsgcmVzcG9uc2UuYm9keS5lcnJvci5tZXNzYWdlKTtcbiAgICB9XG5cbiAgICByZXR1cm4geyB0eElkOiByZXNwb25zZS5ib2R5LnJlc3VsdCB9O1xuICB9XG5cbiAgLyoqIEBpbmhlcml0RG9jICovXG4gIGF1ZGl0RGVjcnlwdGVkS2V5KHsgcHJ2LCBwdWJsaWNLZXksIG11bHRpU2lnVHlwZSB9OiBBdWRpdERlY3J5cHRlZEtleVBhcmFtcykge1xuICAgIGlmIChtdWx0aVNpZ1R5cGUgIT09ICd0c3MnKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1Vuc3VwcG9ydGVkIG11bHRpU2lnVHlwZScpO1xuICAgIH1cbiAgICBhdWRpdEVkZHNhUHJpdmF0ZUtleShwcnYsIHB1YmxpY0tleSA/PyAnJyk7XG4gIH1cblxuICAvKiogQGluaGVyaXREb2MgKi9cbiAgc2V0Q29pblNwZWNpZmljRmllbGRzSW5JbnRlbnQoaW50ZW50OiBQb3B1bGF0ZWRJbnRlbnQsIHBhcmFtczogUHJlYnVpbGRUcmFuc2FjdGlvbldpdGhJbnRlbnRPcHRpb25zKTogdm9pZCB7XG4gICAgLy8gSGFuZGxlIGN1c3RvbSBpbnN0cnVjdGlvbnMgZm9yIFNvbGFuYVxuICAgIGlmIChwYXJhbXMuc29sSW5zdHJ1Y3Rpb25zKSB7XG4gICAgICBpbnRlbnQuc29sSW5zdHJ1Y3Rpb25zID0gcGFyYW1zLnNvbEluc3RydWN0aW9ucztcbiAgICB9XG5cbiAgICAvLyBIYW5kbGUgdmVyc2lvbmVkIHRyYW5zYWN0aW9uIGRhdGEgZm9yIFNvbGFuYVxuICAgIGlmIChwYXJhbXMuc29sVmVyc2lvbmVkVHJhbnNhY3Rpb25EYXRhKSB7XG4gICAgICBpbnRlbnQuc29sVmVyc2lvbmVkVHJhbnNhY3Rpb25EYXRhID0gcGFyYW1zLnNvbFZlcnNpb25lZFRyYW5zYWN0aW9uRGF0YTtcbiAgICB9XG4gIH1cbn1cbiJdfQ==