@bitgo-beta/sdk-coin-sol 7.6.4-beta.70 → 7.6.4-beta.701

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