@bitgo-beta/sdk-coin-sol 7.6.4-beta.49 → 7.6.4-beta.490

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