@bitgo-beta/sdk-coin-sol 7.6.4-beta.68 → 7.6.4-beta.680

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