@bitgo-beta/sdk-coin-sol 7.6.4-beta.7 → 7.6.4-beta.700

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