@bitgo-beta/sdk-coin-sol 7.6.4-beta.31 → 7.6.4-beta.310
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.
- package/dist/cjs/src/bigint-buffer-guard.d.ts.map +1 -0
- package/dist/cjs/src/bigint-buffer-guard.js +29 -0
- package/dist/cjs/src/config/token2022StaticConfig.d.ts.map +1 -0
- package/dist/cjs/src/config/token2022StaticConfig.js +50 -0
- package/dist/cjs/src/index.d.ts.map +1 -0
- package/dist/{src → cjs/src}/index.js +1 -1
- package/dist/cjs/src/lib/ataInitializationBuilder.d.ts.map +1 -0
- package/dist/cjs/src/lib/ataInitializationBuilder.js +196 -0
- package/dist/cjs/src/lib/closeAtaBuilder.d.ts.map +1 -0
- package/dist/cjs/src/lib/closeAtaBuilder.js +69 -0
- package/dist/{src → cjs/src}/lib/constants.d.ts +24 -0
- package/dist/cjs/src/lib/constants.d.ts.map +1 -0
- package/dist/cjs/src/lib/constants.js +196 -0
- package/dist/cjs/src/lib/customInstructionBuilder.d.ts.map +1 -0
- package/dist/cjs/src/lib/customInstructionBuilder.js +289 -0
- package/dist/cjs/src/lib/explainTransactionWasm.d.ts +21 -0
- package/dist/cjs/src/lib/explainTransactionWasm.d.ts.map +1 -0
- package/dist/cjs/src/lib/explainTransactionWasm.js +264 -0
- package/dist/{src → cjs/src}/lib/iface.d.ts +20 -2
- package/dist/cjs/src/lib/iface.d.ts.map +1 -0
- package/dist/cjs/src/lib/iface.js +7 -0
- package/dist/{src → cjs/src}/lib/index.d.ts +1 -0
- package/dist/cjs/src/lib/index.d.ts.map +1 -0
- package/dist/{src → cjs/src}/lib/index.js +4 -2
- package/dist/{src → cjs/src}/lib/instructionParamsFactory.d.ts +1 -0
- package/dist/cjs/src/lib/instructionParamsFactory.d.ts.map +1 -0
- package/dist/cjs/src/lib/instructionParamsFactory.js +1059 -0
- package/dist/cjs/src/lib/jitoStakePoolOperations.d.ts.map +1 -0
- package/dist/cjs/src/lib/jitoStakePoolOperations.js +200 -0
- package/dist/cjs/src/lib/keyPair.d.ts.map +1 -0
- package/dist/cjs/src/lib/keyPair.js +63 -0
- package/dist/cjs/src/lib/messages/index.d.ts.map +1 -0
- package/dist/{src → cjs/src}/lib/messages/index.js +1 -1
- package/dist/cjs/src/lib/messages/messageBuilderFactory.d.ts.map +1 -0
- package/dist/cjs/src/lib/messages/messageBuilderFactory.js +19 -0
- package/dist/cjs/src/lib/recoverNestedAtaBuilder.d.ts +25 -0
- package/dist/cjs/src/lib/recoverNestedAtaBuilder.d.ts.map +1 -0
- package/dist/cjs/src/lib/recoverNestedAtaBuilder.js +90 -0
- package/dist/cjs/src/lib/solInstructionFactory.d.ts.map +1 -0
- package/dist/cjs/src/lib/solInstructionFactory.js +595 -0
- package/dist/cjs/src/lib/stakingActivateBuilder.d.ts.map +1 -0
- package/dist/cjs/src/lib/stakingActivateBuilder.js +120 -0
- package/dist/cjs/src/lib/stakingAuthorizeBuilder.d.ts.map +1 -0
- package/dist/cjs/src/lib/stakingAuthorizeBuilder.js +89 -0
- package/dist/cjs/src/lib/stakingDeactivateBuilder.d.ts.map +1 -0
- package/dist/cjs/src/lib/stakingDeactivateBuilder.js +208 -0
- package/dist/cjs/src/lib/stakingDelegateBuilder.d.ts.map +1 -0
- package/dist/cjs/src/lib/stakingDelegateBuilder.js +120 -0
- package/dist/cjs/src/lib/stakingRawMsgAuthorizeBuilder.d.ts.map +1 -0
- package/dist/cjs/src/lib/stakingRawMsgAuthorizeBuilder.js +110 -0
- package/dist/cjs/src/lib/stakingWithdrawBuilder.d.ts.map +1 -0
- package/dist/cjs/src/lib/stakingWithdrawBuilder.js +78 -0
- package/dist/cjs/src/lib/token2022Config.d.ts.map +1 -0
- package/dist/cjs/src/lib/token2022Config.js +27 -0
- package/dist/cjs/src/lib/tokenTransferBuilder.d.ts.map +1 -0
- package/dist/cjs/src/lib/tokenTransferBuilder.js +188 -0
- package/dist/cjs/src/lib/transaction.d.ts.map +1 -0
- package/dist/cjs/src/lib/transaction.js +612 -0
- package/dist/cjs/src/lib/transactionBuilder.d.ts.map +1 -0
- package/dist/cjs/src/lib/transactionBuilder.js +380 -0
- package/dist/{src → cjs/src}/lib/transactionBuilderFactory.d.ts +5 -0
- package/dist/cjs/src/lib/transactionBuilderFactory.d.ts.map +1 -0
- package/dist/cjs/src/lib/transactionBuilderFactory.js +209 -0
- package/dist/cjs/src/lib/transferBuilder.d.ts.map +1 -0
- package/dist/cjs/src/lib/transferBuilder.js +70 -0
- package/dist/cjs/src/lib/transferBuilderV2.d.ts.map +1 -0
- package/dist/cjs/src/lib/transferBuilderV2.js +210 -0
- package/dist/cjs/src/lib/utils.d.ts.map +1 -0
- package/dist/cjs/src/lib/utils.js +595 -0
- package/dist/cjs/src/lib/walletInitializationBuilder.d.ts.map +1 -0
- package/dist/cjs/src/lib/walletInitializationBuilder.js +71 -0
- package/dist/cjs/src/register.d.ts.map +1 -0
- package/dist/cjs/src/register.js +15 -0
- package/dist/{src → cjs/src}/sol.d.ts +40 -0
- package/dist/cjs/src/sol.d.ts.map +1 -0
- package/dist/cjs/src/sol.js +1402 -0
- package/dist/cjs/src/solToken.d.ts.map +1 -0
- package/dist/cjs/src/solToken.js +69 -0
- package/dist/cjs/src/tsol.d.ts.map +1 -0
- package/dist/cjs/src/tsol.js +24 -0
- package/dist/{test → cjs/test}/fixtures/sol.d.ts.map +1 -1
- package/dist/cjs/test/fixtures/sol.js +1433 -0
- package/dist/{test → cjs/test}/resources/sol.d.ts +27 -27
- package/dist/cjs/test/resources/sol.d.ts.map +1 -0
- package/dist/cjs/test/resources/sol.js +320 -0
- package/dist/cjs/test/unit/explainTransactionWasm.d.ts +5 -0
- package/dist/cjs/test/unit/explainTransactionWasm.d.ts.map +1 -0
- package/dist/cjs/test/unit/explainTransactionWasm.js +26 -0
- package/dist/cjs/test/unit/fixtures/solBackupKey.d.ts.map +1 -0
- package/dist/cjs/test/unit/fixtures/solBackupKey.js +8 -0
- package/dist/cjs/test/unit/getBuilderFactory.d.ts.map +1 -0
- package/dist/cjs/test/unit/getBuilderFactory.js +10 -0
- package/dist/cjs/test/unit/instructionParamsFactory.d.ts.map +1 -0
- package/dist/cjs/test/unit/instructionParamsFactory.js +412 -0
- package/dist/cjs/test/unit/instructionParamsFactory.staking.d.ts.map +1 -0
- package/dist/cjs/test/unit/instructionParamsFactory.staking.js +1059 -0
- package/dist/cjs/test/unit/jitoWasmVerification.d.ts +2 -0
- package/dist/cjs/test/unit/jitoWasmVerification.d.ts.map +1 -0
- package/dist/cjs/test/unit/jitoWasmVerification.js +78 -0
- package/dist/{test → cjs/test}/unit/keyPair.d.ts.map +1 -1
- package/dist/cjs/test/unit/keyPair.js +177 -0
- package/dist/cjs/test/unit/messages/messageBuilderFactory.d.ts.map +1 -0
- package/dist/cjs/test/unit/messages/messageBuilderFactory.js +118 -0
- package/dist/cjs/test/unit/messages/simpleMessageBuilder.d.ts.map +1 -0
- package/dist/cjs/test/unit/messages/simpleMessageBuilder.js +194 -0
- package/dist/{test → cjs/test}/unit/sol.d.ts.map +1 -1
- package/dist/cjs/test/unit/sol.js +3326 -0
- package/dist/cjs/test/unit/solInstructionFactory.d.ts.map +1 -0
- package/dist/cjs/test/unit/solInstructionFactory.js +454 -0
- package/dist/cjs/test/unit/solToken.d.ts.map +1 -0
- package/dist/cjs/test/unit/solToken.js +31 -0
- package/dist/cjs/test/unit/transaction.d.ts.map +1 -0
- package/dist/cjs/test/unit/transaction.js +1108 -0
- package/dist/cjs/test/unit/transactionBuilder/StakingWithdrawBuilder.d.ts.map +1 -0
- package/dist/cjs/test/unit/transactionBuilder/StakingWithdrawBuilder.js +202 -0
- package/dist/cjs/test/unit/transactionBuilder/ataInitBuilder.d.ts.map +1 -0
- package/dist/cjs/test/unit/transactionBuilder/ataInitBuilder.js +471 -0
- package/dist/cjs/test/unit/transactionBuilder/customInstructionBuilder.d.ts.map +1 -0
- package/dist/cjs/test/unit/transactionBuilder/customInstructionBuilder.js +413 -0
- package/dist/cjs/test/unit/transactionBuilder/stakingActivateBuilder.d.ts.map +1 -0
- package/dist/cjs/test/unit/transactionBuilder/stakingActivateBuilder.js +430 -0
- package/dist/cjs/test/unit/transactionBuilder/stakingAuthorizeBuilder.d.ts.map +1 -0
- package/dist/cjs/test/unit/transactionBuilder/stakingAuthorizeBuilder.js +157 -0
- package/dist/cjs/test/unit/transactionBuilder/stakingDeactivateBuilder.d.ts.map +1 -0
- package/dist/cjs/test/unit/transactionBuilder/stakingDeactivateBuilder.js +384 -0
- package/dist/cjs/test/unit/transactionBuilder/stakingDelegateBuilder.d.ts.map +1 -0
- package/dist/cjs/test/unit/transactionBuilder/stakingDelegateBuilder.js +224 -0
- package/dist/cjs/test/unit/transactionBuilder/stakingRawMsgAuthorizeBuilder.d.ts.map +1 -0
- package/dist/cjs/test/unit/transactionBuilder/stakingRawMsgAuthorizeBuilder.js +259 -0
- package/dist/cjs/test/unit/transactionBuilder/tokenTransferBuilder.d.ts.map +1 -0
- package/dist/cjs/test/unit/transactionBuilder/tokenTransferBuilder.js +787 -0
- package/dist/cjs/test/unit/transactionBuilder/transactionBuilder.d.ts.map +1 -0
- package/dist/cjs/test/unit/transactionBuilder/transactionBuilder.js +495 -0
- package/dist/cjs/test/unit/transactionBuilder/transferBuilder.d.ts.map +1 -0
- package/dist/cjs/test/unit/transactionBuilder/transferBuilder.js +286 -0
- package/dist/cjs/test/unit/transactionBuilder/transferBuilderV2.d.ts.map +1 -0
- package/dist/cjs/test/unit/transactionBuilder/transferBuilderV2.js +862 -0
- package/dist/cjs/test/unit/transactionBuilder/walletInitBuilder.d.ts.map +1 -0
- package/dist/cjs/test/unit/transactionBuilder/walletInitBuilder.js +259 -0
- package/dist/{test → cjs/test}/unit/utils.d.ts.map +1 -1
- package/dist/cjs/test/unit/utils.js +517 -0
- package/dist/cjs/test/unit/versionedTransaction.d.ts.map +1 -0
- package/dist/cjs/test/unit/versionedTransaction.js +207 -0
- package/dist/cjs/tsconfig.tsbuildinfo +1 -0
- package/dist/esm/bigint-buffer-guard.d.ts +1 -0
- package/dist/esm/config/token2022StaticConfig.d.ts +3 -0
- package/dist/esm/config/token2022StaticConfig.js +47 -0
- package/dist/esm/index.d.ts +7 -0
- package/dist/esm/index.js +7 -0
- package/dist/esm/lib/ataInitializationBuilder.d.ts +47 -0
- package/dist/esm/lib/ataInitializationBuilder.js +156 -0
- package/dist/esm/lib/closeAtaBuilder.d.ts +19 -0
- package/dist/esm/lib/closeAtaBuilder.js +62 -0
- package/dist/esm/lib/constants.d.ts +164 -0
- package/dist/esm/lib/constants.d.ts.map +1 -0
- package/dist/esm/lib/constants.js +193 -0
- package/dist/esm/lib/customInstructionBuilder.d.ts +72 -0
- package/dist/esm/lib/customInstructionBuilder.js +282 -0
- package/dist/esm/lib/explainTransactionWasm.d.ts +21 -0
- package/dist/esm/lib/explainTransactionWasm.d.ts.map +1 -0
- package/dist/esm/lib/explainTransactionWasm.js +261 -0
- package/dist/esm/lib/iface.d.ts +262 -0
- package/dist/esm/lib/iface.d.ts.map +1 -0
- package/dist/esm/lib/iface.js +3 -0
- package/dist/esm/lib/index.d.ts +23 -0
- package/dist/{src → esm}/lib/index.d.ts.map +1 -1
- package/dist/esm/lib/index.js +23 -0
- package/dist/esm/lib/instructionParamsFactory.d.ts +13 -0
- package/dist/{src → esm}/lib/instructionParamsFactory.d.ts.map +1 -1
- package/dist/esm/lib/instructionParamsFactory.js +1052 -0
- package/dist/esm/lib/jitoStakePoolOperations.d.ts +113 -0
- package/dist/esm/lib/jitoStakePoolOperations.js +189 -0
- package/dist/esm/lib/keyPair.d.ts +26 -0
- package/dist/esm/lib/keyPair.js +59 -0
- package/dist/esm/lib/messages/index.d.ts +2 -0
- package/dist/esm/lib/messages/index.js +2 -0
- package/dist/esm/lib/messages/messageBuilderFactory.d.ts +7 -0
- package/dist/{src → esm}/lib/messages/messageBuilderFactory.js +5 -9
- package/dist/esm/lib/recoverNestedAtaBuilder.d.ts +25 -0
- package/dist/esm/lib/recoverNestedAtaBuilder.d.ts.map +1 -0
- package/dist/esm/lib/recoverNestedAtaBuilder.js +83 -0
- package/dist/esm/lib/solInstructionFactory.d.ts +10 -0
- package/dist/esm/lib/solInstructionFactory.d.ts.map +1 -0
- package/dist/esm/lib/solInstructionFactory.js +589 -0
- package/dist/esm/lib/stakingActivateBuilder.d.ts +59 -0
- package/dist/esm/lib/stakingActivateBuilder.js +113 -0
- package/dist/esm/lib/stakingAuthorizeBuilder.d.ts +43 -0
- package/dist/esm/lib/stakingAuthorizeBuilder.js +82 -0
- package/dist/esm/lib/stakingDeactivateBuilder.d.ts +81 -0
- package/dist/{src → esm}/lib/stakingDeactivateBuilder.js +31 -38
- package/dist/esm/lib/stakingDelegateBuilder.d.ts +42 -0
- package/dist/esm/lib/stakingDelegateBuilder.js +113 -0
- package/dist/esm/lib/stakingRawMsgAuthorizeBuilder.d.ts +33 -0
- package/dist/esm/lib/stakingRawMsgAuthorizeBuilder.js +103 -0
- package/dist/esm/lib/stakingWithdrawBuilder.d.ts +31 -0
- package/dist/esm/lib/stakingWithdrawBuilder.js +71 -0
- package/dist/esm/lib/token2022Config.d.ts +44 -0
- package/dist/esm/lib/token2022Config.js +23 -0
- package/dist/esm/lib/tokenTransferBuilder.d.ts +41 -0
- package/dist/esm/lib/tokenTransferBuilder.js +181 -0
- package/dist/esm/lib/transaction.d.ts +103 -0
- package/dist/esm/lib/transaction.d.ts.map +1 -0
- package/dist/esm/lib/transaction.js +605 -0
- package/dist/esm/lib/transactionBuilder.d.ts +128 -0
- package/dist/esm/lib/transactionBuilder.js +373 -0
- package/dist/esm/lib/transactionBuilderFactory.d.ts +120 -0
- package/dist/esm/lib/transactionBuilderFactory.d.ts.map +1 -0
- package/dist/esm/lib/transactionBuilderFactory.js +205 -0
- package/dist/esm/lib/transferBuilder.d.ts +26 -0
- package/dist/esm/lib/transferBuilder.js +63 -0
- package/dist/esm/lib/transferBuilderV2.d.ts +43 -0
- package/dist/esm/lib/transferBuilderV2.js +203 -0
- package/dist/esm/lib/utils.d.ts +200 -0
- package/dist/{src → esm}/lib/utils.d.ts.map +1 -1
- package/dist/esm/lib/utils.js +558 -0
- package/dist/esm/lib/walletInitializationBuilder.d.ts +26 -0
- package/dist/esm/lib/walletInitializationBuilder.js +64 -0
- package/dist/esm/register.d.ts +3 -0
- package/dist/esm/register.js +11 -0
- package/dist/esm/sol.d.ts +267 -0
- package/dist/esm/sol.d.ts.map +1 -0
- package/dist/esm/sol.js +1361 -0
- package/dist/esm/solToken.d.ts +37 -0
- package/dist/esm/solToken.js +65 -0
- package/dist/esm/tsol.d.ts +11 -0
- package/dist/esm/tsol.js +20 -0
- package/package.json +34 -15
- package/dist/src/config/token2022StaticConfig.js +0 -50
- package/dist/src/lib/ataInitializationBuilder.js +0 -196
- package/dist/src/lib/closeAtaBuilder.js +0 -69
- package/dist/src/lib/constants.d.ts.map +0 -1
- package/dist/src/lib/constants.js +0 -171
- package/dist/src/lib/customInstructionBuilder.js +0 -289
- package/dist/src/lib/iface.d.ts.map +0 -1
- package/dist/src/lib/iface.js +0 -7
- package/dist/src/lib/instructionParamsFactory.js +0 -1036
- package/dist/src/lib/jitoStakePoolOperations.js +0 -200
- package/dist/src/lib/keyPair.js +0 -63
- package/dist/src/lib/solInstructionFactory.d.ts.map +0 -1
- package/dist/src/lib/solInstructionFactory.js +0 -572
- package/dist/src/lib/stakingActivateBuilder.js +0 -120
- package/dist/src/lib/stakingAuthorizeBuilder.js +0 -89
- package/dist/src/lib/stakingDelegateBuilder.js +0 -120
- package/dist/src/lib/stakingRawMsgAuthorizeBuilder.js +0 -110
- package/dist/src/lib/stakingWithdrawBuilder.js +0 -78
- package/dist/src/lib/token2022Config.js +0 -27
- package/dist/src/lib/tokenTransferBuilder.js +0 -188
- package/dist/src/lib/transaction.d.ts.map +0 -1
- package/dist/src/lib/transaction.js +0 -595
- package/dist/src/lib/transactionBuilder.js +0 -380
- package/dist/src/lib/transactionBuilderFactory.d.ts.map +0 -1
- package/dist/src/lib/transactionBuilderFactory.js +0 -202
- package/dist/src/lib/transferBuilder.js +0 -70
- package/dist/src/lib/transferBuilderV2.js +0 -210
- package/dist/src/lib/utils.js +0 -589
- package/dist/src/lib/walletInitializationBuilder.js +0 -71
- package/dist/src/register.js +0 -15
- package/dist/src/sol.d.ts.map +0 -1
- package/dist/src/sol.js +0 -1285
- package/dist/src/solToken.js +0 -69
- package/dist/src/tsol.js +0 -24
- package/dist/test/fixtures/sol.js +0 -1433
- package/dist/test/resources/sol.d.ts.map +0 -1
- package/dist/test/resources/sol.js +0 -320
- package/dist/test/unit/fixtures/solBackupKey.d.ts.map +0 -1
- package/dist/test/unit/fixtures/solBackupKey.js +0 -8
- package/dist/test/unit/getBuilderFactory.d.ts.map +0 -1
- package/dist/test/unit/getBuilderFactory.js +0 -10
- package/dist/test/unit/instructionParamsFactory.d.ts.map +0 -1
- package/dist/test/unit/instructionParamsFactory.js +0 -412
- package/dist/test/unit/instructionParamsFactory.staking.d.ts.map +0 -1
- package/dist/test/unit/instructionParamsFactory.staking.js +0 -1059
- package/dist/test/unit/keyPair.js +0 -177
- package/dist/test/unit/messages/messageBuilderFactory.d.ts.map +0 -1
- package/dist/test/unit/messages/messageBuilderFactory.js +0 -118
- package/dist/test/unit/messages/simpleMessageBuilder.d.ts.map +0 -1
- package/dist/test/unit/messages/simpleMessageBuilder.js +0 -194
- package/dist/test/unit/sol.js +0 -3108
- package/dist/test/unit/solInstructionFactory.d.ts.map +0 -1
- package/dist/test/unit/solInstructionFactory.js +0 -454
- package/dist/test/unit/solToken.d.ts.map +0 -1
- package/dist/test/unit/solToken.js +0 -31
- package/dist/test/unit/transaction.d.ts.map +0 -1
- package/dist/test/unit/transaction.js +0 -983
- package/dist/test/unit/transactionBuilder/StakingWithdrawBuilder.d.ts.map +0 -1
- package/dist/test/unit/transactionBuilder/StakingWithdrawBuilder.js +0 -202
- package/dist/test/unit/transactionBuilder/ataInitBuilder.d.ts.map +0 -1
- package/dist/test/unit/transactionBuilder/ataInitBuilder.js +0 -471
- package/dist/test/unit/transactionBuilder/customInstructionBuilder.d.ts.map +0 -1
- package/dist/test/unit/transactionBuilder/customInstructionBuilder.js +0 -413
- package/dist/test/unit/transactionBuilder/stakingActivateBuilder.d.ts.map +0 -1
- package/dist/test/unit/transactionBuilder/stakingActivateBuilder.js +0 -430
- package/dist/test/unit/transactionBuilder/stakingAuthorizeBuilder.d.ts.map +0 -1
- package/dist/test/unit/transactionBuilder/stakingAuthorizeBuilder.js +0 -157
- package/dist/test/unit/transactionBuilder/stakingDeactivateBuilder.d.ts.map +0 -1
- package/dist/test/unit/transactionBuilder/stakingDeactivateBuilder.js +0 -384
- package/dist/test/unit/transactionBuilder/stakingDelegateBuilder.d.ts.map +0 -1
- package/dist/test/unit/transactionBuilder/stakingDelegateBuilder.js +0 -224
- package/dist/test/unit/transactionBuilder/stakingRawMsgAuthorizeBuilder.d.ts.map +0 -1
- package/dist/test/unit/transactionBuilder/stakingRawMsgAuthorizeBuilder.js +0 -259
- package/dist/test/unit/transactionBuilder/tokenTransferBuilder.d.ts.map +0 -1
- package/dist/test/unit/transactionBuilder/tokenTransferBuilder.js +0 -787
- package/dist/test/unit/transactionBuilder/transactionBuilder.d.ts.map +0 -1
- package/dist/test/unit/transactionBuilder/transactionBuilder.js +0 -495
- package/dist/test/unit/transactionBuilder/transferBuilder.d.ts.map +0 -1
- package/dist/test/unit/transactionBuilder/transferBuilder.js +0 -286
- package/dist/test/unit/transactionBuilder/transferBuilderV2.d.ts.map +0 -1
- package/dist/test/unit/transactionBuilder/transferBuilderV2.js +0 -862
- package/dist/test/unit/transactionBuilder/walletInitBuilder.d.ts.map +0 -1
- package/dist/test/unit/transactionBuilder/walletInitBuilder.js +0 -259
- package/dist/test/unit/utils.js +0 -517
- package/dist/test/unit/versionedTransaction.d.ts.map +0 -1
- package/dist/test/unit/versionedTransaction.js +0 -207
- package/dist/tsconfig.tsbuildinfo +0 -1
- /package/dist/{src → cjs/src}/bigint-buffer-guard.d.ts +0 -0
- /package/dist/{src → cjs/src}/config/token2022StaticConfig.d.ts +0 -0
- /package/dist/{src → cjs/src}/index.d.ts +0 -0
- /package/dist/{src → cjs/src}/lib/ataInitializationBuilder.d.ts +0 -0
- /package/dist/{src → cjs/src}/lib/closeAtaBuilder.d.ts +0 -0
- /package/dist/{src → cjs/src}/lib/customInstructionBuilder.d.ts +0 -0
- /package/dist/{src → cjs/src}/lib/jitoStakePoolOperations.d.ts +0 -0
- /package/dist/{src → cjs/src}/lib/keyPair.d.ts +0 -0
- /package/dist/{src → cjs/src}/lib/messages/index.d.ts +0 -0
- /package/dist/{src → cjs/src}/lib/messages/messageBuilderFactory.d.ts +0 -0
- /package/dist/{src → cjs/src}/lib/solInstructionFactory.d.ts +0 -0
- /package/dist/{src → cjs/src}/lib/stakingActivateBuilder.d.ts +0 -0
- /package/dist/{src → cjs/src}/lib/stakingAuthorizeBuilder.d.ts +0 -0
- /package/dist/{src → cjs/src}/lib/stakingDeactivateBuilder.d.ts +0 -0
- /package/dist/{src → cjs/src}/lib/stakingDelegateBuilder.d.ts +0 -0
- /package/dist/{src → cjs/src}/lib/stakingRawMsgAuthorizeBuilder.d.ts +0 -0
- /package/dist/{src → cjs/src}/lib/stakingWithdrawBuilder.d.ts +0 -0
- /package/dist/{src → cjs/src}/lib/token2022Config.d.ts +0 -0
- /package/dist/{src → cjs/src}/lib/tokenTransferBuilder.d.ts +0 -0
- /package/dist/{src → cjs/src}/lib/transaction.d.ts +0 -0
- /package/dist/{src → cjs/src}/lib/transactionBuilder.d.ts +0 -0
- /package/dist/{src → cjs/src}/lib/transferBuilder.d.ts +0 -0
- /package/dist/{src → cjs/src}/lib/transferBuilderV2.d.ts +0 -0
- /package/dist/{src → cjs/src}/lib/utils.d.ts +0 -0
- /package/dist/{src → cjs/src}/lib/walletInitializationBuilder.d.ts +0 -0
- /package/dist/{src → cjs/src}/register.d.ts +0 -0
- /package/dist/{src → cjs/src}/solToken.d.ts +0 -0
- /package/dist/{src → cjs/src}/tsol.d.ts +0 -0
- /package/dist/{test → cjs/test}/fixtures/sol.d.ts +0 -0
- /package/dist/{test → cjs/test}/unit/fixtures/solBackupKey.d.ts +0 -0
- /package/dist/{test → cjs/test}/unit/getBuilderFactory.d.ts +0 -0
- /package/dist/{test → cjs/test}/unit/instructionParamsFactory.d.ts +0 -0
- /package/dist/{test → cjs/test}/unit/instructionParamsFactory.staking.d.ts +0 -0
- /package/dist/{test → cjs/test}/unit/keyPair.d.ts +0 -0
- /package/dist/{test → cjs/test}/unit/messages/messageBuilderFactory.d.ts +0 -0
- /package/dist/{test → cjs/test}/unit/messages/simpleMessageBuilder.d.ts +0 -0
- /package/dist/{test → cjs/test}/unit/sol.d.ts +0 -0
- /package/dist/{test → cjs/test}/unit/solInstructionFactory.d.ts +0 -0
- /package/dist/{test → cjs/test}/unit/solToken.d.ts +0 -0
- /package/dist/{test → cjs/test}/unit/transaction.d.ts +0 -0
- /package/dist/{test → cjs/test}/unit/transactionBuilder/StakingWithdrawBuilder.d.ts +0 -0
- /package/dist/{test → cjs/test}/unit/transactionBuilder/ataInitBuilder.d.ts +0 -0
- /package/dist/{test → cjs/test}/unit/transactionBuilder/customInstructionBuilder.d.ts +0 -0
- /package/dist/{test → cjs/test}/unit/transactionBuilder/stakingActivateBuilder.d.ts +0 -0
- /package/dist/{test → cjs/test}/unit/transactionBuilder/stakingAuthorizeBuilder.d.ts +0 -0
- /package/dist/{test → cjs/test}/unit/transactionBuilder/stakingDeactivateBuilder.d.ts +0 -0
- /package/dist/{test → cjs/test}/unit/transactionBuilder/stakingDelegateBuilder.d.ts +0 -0
- /package/dist/{test → cjs/test}/unit/transactionBuilder/stakingRawMsgAuthorizeBuilder.d.ts +0 -0
- /package/dist/{test → cjs/test}/unit/transactionBuilder/tokenTransferBuilder.d.ts +0 -0
- /package/dist/{test → cjs/test}/unit/transactionBuilder/transactionBuilder.d.ts +0 -0
- /package/dist/{test → cjs/test}/unit/transactionBuilder/transferBuilder.d.ts +0 -0
- /package/dist/{test → cjs/test}/unit/transactionBuilder/transferBuilderV2.d.ts +0 -0
- /package/dist/{test → cjs/test}/unit/transactionBuilder/walletInitBuilder.d.ts +0 -0
- /package/dist/{test → cjs/test}/unit/utils.d.ts +0 -0
- /package/dist/{test → cjs/test}/unit/versionedTransaction.d.ts +0 -0
- /package/dist/{src → esm}/bigint-buffer-guard.d.ts.map +0 -0
- /package/dist/{src → esm}/bigint-buffer-guard.js +0 -0
- /package/dist/{src → esm}/config/token2022StaticConfig.d.ts.map +0 -0
- /package/dist/{src → esm}/index.d.ts.map +0 -0
- /package/dist/{src → esm}/lib/ataInitializationBuilder.d.ts.map +0 -0
- /package/dist/{src → esm}/lib/closeAtaBuilder.d.ts.map +0 -0
- /package/dist/{src → esm}/lib/customInstructionBuilder.d.ts.map +0 -0
- /package/dist/{src → esm}/lib/jitoStakePoolOperations.d.ts.map +0 -0
- /package/dist/{src → esm}/lib/keyPair.d.ts.map +0 -0
- /package/dist/{src → esm}/lib/messages/index.d.ts.map +0 -0
- /package/dist/{src → esm}/lib/messages/messageBuilderFactory.d.ts.map +0 -0
- /package/dist/{src → esm}/lib/stakingActivateBuilder.d.ts.map +0 -0
- /package/dist/{src → esm}/lib/stakingAuthorizeBuilder.d.ts.map +0 -0
- /package/dist/{src → esm}/lib/stakingDeactivateBuilder.d.ts.map +0 -0
- /package/dist/{src → esm}/lib/stakingDelegateBuilder.d.ts.map +0 -0
- /package/dist/{src → esm}/lib/stakingRawMsgAuthorizeBuilder.d.ts.map +0 -0
- /package/dist/{src → esm}/lib/stakingWithdrawBuilder.d.ts.map +0 -0
- /package/dist/{src → esm}/lib/token2022Config.d.ts.map +0 -0
- /package/dist/{src → esm}/lib/tokenTransferBuilder.d.ts.map +0 -0
- /package/dist/{src → esm}/lib/transactionBuilder.d.ts.map +0 -0
- /package/dist/{src → esm}/lib/transferBuilder.d.ts.map +0 -0
- /package/dist/{src → esm}/lib/transferBuilderV2.d.ts.map +0 -0
- /package/dist/{src → esm}/lib/walletInitializationBuilder.d.ts.map +0 -0
- /package/dist/{src → esm}/register.d.ts.map +0 -0
- /package/dist/{src → esm}/solToken.d.ts.map +0 -0
- /package/dist/{src → esm}/tsol.d.ts.map +0 -0
package/dist/src/sol.js
DELETED
|
@@ -1,1285 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* @prettier
|
|
4
|
-
*/
|
|
5
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
6
|
-
if (k2 === undefined) k2 = k;
|
|
7
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
8
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
9
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
10
|
-
}
|
|
11
|
-
Object.defineProperty(o, k2, desc);
|
|
12
|
-
}) : (function(o, m, k, k2) {
|
|
13
|
-
if (k2 === undefined) k2 = k;
|
|
14
|
-
o[k2] = m[k];
|
|
15
|
-
}));
|
|
16
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
17
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
18
|
-
}) : function(o, v) {
|
|
19
|
-
o["default"] = v;
|
|
20
|
-
});
|
|
21
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
22
|
-
var ownKeys = function(o) {
|
|
23
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
24
|
-
var ar = [];
|
|
25
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
26
|
-
return ar;
|
|
27
|
-
};
|
|
28
|
-
return ownKeys(o);
|
|
29
|
-
};
|
|
30
|
-
return function (mod) {
|
|
31
|
-
if (mod && mod.__esModule) return mod;
|
|
32
|
-
var result = {};
|
|
33
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
34
|
-
__setModuleDefault(result, mod);
|
|
35
|
-
return result;
|
|
36
|
-
};
|
|
37
|
-
})();
|
|
38
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
39
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
40
|
-
};
|
|
41
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
-
exports.Sol = exports.DEFAULT_SCAN_FACTOR = void 0;
|
|
43
|
-
const spl_token_1 = require("@solana/spl-token");
|
|
44
|
-
const bignumber_js_1 = __importDefault(require("bignumber.js"));
|
|
45
|
-
const base58 = __importStar(require("bs58"));
|
|
46
|
-
const _ = __importStar(require("lodash"));
|
|
47
|
-
const request = __importStar(require("superagent"));
|
|
48
|
-
const sdk_core_1 = require("@bitgo-beta/sdk-core");
|
|
49
|
-
const sdk_lib_mpc_1 = require("@bitgo-beta/sdk-lib-mpc");
|
|
50
|
-
const statics_1 = require("@bitgo-beta/statics");
|
|
51
|
-
const lib_1 = require("./lib");
|
|
52
|
-
const utils_1 = require("./lib/utils");
|
|
53
|
-
exports.DEFAULT_SCAN_FACTOR = 20; // default number of receive addresses to scan for funds
|
|
54
|
-
const HEX_REGEX = /^[0-9a-fA-F]+$/;
|
|
55
|
-
const BLIND_SIGNING_TX_TYPES_TO_CHECK = { enabletoken: 'AssociatedTokenAccountInitialization' };
|
|
56
|
-
class Sol extends sdk_core_1.BaseCoin {
|
|
57
|
-
constructor(bitgo, staticsCoin) {
|
|
58
|
-
super(bitgo);
|
|
59
|
-
if (!staticsCoin) {
|
|
60
|
-
throw new Error('missing required constructor parameter staticsCoin');
|
|
61
|
-
}
|
|
62
|
-
this._staticsCoin = staticsCoin;
|
|
63
|
-
}
|
|
64
|
-
static createInstance(bitgo, staticsCoin) {
|
|
65
|
-
return new Sol(bitgo, staticsCoin);
|
|
66
|
-
}
|
|
67
|
-
allowsAccountConsolidations() {
|
|
68
|
-
return true;
|
|
69
|
-
}
|
|
70
|
-
supportsTss() {
|
|
71
|
-
return true;
|
|
72
|
-
}
|
|
73
|
-
/** @inheritDoc */
|
|
74
|
-
supportsMessageSigning() {
|
|
75
|
-
return true;
|
|
76
|
-
}
|
|
77
|
-
/** inherited doc */
|
|
78
|
-
getDefaultMultisigType() {
|
|
79
|
-
return sdk_core_1.multisigTypes.tss;
|
|
80
|
-
}
|
|
81
|
-
getMPCAlgorithm() {
|
|
82
|
-
return 'eddsa';
|
|
83
|
-
}
|
|
84
|
-
getChain() {
|
|
85
|
-
return this._staticsCoin.name;
|
|
86
|
-
}
|
|
87
|
-
getFamily() {
|
|
88
|
-
return this._staticsCoin.family;
|
|
89
|
-
}
|
|
90
|
-
getFullName() {
|
|
91
|
-
return this._staticsCoin.fullName;
|
|
92
|
-
}
|
|
93
|
-
getNetwork() {
|
|
94
|
-
return this._staticsCoin.network;
|
|
95
|
-
}
|
|
96
|
-
getBaseFactor() {
|
|
97
|
-
return Math.pow(10, this._staticsCoin.decimalPlaces);
|
|
98
|
-
}
|
|
99
|
-
verifyTxType(expectedTypeFromUserParams, actualTypeFromDecoded) {
|
|
100
|
-
const matchFromUserToDecodedType = BLIND_SIGNING_TX_TYPES_TO_CHECK[expectedTypeFromUserParams];
|
|
101
|
-
if (matchFromUserToDecodedType !== actualTypeFromDecoded) {
|
|
102
|
-
throw new Error(`Invalid transaction type on token enablement: expected "${matchFromUserToDecodedType}", got "${actualTypeFromDecoded}".`);
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
throwIfMissingTokenEnablementsOrReturn(explanation) {
|
|
106
|
-
if (!explanation.tokenEnablements || explanation.tokenEnablements.length === 0)
|
|
107
|
-
throw new Error('Missing tx token enablements data on token enablement tx prebuild');
|
|
108
|
-
return explanation.tokenEnablements;
|
|
109
|
-
}
|
|
110
|
-
throwIfMissingEnableTokenConfigOrReturn(txParams) {
|
|
111
|
-
if (!txParams.enableTokens || txParams.enableTokens.length === 0)
|
|
112
|
-
throw new Error('Missing enable token config');
|
|
113
|
-
return txParams.enableTokens;
|
|
114
|
-
}
|
|
115
|
-
verifyTokenName(tokenEnablementsPrebuild, enableTokensConfig) {
|
|
116
|
-
enableTokensConfig.forEach((enableTokenConfig) => {
|
|
117
|
-
const expectedTokenName = enableTokenConfig.name;
|
|
118
|
-
tokenEnablementsPrebuild.forEach((tokenEnablement) => {
|
|
119
|
-
if (!tokenEnablement.tokenName)
|
|
120
|
-
throw new Error('Missing token name on token enablement tx');
|
|
121
|
-
if (tokenEnablement.tokenName !== expectedTokenName)
|
|
122
|
-
throw new Error(`Invalid token name: expected ${expectedTokenName}, got ${tokenEnablement.tokenName} on token enablement tx`);
|
|
123
|
-
});
|
|
124
|
-
});
|
|
125
|
-
}
|
|
126
|
-
async verifyTokenAddress(tokenEnablementsPrebuild, enableTokensConfig) {
|
|
127
|
-
for (const enableTokenConfig of enableTokensConfig) {
|
|
128
|
-
const expectedTokenAddress = enableTokenConfig.address;
|
|
129
|
-
const expectedTokenName = enableTokenConfig.name;
|
|
130
|
-
if (!expectedTokenAddress)
|
|
131
|
-
throw new Error('Missing token address on token enablement tx');
|
|
132
|
-
if (!expectedTokenName)
|
|
133
|
-
throw new Error('Missing token name on token enablement tx');
|
|
134
|
-
for (const tokenEnablement of tokenEnablementsPrebuild) {
|
|
135
|
-
let tokenMintAddress;
|
|
136
|
-
try {
|
|
137
|
-
tokenMintAddress = (0, utils_1.getSolTokenFromTokenName)(expectedTokenName);
|
|
138
|
-
}
|
|
139
|
-
catch {
|
|
140
|
-
throw new Error(`Unable to derive ATA for token address: ${expectedTokenAddress}`);
|
|
141
|
-
}
|
|
142
|
-
if (!tokenMintAddress ||
|
|
143
|
-
tokenMintAddress.tokenAddress === undefined ||
|
|
144
|
-
tokenMintAddress.programId === undefined) {
|
|
145
|
-
throw new Error(`Unable to get token mint address for ${expectedTokenName}`);
|
|
146
|
-
}
|
|
147
|
-
let ata;
|
|
148
|
-
try {
|
|
149
|
-
ata = await (0, utils_1.getAssociatedTokenAccountAddress)(tokenMintAddress.tokenAddress, expectedTokenAddress, true, tokenMintAddress.programId);
|
|
150
|
-
}
|
|
151
|
-
catch {
|
|
152
|
-
throw new Error(`Unable to derive ATA for token address: ${expectedTokenAddress}`);
|
|
153
|
-
}
|
|
154
|
-
if (ata !== tokenEnablement.address) {
|
|
155
|
-
throw new Error(`Invalid token address: expected ${ata}, got ${tokenEnablement.address} on token enablement tx`);
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
hasSolVersionedTransactionData(txParams) {
|
|
161
|
-
return 'solVersionedTransactionData' in txParams && txParams.solVersionedTransactionData !== undefined;
|
|
162
|
-
}
|
|
163
|
-
/**
|
|
164
|
-
* Verify a versioned Solana transaction with basic structural validation
|
|
165
|
-
* @param params - verification parameters
|
|
166
|
-
* @returns true if verification passes
|
|
167
|
-
*/
|
|
168
|
-
async verifyVersionedTransaction(params) {
|
|
169
|
-
const { txParams, txPrebuild } = params;
|
|
170
|
-
const rawTx = txPrebuild.txBase64 || txPrebuild.txHex;
|
|
171
|
-
if (!rawTx) {
|
|
172
|
-
throw new Error('missing required tx prebuild property txBase64 or txHex');
|
|
173
|
-
}
|
|
174
|
-
// Validate that the versioned transaction data is well-formed
|
|
175
|
-
if (!this.hasSolVersionedTransactionData(txParams)) {
|
|
176
|
-
throw new Error('solVersionedTransactionData is required for versioned transaction verification');
|
|
177
|
-
}
|
|
178
|
-
const versionedData = txParams.solVersionedTransactionData;
|
|
179
|
-
if (!versionedData.versionedInstructions || versionedData.versionedInstructions.length === 0) {
|
|
180
|
-
throw new Error('versioned transaction must have at least one instruction');
|
|
181
|
-
}
|
|
182
|
-
if (!versionedData.staticAccountKeys || versionedData.staticAccountKeys.length === 0) {
|
|
183
|
-
throw new Error('versioned transaction must have at least one static account key');
|
|
184
|
-
}
|
|
185
|
-
if (!versionedData.messageHeader) {
|
|
186
|
-
throw new Error('versioned transaction must have a message header');
|
|
187
|
-
}
|
|
188
|
-
// Validate that we can deserialize the transaction
|
|
189
|
-
let rawTxBase64 = rawTx;
|
|
190
|
-
if (HEX_REGEX.test(rawTx)) {
|
|
191
|
-
rawTxBase64 = Buffer.from(rawTx, 'hex').toString('base64');
|
|
192
|
-
}
|
|
193
|
-
try {
|
|
194
|
-
const txBytes = Buffer.from(rawTxBase64, 'base64');
|
|
195
|
-
if (txBytes.length < 1) {
|
|
196
|
-
throw new Error('transaction bytes are empty');
|
|
197
|
-
}
|
|
198
|
-
// Check version byte (after signatures)
|
|
199
|
-
const numSignatures = txBytes[0];
|
|
200
|
-
const signatureSize = 64;
|
|
201
|
-
const versionByteOffset = 1 + numSignatures * signatureSize;
|
|
202
|
-
if (txBytes.length <= versionByteOffset) {
|
|
203
|
-
throw new Error('transaction bytes are too short to contain version byte');
|
|
204
|
-
}
|
|
205
|
-
const versionByte = txBytes[versionByteOffset];
|
|
206
|
-
const isVersioned = (versionByte & 0x80) !== 0;
|
|
207
|
-
if (!isVersioned) {
|
|
208
|
-
throw new Error('transaction does not have versioned format');
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
catch (error) {
|
|
212
|
-
throw new Error(`failed to validate versioned transaction format: ${error.message}`);
|
|
213
|
-
}
|
|
214
|
-
return true;
|
|
215
|
-
}
|
|
216
|
-
async verifyTransaction(params) {
|
|
217
|
-
// asset name to transfer amount map
|
|
218
|
-
const totalAmount = {};
|
|
219
|
-
const coinConfig = statics_1.coins.get(this.getChain());
|
|
220
|
-
const { txParams: txParams, txPrebuild: txPrebuild, memo: memo, durableNonce: durableNonce, verification: verificationOptions, } = params;
|
|
221
|
-
if (this.hasSolVersionedTransactionData(txParams)) {
|
|
222
|
-
return this.verifyVersionedTransaction(params);
|
|
223
|
-
}
|
|
224
|
-
const transaction = new lib_1.Transaction(coinConfig);
|
|
225
|
-
const rawTx = txPrebuild.txBase64 || txPrebuild.txHex;
|
|
226
|
-
const consolidateId = txPrebuild.consolidateId;
|
|
227
|
-
const walletRootAddress = params.wallet.coinSpecific()?.rootAddress;
|
|
228
|
-
if (!rawTx) {
|
|
229
|
-
throw new Error('missing required tx prebuild property txBase64 or txHex');
|
|
230
|
-
}
|
|
231
|
-
let rawTxBase64 = rawTx;
|
|
232
|
-
if (HEX_REGEX.test(rawTx)) {
|
|
233
|
-
rawTxBase64 = Buffer.from(rawTx, 'hex').toString('base64');
|
|
234
|
-
}
|
|
235
|
-
transaction.fromRawTransaction(rawTxBase64);
|
|
236
|
-
const explainedTx = transaction.explainTransaction();
|
|
237
|
-
if (txParams.type === 'enabletoken' && verificationOptions?.verifyTokenEnablement) {
|
|
238
|
-
this.verifyTxType(txParams.type, explainedTx.type);
|
|
239
|
-
const tokenEnablementsPrebuild = this.throwIfMissingTokenEnablementsOrReturn(explainedTx);
|
|
240
|
-
const enableTokensConfig = this.throwIfMissingEnableTokenConfigOrReturn(txParams);
|
|
241
|
-
this.verifyTokenName(tokenEnablementsPrebuild, enableTokensConfig);
|
|
242
|
-
await this.verifyTokenAddress(tokenEnablementsPrebuild, enableTokensConfig);
|
|
243
|
-
}
|
|
244
|
-
// users do not input recipients for consolidation requests as they are generated by the server
|
|
245
|
-
if (txParams.recipients !== undefined) {
|
|
246
|
-
const filteredRecipients = txParams.recipients?.map((recipient) => _.pick(recipient, ['address', 'amount', 'tokenName']));
|
|
247
|
-
const filteredOutputs = explainedTx.outputs.map((output) => _.pick(output, ['address', 'amount', 'tokenName']));
|
|
248
|
-
if (filteredRecipients.length !== filteredOutputs.length) {
|
|
249
|
-
throw new Error('Number of tx outputs does not match with number of txParams recipients');
|
|
250
|
-
}
|
|
251
|
-
// For each recipient, check if it's a token tx (tokenName will exist if so)
|
|
252
|
-
// If it is a token tx, verify that the recipient address equals the derived address from explainedTx
|
|
253
|
-
// Derive the ATA if it is a native address and confirm it is equal to the explained tx recipient
|
|
254
|
-
const recipientChecks = await Promise.all(filteredRecipients.map(async (recipientFromUser, index) => {
|
|
255
|
-
const recipientFromTx = filteredOutputs[index]; // This address should be an ATA
|
|
256
|
-
// Compare the BigNumber values because amount is (string | number)
|
|
257
|
-
const userAmount = new bignumber_js_1.default(recipientFromUser.amount);
|
|
258
|
-
const txAmount = new bignumber_js_1.default(recipientFromTx.amount);
|
|
259
|
-
if (!userAmount.isEqualTo(txAmount)) {
|
|
260
|
-
return false;
|
|
261
|
-
}
|
|
262
|
-
// Compare the addresses and tokenNames
|
|
263
|
-
// Else if the addresses are not the same, check the derived ATA for parity
|
|
264
|
-
if (recipientFromUser.address === recipientFromTx.address &&
|
|
265
|
-
recipientFromUser.tokenName === recipientFromTx.tokenName) {
|
|
266
|
-
return true;
|
|
267
|
-
}
|
|
268
|
-
else if (recipientFromUser.address !== recipientFromTx.address && recipientFromUser.tokenName) {
|
|
269
|
-
// Try to check if the user's derived ATA is equal to the tx recipient address
|
|
270
|
-
// If getAssociatedTokenAccountAddress throws an error, then we are unable to derive the ATA for that address.
|
|
271
|
-
// Return false and throw an error if that is the case.
|
|
272
|
-
try {
|
|
273
|
-
const tokenMintAddress = (0, utils_1.getSolTokenFromTokenName)(recipientFromUser.tokenName);
|
|
274
|
-
return (0, utils_1.getAssociatedTokenAccountAddress)(tokenMintAddress.tokenAddress, recipientFromUser.address, true, tokenMintAddress.programId).then((ata) => {
|
|
275
|
-
return ata === recipientFromTx.address;
|
|
276
|
-
});
|
|
277
|
-
}
|
|
278
|
-
catch {
|
|
279
|
-
// Unable to derive ATA
|
|
280
|
-
return false;
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
return false;
|
|
284
|
-
}));
|
|
285
|
-
if (recipientChecks.includes(false)) {
|
|
286
|
-
throw new Error('Tx outputs does not match with expected txParams recipients');
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
else if (verificationOptions?.consolidationToBaseAddress) {
|
|
290
|
-
//verify funds are sent to walletRootAddress for a consolidation
|
|
291
|
-
const filteredOutputs = explainedTx.outputs.map((output) => _.pick(output, ['address', 'amount', 'tokenName']));
|
|
292
|
-
// Cache to store already derived ATA addresses
|
|
293
|
-
const ataAddressCache = {};
|
|
294
|
-
for (const output of filteredOutputs) {
|
|
295
|
-
if (output.tokenName) {
|
|
296
|
-
// Check cache first before deriving ATA address
|
|
297
|
-
if (!ataAddressCache[output.tokenName]) {
|
|
298
|
-
const tokenMintAddress = (0, utils_1.getSolTokenFromTokenName)(output.tokenName);
|
|
299
|
-
if (tokenMintAddress?.tokenAddress && tokenMintAddress?.programId) {
|
|
300
|
-
ataAddressCache[output.tokenName] = await (0, utils_1.getAssociatedTokenAccountAddress)(tokenMintAddress.tokenAddress, walletRootAddress, true, tokenMintAddress.programId);
|
|
301
|
-
}
|
|
302
|
-
else {
|
|
303
|
-
throw new Error(`Unable to get token information for ${output.tokenName}`);
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
if (ataAddressCache[output.tokenName] !== output.address) {
|
|
307
|
-
throw new Error('tx outputs does not match with expected address');
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
|
-
else if (output.address !== walletRootAddress) {
|
|
311
|
-
throw new Error('tx outputs does not match with expected address');
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
const transactionJson = transaction.toJson();
|
|
316
|
-
if (memo && memo.value !== explainedTx.memo) {
|
|
317
|
-
throw new Error('Tx memo does not match with expected txParams recipient memo');
|
|
318
|
-
}
|
|
319
|
-
if (txParams.recipients) {
|
|
320
|
-
for (const recipients of txParams.recipients) {
|
|
321
|
-
// totalAmount based on each token
|
|
322
|
-
const assetName = recipients.tokenName || this.getChain();
|
|
323
|
-
const amount = totalAmount[assetName] || new bignumber_js_1.default(0);
|
|
324
|
-
totalAmount[assetName] = amount.plus(recipients.amount);
|
|
325
|
-
}
|
|
326
|
-
// total output amount from explainedTx
|
|
327
|
-
const explainedTxTotal = {};
|
|
328
|
-
for (const output of explainedTx.outputs) {
|
|
329
|
-
// total output amount based on each token
|
|
330
|
-
const assetName = output.tokenName || this.getChain();
|
|
331
|
-
const amount = explainedTxTotal[assetName] || new bignumber_js_1.default(0);
|
|
332
|
-
explainedTxTotal[assetName] = amount.plus(output.amount);
|
|
333
|
-
}
|
|
334
|
-
if (!_.isEqual(explainedTxTotal, totalAmount)) {
|
|
335
|
-
throw new Error('Tx total amount does not match with expected total amount field');
|
|
336
|
-
}
|
|
337
|
-
}
|
|
338
|
-
// For non-consolidate transactions, feePayer must be the wallet's root address
|
|
339
|
-
if (consolidateId === undefined && transactionJson.feePayer !== walletRootAddress) {
|
|
340
|
-
throw new Error('Tx fee payer is not the wallet root address');
|
|
341
|
-
}
|
|
342
|
-
if (durableNonce && !_.isEqual(explainedTx.durableNonce, durableNonce)) {
|
|
343
|
-
throw new Error('Tx durableNonce does not match with param durableNonce');
|
|
344
|
-
}
|
|
345
|
-
return true;
|
|
346
|
-
}
|
|
347
|
-
async isWalletAddress(params) {
|
|
348
|
-
return (0, sdk_core_1.verifyEddsaTssWalletAddress)(params, (address) => this.isValidAddress(address), (publicKey) => this.getAddressFromPublicKey(publicKey));
|
|
349
|
-
}
|
|
350
|
-
/**
|
|
351
|
-
* Converts a Solana public key to an address
|
|
352
|
-
* @param publicKey Hex-encoded public key (64 hex characters = 32 bytes)
|
|
353
|
-
* @returns Base58-encoded Solana address
|
|
354
|
-
*/
|
|
355
|
-
getAddressFromPublicKey(publicKey) {
|
|
356
|
-
const publicKeyBuffer = Buffer.from(publicKey, 'hex');
|
|
357
|
-
return base58.encode(publicKeyBuffer);
|
|
358
|
-
}
|
|
359
|
-
/**
|
|
360
|
-
* Generate Solana key pair
|
|
361
|
-
*
|
|
362
|
-
* @param {Buffer} seed - Seed from which the new SolKeyPair should be generated, otherwise a random seed is used
|
|
363
|
-
* @returns {Object} object with generated pub and prv
|
|
364
|
-
*/
|
|
365
|
-
generateKeyPair(seed) {
|
|
366
|
-
const result = seed ? new lib_1.KeyPair({ seed }).getKeys() : new lib_1.KeyPair().getKeys();
|
|
367
|
-
return result;
|
|
368
|
-
}
|
|
369
|
-
/**
|
|
370
|
-
* Return boolean indicating whether input is valid public key for the coin
|
|
371
|
-
*
|
|
372
|
-
* @param {string} pub the prv to be checked
|
|
373
|
-
* @returns is it valid?
|
|
374
|
-
*/
|
|
375
|
-
isValidPub(pub) {
|
|
376
|
-
return (0, utils_1.isValidPublicKey)(pub);
|
|
377
|
-
}
|
|
378
|
-
/**
|
|
379
|
-
* Return boolean indicating whether input is valid private key for the coin
|
|
380
|
-
*
|
|
381
|
-
* @param {string} prv the prv to be checked
|
|
382
|
-
* @returns is it valid?
|
|
383
|
-
*/
|
|
384
|
-
isValidPrv(prv) {
|
|
385
|
-
return (0, utils_1.isValidPrivateKey)(prv);
|
|
386
|
-
}
|
|
387
|
-
isValidAddress(address) {
|
|
388
|
-
return (0, utils_1.isValidAddress)(address);
|
|
389
|
-
}
|
|
390
|
-
async signMessage(key, message) {
|
|
391
|
-
const solKeypair = new lib_1.KeyPair({ prv: key.prv });
|
|
392
|
-
if (Buffer.isBuffer(message)) {
|
|
393
|
-
message = base58.encode(message);
|
|
394
|
-
}
|
|
395
|
-
return Buffer.from(solKeypair.signMessage(message));
|
|
396
|
-
}
|
|
397
|
-
/**
|
|
398
|
-
* Signs Solana transaction
|
|
399
|
-
* @param params
|
|
400
|
-
* @param callback
|
|
401
|
-
*/
|
|
402
|
-
async signTransaction(params) {
|
|
403
|
-
const factory = this.getBuilder();
|
|
404
|
-
const rawTx = params.txPrebuild.txHex || params.txPrebuild.txBase64;
|
|
405
|
-
const txBuilder = factory.from(rawTx);
|
|
406
|
-
txBuilder.sign({ key: params.prv });
|
|
407
|
-
const transaction = await txBuilder.build();
|
|
408
|
-
if (!transaction) {
|
|
409
|
-
throw new Error('Invalid transaction');
|
|
410
|
-
}
|
|
411
|
-
const serializedTx = transaction.toBroadcastFormat();
|
|
412
|
-
return {
|
|
413
|
-
txHex: serializedTx,
|
|
414
|
-
};
|
|
415
|
-
}
|
|
416
|
-
async parseTransaction(params) {
|
|
417
|
-
const transactionExplanation = await this.explainTransaction({
|
|
418
|
-
txBase64: params.txBase64,
|
|
419
|
-
feeInfo: params.feeInfo,
|
|
420
|
-
tokenAccountRentExemptAmount: params.tokenAccountRentExemptAmount,
|
|
421
|
-
});
|
|
422
|
-
if (!transactionExplanation) {
|
|
423
|
-
throw new Error('Invalid transaction');
|
|
424
|
-
}
|
|
425
|
-
const solTransaction = transactionExplanation;
|
|
426
|
-
if (solTransaction.outputs.length <= 0) {
|
|
427
|
-
return {
|
|
428
|
-
inputs: [],
|
|
429
|
-
outputs: [],
|
|
430
|
-
};
|
|
431
|
-
}
|
|
432
|
-
const senderAddress = solTransaction.outputs[0].address;
|
|
433
|
-
const feeAmount = new bignumber_js_1.default(solTransaction.fee.fee);
|
|
434
|
-
// assume 1 sender, who is also the fee payer
|
|
435
|
-
const inputs = [
|
|
436
|
-
{
|
|
437
|
-
address: senderAddress,
|
|
438
|
-
amount: new bignumber_js_1.default(solTransaction.outputAmount).plus(feeAmount).toNumber(),
|
|
439
|
-
},
|
|
440
|
-
];
|
|
441
|
-
const outputs = solTransaction.outputs.map(({ address, amount, tokenName }) => {
|
|
442
|
-
const output = { address, amount };
|
|
443
|
-
if (tokenName) {
|
|
444
|
-
output.tokenName = tokenName;
|
|
445
|
-
}
|
|
446
|
-
return output;
|
|
447
|
-
});
|
|
448
|
-
return {
|
|
449
|
-
inputs,
|
|
450
|
-
outputs,
|
|
451
|
-
};
|
|
452
|
-
}
|
|
453
|
-
/**
|
|
454
|
-
* Explain a Solana transaction from txBase64
|
|
455
|
-
* @param params
|
|
456
|
-
*/
|
|
457
|
-
async explainTransaction(params) {
|
|
458
|
-
const factory = this.getBuilder();
|
|
459
|
-
let rebuiltTransaction;
|
|
460
|
-
try {
|
|
461
|
-
const transactionBuilder = factory.from(params.txBase64);
|
|
462
|
-
if (transactionBuilder instanceof lib_1.TransactionBuilder) {
|
|
463
|
-
const txBuilder = transactionBuilder;
|
|
464
|
-
txBuilder.fee({ amount: params.feeInfo.fee });
|
|
465
|
-
if (params.tokenAccountRentExemptAmount) {
|
|
466
|
-
txBuilder.associatedTokenAccountRent(params.tokenAccountRentExemptAmount);
|
|
467
|
-
}
|
|
468
|
-
}
|
|
469
|
-
rebuiltTransaction = await transactionBuilder.build();
|
|
470
|
-
}
|
|
471
|
-
catch (e) {
|
|
472
|
-
console.log(e);
|
|
473
|
-
throw new Error('Invalid transaction');
|
|
474
|
-
}
|
|
475
|
-
const explainedTransaction = rebuiltTransaction.explainTransaction();
|
|
476
|
-
return explainedTransaction;
|
|
477
|
-
}
|
|
478
|
-
/** @inheritDoc */
|
|
479
|
-
async getSignablePayload(serializedTx) {
|
|
480
|
-
const factory = this.getBuilder();
|
|
481
|
-
const rebuiltTransaction = await factory.from(serializedTx).build();
|
|
482
|
-
return rebuiltTransaction.signablePayload;
|
|
483
|
-
}
|
|
484
|
-
/** @inheritDoc */
|
|
485
|
-
async presignTransaction(params) {
|
|
486
|
-
// Hot wallet txns are only valid for 1-2 minutes.
|
|
487
|
-
// To buy more time, we rebuild the transaction with a new blockhash right before we sign.
|
|
488
|
-
if (params.walletData.type !== 'hot') {
|
|
489
|
-
return Promise.resolve(params);
|
|
490
|
-
}
|
|
491
|
-
const txRequestId = params.txPrebuild?.txRequestId;
|
|
492
|
-
if (txRequestId === undefined) {
|
|
493
|
-
throw new Error('Missing txRequestId');
|
|
494
|
-
}
|
|
495
|
-
const { tssUtils } = params;
|
|
496
|
-
await tssUtils.deleteSignatureShares(txRequestId);
|
|
497
|
-
const recreated = await tssUtils.getTxRequest(txRequestId);
|
|
498
|
-
let txHex = '';
|
|
499
|
-
if (recreated.unsignedTxs) {
|
|
500
|
-
txHex = recreated.unsignedTxs[0]?.serializedTxHex;
|
|
501
|
-
}
|
|
502
|
-
else {
|
|
503
|
-
txHex = recreated.transactions ? recreated.transactions[0]?.unsignedTx.serializedTxHex : '';
|
|
504
|
-
}
|
|
505
|
-
if (!txHex) {
|
|
506
|
-
throw new Error('Missing serialized tx hex');
|
|
507
|
-
}
|
|
508
|
-
return Promise.resolve({
|
|
509
|
-
...params,
|
|
510
|
-
txPrebuild: recreated,
|
|
511
|
-
txHex,
|
|
512
|
-
});
|
|
513
|
-
}
|
|
514
|
-
getPublicNodeUrl(apiKey) {
|
|
515
|
-
if (apiKey) {
|
|
516
|
-
return sdk_core_1.Environments[this.bitgo.getEnv()].solAlchemyNodeUrl + `/${apiKey}`;
|
|
517
|
-
}
|
|
518
|
-
return sdk_core_1.Environments[this.bitgo.getEnv()].solNodeUrl;
|
|
519
|
-
}
|
|
520
|
-
/**
|
|
521
|
-
* Make a request to one of the public SOL nodes available
|
|
522
|
-
* @param params.payload
|
|
523
|
-
*/
|
|
524
|
-
async getDataFromNode(params, apiKey) {
|
|
525
|
-
const nodeUrl = this.getPublicNodeUrl(apiKey);
|
|
526
|
-
try {
|
|
527
|
-
return await request.post(nodeUrl).send(params.payload);
|
|
528
|
-
}
|
|
529
|
-
catch (e) {
|
|
530
|
-
console.debug(e);
|
|
531
|
-
}
|
|
532
|
-
throw new Error(`Unable to call endpoint: '/' from node: ${nodeUrl}`);
|
|
533
|
-
}
|
|
534
|
-
async getBlockhash(apiKey) {
|
|
535
|
-
const response = await this.getDataFromNode({
|
|
536
|
-
payload: {
|
|
537
|
-
id: '1',
|
|
538
|
-
jsonrpc: '2.0',
|
|
539
|
-
method: 'getLatestBlockhash',
|
|
540
|
-
params: [
|
|
541
|
-
{
|
|
542
|
-
commitment: 'finalized',
|
|
543
|
-
},
|
|
544
|
-
],
|
|
545
|
-
},
|
|
546
|
-
}, apiKey);
|
|
547
|
-
if (response.status !== 200) {
|
|
548
|
-
throw new Error('Account not found');
|
|
549
|
-
}
|
|
550
|
-
return response.body.result.value.blockhash;
|
|
551
|
-
}
|
|
552
|
-
async getFeeForMessage(message, apiKey) {
|
|
553
|
-
const response = await this.getDataFromNode({
|
|
554
|
-
payload: {
|
|
555
|
-
id: '1',
|
|
556
|
-
jsonrpc: '2.0',
|
|
557
|
-
method: 'getFeeForMessage',
|
|
558
|
-
params: [
|
|
559
|
-
message,
|
|
560
|
-
{
|
|
561
|
-
commitment: 'finalized',
|
|
562
|
-
},
|
|
563
|
-
],
|
|
564
|
-
},
|
|
565
|
-
}, apiKey);
|
|
566
|
-
if (response.status !== 200) {
|
|
567
|
-
throw new Error('Account not found');
|
|
568
|
-
}
|
|
569
|
-
return response.body.result.value;
|
|
570
|
-
}
|
|
571
|
-
async getRentExemptAmount(apiKey) {
|
|
572
|
-
const response = await this.getDataFromNode({
|
|
573
|
-
payload: {
|
|
574
|
-
jsonrpc: '2.0',
|
|
575
|
-
id: '1',
|
|
576
|
-
method: 'getMinimumBalanceForRentExemption',
|
|
577
|
-
params: [165],
|
|
578
|
-
},
|
|
579
|
-
}, apiKey);
|
|
580
|
-
if (response.status !== 200 || response.error) {
|
|
581
|
-
throw new Error(JSON.stringify(response.error));
|
|
582
|
-
}
|
|
583
|
-
return response.body.result;
|
|
584
|
-
}
|
|
585
|
-
async getAccountBalance(pubKey, apiKey) {
|
|
586
|
-
const response = await this.getDataFromNode({
|
|
587
|
-
payload: {
|
|
588
|
-
id: '1',
|
|
589
|
-
jsonrpc: '2.0',
|
|
590
|
-
method: 'getBalance',
|
|
591
|
-
params: [pubKey],
|
|
592
|
-
},
|
|
593
|
-
}, apiKey);
|
|
594
|
-
if (response.status !== 200) {
|
|
595
|
-
throw new Error('Account not found');
|
|
596
|
-
}
|
|
597
|
-
return response.body.result.value;
|
|
598
|
-
}
|
|
599
|
-
async getAccountInfo(pubKey, apiKey) {
|
|
600
|
-
const response = await this.getDataFromNode({
|
|
601
|
-
payload: {
|
|
602
|
-
id: '1',
|
|
603
|
-
jsonrpc: '2.0',
|
|
604
|
-
method: 'getAccountInfo',
|
|
605
|
-
params: [
|
|
606
|
-
pubKey,
|
|
607
|
-
{
|
|
608
|
-
encoding: 'jsonParsed',
|
|
609
|
-
},
|
|
610
|
-
],
|
|
611
|
-
},
|
|
612
|
-
}, apiKey);
|
|
613
|
-
if (response.status !== 200) {
|
|
614
|
-
throw new Error('Account not found');
|
|
615
|
-
}
|
|
616
|
-
return {
|
|
617
|
-
authority: response.body.result.value.data.parsed.info.authority,
|
|
618
|
-
blockhash: response.body.result.value.data.parsed.info.blockhash,
|
|
619
|
-
};
|
|
620
|
-
}
|
|
621
|
-
async getTokenAccountsByOwner(pubKey = '', programId = '', apiKey) {
|
|
622
|
-
const response = await this.getDataFromNode({
|
|
623
|
-
payload: {
|
|
624
|
-
id: '1',
|
|
625
|
-
jsonrpc: '2.0',
|
|
626
|
-
method: 'getTokenAccountsByOwner',
|
|
627
|
-
params: [
|
|
628
|
-
pubKey,
|
|
629
|
-
{
|
|
630
|
-
programId: programId.toString().toLowerCase() === spl_token_1.TOKEN_2022_PROGRAM_ID.toString().toLowerCase()
|
|
631
|
-
? spl_token_1.TOKEN_2022_PROGRAM_ID.toString()
|
|
632
|
-
: spl_token_1.TOKEN_PROGRAM_ID.toString(),
|
|
633
|
-
},
|
|
634
|
-
{
|
|
635
|
-
encoding: 'jsonParsed',
|
|
636
|
-
},
|
|
637
|
-
],
|
|
638
|
-
},
|
|
639
|
-
}, apiKey);
|
|
640
|
-
if (response.status !== 200) {
|
|
641
|
-
throw new Error('Account not found');
|
|
642
|
-
}
|
|
643
|
-
if (response.body.result.value.length !== 0) {
|
|
644
|
-
const tokenAccounts = [];
|
|
645
|
-
for (const tokenAccount of response.body.result.value) {
|
|
646
|
-
tokenAccounts.push({ info: tokenAccount.account.data.parsed.info, pubKey: tokenAccount.pubKey });
|
|
647
|
-
}
|
|
648
|
-
return tokenAccounts;
|
|
649
|
-
}
|
|
650
|
-
return [];
|
|
651
|
-
}
|
|
652
|
-
async getTokenAccountInfo(pubKey, apiKey) {
|
|
653
|
-
const response = await this.getDataFromNode({
|
|
654
|
-
payload: {
|
|
655
|
-
id: '1',
|
|
656
|
-
jsonrpc: '2.0',
|
|
657
|
-
method: 'getAccountInfo',
|
|
658
|
-
params: [
|
|
659
|
-
pubKey,
|
|
660
|
-
{
|
|
661
|
-
encoding: 'jsonParsed',
|
|
662
|
-
},
|
|
663
|
-
],
|
|
664
|
-
},
|
|
665
|
-
}, apiKey);
|
|
666
|
-
if (response.status !== 200) {
|
|
667
|
-
throw new Error('Account not found');
|
|
668
|
-
}
|
|
669
|
-
return {
|
|
670
|
-
pubKey: pubKey,
|
|
671
|
-
info: response.body.result.value.data.parsed.info,
|
|
672
|
-
};
|
|
673
|
-
}
|
|
674
|
-
/** inherited doc */
|
|
675
|
-
async createBroadcastableSweepTransaction(params) {
|
|
676
|
-
if (!params.signatureShares) {
|
|
677
|
-
('Missing transaction(s)');
|
|
678
|
-
}
|
|
679
|
-
const req = params.signatureShares;
|
|
680
|
-
const broadcastableTransactions = [];
|
|
681
|
-
let lastScanIndex = 0;
|
|
682
|
-
for (let i = 0; i < req.length; i++) {
|
|
683
|
-
const MPC = await sdk_core_1.EDDSAMethods.getInitializedMpcInstance();
|
|
684
|
-
const transaction = req[i].txRequest.transactions[0].unsignedTx;
|
|
685
|
-
if (!req[i].ovc || !req[i].ovc[0].eddsaSignature) {
|
|
686
|
-
throw new Error('Missing signature(s)');
|
|
687
|
-
}
|
|
688
|
-
const signature = req[i].ovc[0].eddsaSignature;
|
|
689
|
-
if (!transaction.signableHex) {
|
|
690
|
-
throw new Error('Missing signable hex');
|
|
691
|
-
}
|
|
692
|
-
const messageBuffer = Buffer.from(transaction.signableHex, 'hex');
|
|
693
|
-
const result = MPC.verify(messageBuffer, signature);
|
|
694
|
-
if (!result) {
|
|
695
|
-
throw new Error('Invalid signature');
|
|
696
|
-
}
|
|
697
|
-
const signatureHex = Buffer.concat([Buffer.from(signature.R, 'hex'), Buffer.from(signature.sigma, 'hex')]);
|
|
698
|
-
const txBuilder = this.getBuilder().from(transaction.serializedTx);
|
|
699
|
-
if (!transaction.coinSpecific?.commonKeychain) {
|
|
700
|
-
throw new Error('Missing common keychain');
|
|
701
|
-
}
|
|
702
|
-
const commonKeychain = transaction.coinSpecific.commonKeychain;
|
|
703
|
-
if (!transaction.derivationPath) {
|
|
704
|
-
throw new Error('Missing derivation path');
|
|
705
|
-
}
|
|
706
|
-
const derivationPath = transaction.derivationPath;
|
|
707
|
-
const accountId = MPC.deriveUnhardened(commonKeychain, derivationPath).slice(0, 64);
|
|
708
|
-
const bs58EncodedPublicKey = new lib_1.KeyPair({ pub: accountId }).getAddress();
|
|
709
|
-
// add combined signature from ovc
|
|
710
|
-
const publicKeyObj = { pub: bs58EncodedPublicKey };
|
|
711
|
-
txBuilder.addSignature(publicKeyObj, signatureHex);
|
|
712
|
-
const signedTransaction = await txBuilder.build();
|
|
713
|
-
const serializedTx = signedTransaction.toBroadcastFormat();
|
|
714
|
-
broadcastableTransactions.push({
|
|
715
|
-
serializedTx: serializedTx,
|
|
716
|
-
scanIndex: transaction.scanIndex,
|
|
717
|
-
});
|
|
718
|
-
if (i === req.length - 1 && transaction.coinSpecific.lastScanIndex) {
|
|
719
|
-
lastScanIndex = transaction.coinSpecific.lastScanIndex;
|
|
720
|
-
}
|
|
721
|
-
}
|
|
722
|
-
return { transactions: broadcastableTransactions, lastScanIndex };
|
|
723
|
-
}
|
|
724
|
-
/**
|
|
725
|
-
* Builds a funds recovery transaction without BitGo
|
|
726
|
-
* @param {SolRecoveryOptions} params parameters needed to construct and
|
|
727
|
-
* (maybe) sign the transaction
|
|
728
|
-
*
|
|
729
|
-
* @returns {MPCTx | MPCSweepTxs} the serialized transaction hex string and index
|
|
730
|
-
* of the address being swept
|
|
731
|
-
*/
|
|
732
|
-
async recover(params) {
|
|
733
|
-
if (!params.bitgoKey) {
|
|
734
|
-
throw new Error('missing bitgoKey');
|
|
735
|
-
}
|
|
736
|
-
if (!params.recoveryDestination || !this.isValidAddress(params.recoveryDestination)) {
|
|
737
|
-
throw new Error('invalid recoveryDestination');
|
|
738
|
-
}
|
|
739
|
-
const bitgoKey = params.bitgoKey.replace(/\s/g, '');
|
|
740
|
-
const isUnsignedSweep = !params.userKey && !params.backupKey && !params.walletPassphrase;
|
|
741
|
-
// Build the transaction
|
|
742
|
-
const MPC = await sdk_core_1.EDDSAMethods.getInitializedMpcInstance();
|
|
743
|
-
let balance = 0;
|
|
744
|
-
const index = params.index || 0;
|
|
745
|
-
const currPath = params.seed ? (0, sdk_lib_mpc_1.getDerivationPath)(params.seed) + `/${index}` : `m/${index}`;
|
|
746
|
-
const accountId = MPC.deriveUnhardened(bitgoKey, currPath).slice(0, 64);
|
|
747
|
-
const bs58EncodedPublicKey = new lib_1.KeyPair({ pub: accountId }).getAddress();
|
|
748
|
-
balance = await this.getAccountBalance(bs58EncodedPublicKey, params.apiKey);
|
|
749
|
-
const factory = this.getBuilder();
|
|
750
|
-
const walletCoin = this.getChain();
|
|
751
|
-
let txBuilder;
|
|
752
|
-
let blockhash = await this.getBlockhash(params.apiKey);
|
|
753
|
-
let rentExemptAmount;
|
|
754
|
-
let authority = '';
|
|
755
|
-
let totalFee = new bignumber_js_1.default(0);
|
|
756
|
-
let totalFeeForTokenRecovery = new bignumber_js_1.default(0);
|
|
757
|
-
// check for possible token recovery, recover the token provide by user
|
|
758
|
-
if (params.tokenContractAddress) {
|
|
759
|
-
let isUnsupportedToken = false;
|
|
760
|
-
const tokenAccounts = await this.getTokenAccountsByOwner(bs58EncodedPublicKey, params.programId, params.apiKey);
|
|
761
|
-
if (tokenAccounts.length !== 0) {
|
|
762
|
-
// there exists token accounts on the given address, but need to check certain conditions:
|
|
763
|
-
// 1. if there is a recoverable balance
|
|
764
|
-
// 2. if the token is supported by bitgo
|
|
765
|
-
const recovereableTokenAccounts = [];
|
|
766
|
-
for (const tokenAccount of tokenAccounts) {
|
|
767
|
-
if (params.tokenContractAddress === tokenAccount.info.mint) {
|
|
768
|
-
const tokenAmount = new bignumber_js_1.default(tokenAccount.info.tokenAmount.amount);
|
|
769
|
-
const network = this.getNetwork();
|
|
770
|
-
const token = (0, utils_1.getSolTokenFromAddress)(tokenAccount.info.mint, network); // todo(WIN-5894) fix for ams
|
|
771
|
-
if (!token) {
|
|
772
|
-
isUnsupportedToken = true;
|
|
773
|
-
}
|
|
774
|
-
if (tokenAmount.gt(new bignumber_js_1.default(0))) {
|
|
775
|
-
tokenAccount.tokenName = token?.name || 'Unsupported Token';
|
|
776
|
-
recovereableTokenAccounts.push(tokenAccount);
|
|
777
|
-
}
|
|
778
|
-
break;
|
|
779
|
-
}
|
|
780
|
-
}
|
|
781
|
-
if (recovereableTokenAccounts.length !== 0) {
|
|
782
|
-
rentExemptAmount = await this.getRentExemptAmount(params.apiKey);
|
|
783
|
-
txBuilder = factory
|
|
784
|
-
.getTokenTransferBuilder()
|
|
785
|
-
.nonce(blockhash)
|
|
786
|
-
.sender(bs58EncodedPublicKey)
|
|
787
|
-
.associatedTokenAccountRent(rentExemptAmount.toString())
|
|
788
|
-
.feePayer(bs58EncodedPublicKey);
|
|
789
|
-
// need to get all token accounts of the recipient address and need to create them if they do not exist
|
|
790
|
-
const recipientTokenAccounts = await this.getTokenAccountsByOwner(params.recoveryDestination, params.programId, params.apiKey);
|
|
791
|
-
for (const tokenAccount of recovereableTokenAccounts) {
|
|
792
|
-
let recipientTokenAccountExists = false;
|
|
793
|
-
for (const recipientTokenAccount of recipientTokenAccounts) {
|
|
794
|
-
if (recipientTokenAccount.info.mint === tokenAccount.info.mint) {
|
|
795
|
-
recipientTokenAccountExists = true;
|
|
796
|
-
break;
|
|
797
|
-
}
|
|
798
|
-
}
|
|
799
|
-
const recipientTokenAccount = await (0, utils_1.getAssociatedTokenAccountAddress)(tokenAccount.info.mint, params.recoveryDestination, false, params.programId?.toString());
|
|
800
|
-
const tokenName = tokenAccount.tokenName;
|
|
801
|
-
const sendParams = {
|
|
802
|
-
address: recipientTokenAccount,
|
|
803
|
-
amount: tokenAccount.info.tokenAmount.amount,
|
|
804
|
-
tokenName,
|
|
805
|
-
...(isUnsupportedToken
|
|
806
|
-
? {
|
|
807
|
-
tokenAddress: tokenAccount.info.mint,
|
|
808
|
-
programId: params.programId?.toString(),
|
|
809
|
-
decimalPlaces: tokenAccount.info.tokenAmount.decimals,
|
|
810
|
-
}
|
|
811
|
-
: {}),
|
|
812
|
-
};
|
|
813
|
-
txBuilder.send(sendParams);
|
|
814
|
-
if (!recipientTokenAccountExists) {
|
|
815
|
-
// recipient token account does not exist for token and must be created
|
|
816
|
-
txBuilder.createAssociatedTokenAccount({
|
|
817
|
-
ownerAddress: params.recoveryDestination,
|
|
818
|
-
tokenName: tokenName,
|
|
819
|
-
...(isUnsupportedToken ? { tokenAddress: tokenAccount.info.mint } : {}),
|
|
820
|
-
programId: params.programId?.toString().toLowerCase() === spl_token_1.TOKEN_2022_PROGRAM_ID.toString().toLowerCase()
|
|
821
|
-
? spl_token_1.TOKEN_2022_PROGRAM_ID.toString()
|
|
822
|
-
: spl_token_1.TOKEN_PROGRAM_ID.toString(),
|
|
823
|
-
});
|
|
824
|
-
// add rent exempt amount to total fee for each token account that has to be created
|
|
825
|
-
totalFeeForTokenRecovery = totalFeeForTokenRecovery.plus(rentExemptAmount);
|
|
826
|
-
}
|
|
827
|
-
}
|
|
828
|
-
}
|
|
829
|
-
else {
|
|
830
|
-
throw Error('Not enough token funds to recover');
|
|
831
|
-
}
|
|
832
|
-
}
|
|
833
|
-
else {
|
|
834
|
-
// there are no recoverable token accounts , need to check if there are tokens to recover
|
|
835
|
-
throw Error('Did not find token account to recover tokens, please check token account');
|
|
836
|
-
}
|
|
837
|
-
}
|
|
838
|
-
else {
|
|
839
|
-
txBuilder = factory
|
|
840
|
-
.getTransferBuilder()
|
|
841
|
-
.nonce(blockhash)
|
|
842
|
-
.sender(bs58EncodedPublicKey)
|
|
843
|
-
.send({ address: params.recoveryDestination, amount: balance.toString() })
|
|
844
|
-
.feePayer(bs58EncodedPublicKey);
|
|
845
|
-
}
|
|
846
|
-
if (params.durableNonce) {
|
|
847
|
-
const durableNonceInfo = await this.getAccountInfo(params.durableNonce.publicKey, params.apiKey);
|
|
848
|
-
blockhash = durableNonceInfo.blockhash;
|
|
849
|
-
authority = durableNonceInfo.authority;
|
|
850
|
-
txBuilder.nonce(blockhash, {
|
|
851
|
-
walletNonceAddress: params.durableNonce.publicKey,
|
|
852
|
-
authWalletAddress: authority,
|
|
853
|
-
});
|
|
854
|
-
}
|
|
855
|
-
// build the transaction without fee
|
|
856
|
-
const unsignedTransactionWithoutFee = (await txBuilder.build());
|
|
857
|
-
const serializedMessage = unsignedTransactionWithoutFee.solTransaction.serializeMessage().toString('base64');
|
|
858
|
-
const baseFee = await this.getFeeForMessage(serializedMessage, params.apiKey);
|
|
859
|
-
const feePerSignature = params.durableNonce ? baseFee / 2 : baseFee;
|
|
860
|
-
totalFee = totalFee.plus(new bignumber_js_1.default(baseFee));
|
|
861
|
-
totalFeeForTokenRecovery = totalFeeForTokenRecovery.plus(new bignumber_js_1.default(baseFee));
|
|
862
|
-
if (totalFee.gt(balance)) {
|
|
863
|
-
throw Error('Did not find address with funds to recover');
|
|
864
|
-
}
|
|
865
|
-
if (params.tokenContractAddress) {
|
|
866
|
-
// Check if there is sufficient native solana to recover tokens
|
|
867
|
-
if (new bignumber_js_1.default(balance).lt(totalFeeForTokenRecovery)) {
|
|
868
|
-
throw Error('Not enough funds to pay for recover tokens fees, have: ' +
|
|
869
|
-
balance +
|
|
870
|
-
' need: ' +
|
|
871
|
-
totalFeeForTokenRecovery.toString());
|
|
872
|
-
}
|
|
873
|
-
txBuilder.fee({ amount: feePerSignature });
|
|
874
|
-
}
|
|
875
|
-
else {
|
|
876
|
-
const netAmount = new bignumber_js_1.default(balance).minus(totalFee);
|
|
877
|
-
txBuilder = factory
|
|
878
|
-
.getTransferBuilder()
|
|
879
|
-
.nonce(blockhash)
|
|
880
|
-
.sender(bs58EncodedPublicKey)
|
|
881
|
-
.send({ address: params.recoveryDestination, amount: netAmount.toString() })
|
|
882
|
-
.feePayer(bs58EncodedPublicKey)
|
|
883
|
-
.fee({ amount: feePerSignature });
|
|
884
|
-
if (params.durableNonce) {
|
|
885
|
-
txBuilder.nonce(blockhash, {
|
|
886
|
-
walletNonceAddress: params.durableNonce.publicKey,
|
|
887
|
-
authWalletAddress: authority,
|
|
888
|
-
});
|
|
889
|
-
}
|
|
890
|
-
}
|
|
891
|
-
if (!isUnsignedSweep) {
|
|
892
|
-
// Sign the txn
|
|
893
|
-
if (!params.userKey) {
|
|
894
|
-
throw new Error('missing userKey');
|
|
895
|
-
}
|
|
896
|
-
if (!params.backupKey) {
|
|
897
|
-
throw new Error('missing backupKey');
|
|
898
|
-
}
|
|
899
|
-
if (!params.walletPassphrase) {
|
|
900
|
-
throw new Error('missing wallet passphrase');
|
|
901
|
-
}
|
|
902
|
-
// build the transaction with fee
|
|
903
|
-
const unsignedTransaction = (await txBuilder.build());
|
|
904
|
-
const userKey = params.userKey.replace(/\s/g, '');
|
|
905
|
-
const backupKey = params.backupKey.replace(/\s/g, '');
|
|
906
|
-
// Decrypt private keys from KeyCard values
|
|
907
|
-
let userPrv;
|
|
908
|
-
try {
|
|
909
|
-
userPrv = this.bitgo.decrypt({
|
|
910
|
-
input: userKey,
|
|
911
|
-
password: params.walletPassphrase,
|
|
912
|
-
});
|
|
913
|
-
}
|
|
914
|
-
catch (e) {
|
|
915
|
-
throw new Error(`Error decrypting user keychain: ${e.message}`);
|
|
916
|
-
}
|
|
917
|
-
const userSigningMaterial = JSON.parse(userPrv);
|
|
918
|
-
let backupPrv;
|
|
919
|
-
try {
|
|
920
|
-
backupPrv = this.bitgo.decrypt({
|
|
921
|
-
input: backupKey,
|
|
922
|
-
password: params.walletPassphrase,
|
|
923
|
-
});
|
|
924
|
-
}
|
|
925
|
-
catch (e) {
|
|
926
|
-
throw new Error(`Error decrypting backup keychain: ${e.message}`);
|
|
927
|
-
}
|
|
928
|
-
const backupSigningMaterial = JSON.parse(backupPrv);
|
|
929
|
-
const signatureHex = await sdk_core_1.EDDSAMethods.getTSSSignature(userSigningMaterial, backupSigningMaterial, currPath, unsignedTransaction);
|
|
930
|
-
const publicKeyObj = { pub: bs58EncodedPublicKey };
|
|
931
|
-
txBuilder.addSignature(publicKeyObj, signatureHex);
|
|
932
|
-
}
|
|
933
|
-
if (params.durableNonce) {
|
|
934
|
-
// add durable nonce account signature
|
|
935
|
-
txBuilder.sign({ key: params.durableNonce.secretKey });
|
|
936
|
-
}
|
|
937
|
-
const completedTransaction = await txBuilder.build();
|
|
938
|
-
const serializedTx = completedTransaction.toBroadcastFormat();
|
|
939
|
-
const derivationPath = params.seed ? (0, sdk_lib_mpc_1.getDerivationPath)(params.seed) + `/${index}` : `m/${index}`;
|
|
940
|
-
const inputs = [];
|
|
941
|
-
for (const input of completedTransaction.inputs) {
|
|
942
|
-
inputs.push({
|
|
943
|
-
address: input.address,
|
|
944
|
-
valueString: input.value,
|
|
945
|
-
value: new bignumber_js_1.default(input.value).toNumber(),
|
|
946
|
-
});
|
|
947
|
-
}
|
|
948
|
-
const outputs = [];
|
|
949
|
-
for (const output of completedTransaction.outputs) {
|
|
950
|
-
outputs.push({
|
|
951
|
-
address: output.address,
|
|
952
|
-
valueString: output.value,
|
|
953
|
-
coinName: output.coin ? output.coin : walletCoin,
|
|
954
|
-
});
|
|
955
|
-
}
|
|
956
|
-
const spendAmount = completedTransaction.inputs.length === 1 ? completedTransaction.inputs[0].value : 0;
|
|
957
|
-
const parsedTx = { inputs: inputs, outputs: outputs, spendAmount: spendAmount, type: '' };
|
|
958
|
-
const feeInfo = { fee: totalFeeForTokenRecovery.toNumber(), feeString: totalFee.toString() };
|
|
959
|
-
const coinSpecific = { commonKeychain: bitgoKey };
|
|
960
|
-
if (isUnsignedSweep) {
|
|
961
|
-
const transaction = {
|
|
962
|
-
serializedTx: serializedTx,
|
|
963
|
-
scanIndex: index,
|
|
964
|
-
coin: walletCoin,
|
|
965
|
-
signableHex: completedTransaction.signablePayload.toString('hex'),
|
|
966
|
-
derivationPath: derivationPath,
|
|
967
|
-
parsedTx: parsedTx,
|
|
968
|
-
feeInfo: feeInfo,
|
|
969
|
-
coinSpecific: coinSpecific,
|
|
970
|
-
};
|
|
971
|
-
const unsignedTx = { unsignedTx: transaction, signatureShares: [] };
|
|
972
|
-
const transactions = [unsignedTx];
|
|
973
|
-
const txRequest = {
|
|
974
|
-
transactions: transactions,
|
|
975
|
-
walletCoin: walletCoin,
|
|
976
|
-
};
|
|
977
|
-
const txRequests = { txRequests: [txRequest] };
|
|
978
|
-
return txRequests;
|
|
979
|
-
}
|
|
980
|
-
const transaction = {
|
|
981
|
-
serializedTx: serializedTx,
|
|
982
|
-
scanIndex: index,
|
|
983
|
-
};
|
|
984
|
-
return transaction;
|
|
985
|
-
}
|
|
986
|
-
/**
|
|
987
|
-
* Builds a funds recovery transaction without BitGo
|
|
988
|
-
* @param {SolRecoveryOptions} params parameters needed to construct and
|
|
989
|
-
* (maybe) sign the transaction
|
|
990
|
-
*
|
|
991
|
-
* @returns {BaseBroadcastTransactionResult[]} the serialized transaction hex string and index
|
|
992
|
-
* of the address being swept
|
|
993
|
-
*/
|
|
994
|
-
async recoverCloseATA(params) {
|
|
995
|
-
if (!params.bitgoKey) {
|
|
996
|
-
throw new Error('missing bitgoKey');
|
|
997
|
-
}
|
|
998
|
-
if (!params.recoveryDestination || !this.isValidAddress(params.recoveryDestination)) {
|
|
999
|
-
throw new Error('invalid recoveryDestination');
|
|
1000
|
-
}
|
|
1001
|
-
if (!params.closeAtaAddress || !this.isValidAddress(params.closeAtaAddress)) {
|
|
1002
|
-
throw new Error('invalid closeAtaAddress');
|
|
1003
|
-
}
|
|
1004
|
-
const bitgoKey = params.bitgoKey.replace(/\s/g, '');
|
|
1005
|
-
// Build the transaction
|
|
1006
|
-
const MPC = await sdk_core_1.EDDSAMethods.getInitializedMpcInstance();
|
|
1007
|
-
let balance = 0;
|
|
1008
|
-
const index = params.index || 0;
|
|
1009
|
-
const currPath = params.seed ? (0, sdk_lib_mpc_1.getDerivationPath)(params.seed) + `/${index}` : `m/${index}`;
|
|
1010
|
-
const accountId = MPC.deriveUnhardened(bitgoKey, currPath).slice(0, 64);
|
|
1011
|
-
const bs58EncodedPublicKey = new lib_1.KeyPair({ pub: accountId }).getAddress();
|
|
1012
|
-
const accountBalance = await this.getAccountBalance(bs58EncodedPublicKey);
|
|
1013
|
-
balance = await this.getAccountBalance(params.closeAtaAddress);
|
|
1014
|
-
if (balance <= 0) {
|
|
1015
|
-
throw Error('Did not find closeAtaAddress with sol funds to recover');
|
|
1016
|
-
}
|
|
1017
|
-
const factory = this.getBuilder();
|
|
1018
|
-
let txBuilder;
|
|
1019
|
-
let blockhash;
|
|
1020
|
-
const recovertTxns = [];
|
|
1021
|
-
const rentExemptAmount = await this.getRentExemptAmount();
|
|
1022
|
-
// do token recovery before closing ATA address
|
|
1023
|
-
// check if any token is present on the closeAtaAddress
|
|
1024
|
-
const tokenInfo = await this.getTokenAccountInfo(params.closeAtaAddress);
|
|
1025
|
-
const tokenBalance = Number(tokenInfo.info.tokenAmount.amount);
|
|
1026
|
-
if (tokenBalance > 0) {
|
|
1027
|
-
// closeATA address has some token balance, it needs to be withdrawn before closing ATA
|
|
1028
|
-
console.log(`closeATA address ${params.closeAtaAddress} has token balance ${tokenBalance}, it needs to be withdrawn before closing ATA address`);
|
|
1029
|
-
if (!params.recoveryDestinationAtaAddress || !this.isValidAddress(params.recoveryDestinationAtaAddress)) {
|
|
1030
|
-
throw new Error('invalid recoveryDestinationAtaAddress');
|
|
1031
|
-
}
|
|
1032
|
-
blockhash = await this.getBlockhash(params.apiKey);
|
|
1033
|
-
txBuilder = factory
|
|
1034
|
-
.getTokenTransferBuilder()
|
|
1035
|
-
.nonce(blockhash)
|
|
1036
|
-
.sender(bs58EncodedPublicKey)
|
|
1037
|
-
.associatedTokenAccountRent(rentExemptAmount.toString())
|
|
1038
|
-
.feePayer(bs58EncodedPublicKey);
|
|
1039
|
-
const unsignedTransaction = (await txBuilder.build());
|
|
1040
|
-
const serializedMessage = unsignedTransaction.solTransaction.serializeMessage().toString('base64');
|
|
1041
|
-
const feePerSignature = await this.getFeeForMessage(serializedMessage, params.apiKey);
|
|
1042
|
-
const baseFee = params.durableNonce ? feePerSignature * 2 : feePerSignature;
|
|
1043
|
-
const totalFee = new bignumber_js_1.default(baseFee);
|
|
1044
|
-
if (totalFee.gt(accountBalance)) {
|
|
1045
|
-
throw Error('Did not find address with funds to recover');
|
|
1046
|
-
}
|
|
1047
|
-
txBuilder.fee({ amount: feePerSignature });
|
|
1048
|
-
const network = this.getNetwork();
|
|
1049
|
-
const token = (0, utils_1.getSolTokenFromAddress)(tokenInfo.info.mint, network); // todo(WIN-5894) fix for ams
|
|
1050
|
-
txBuilder.send({
|
|
1051
|
-
address: params.recoveryDestinationAtaAddress,
|
|
1052
|
-
amount: tokenBalance,
|
|
1053
|
-
tokenName: token?.name,
|
|
1054
|
-
});
|
|
1055
|
-
const tokenRecoveryTxn = await this.signAndGenerateBroadcastableTransaction(params, txBuilder, bs58EncodedPublicKey);
|
|
1056
|
-
const serializedTokenRecoveryTxn = (await tokenRecoveryTxn).serializedTx;
|
|
1057
|
-
const broadcastTokenRecoveryTxn = await this.broadcastTransaction({
|
|
1058
|
-
serializedSignedTransaction: serializedTokenRecoveryTxn,
|
|
1059
|
-
});
|
|
1060
|
-
console.log(broadcastTokenRecoveryTxn);
|
|
1061
|
-
recovertTxns.push(broadcastTokenRecoveryTxn);
|
|
1062
|
-
}
|
|
1063
|
-
// after recovering the token amount, attempting to close the ATA address
|
|
1064
|
-
if (params.closeAtaAddress) {
|
|
1065
|
-
blockhash = await this.getBlockhash(params.apiKey);
|
|
1066
|
-
const ataCloseBuilder = () => {
|
|
1067
|
-
const txBuilder = factory.getCloseAtaInitializationBuilder();
|
|
1068
|
-
txBuilder.nonce(blockhash);
|
|
1069
|
-
txBuilder.sender(bs58EncodedPublicKey);
|
|
1070
|
-
txBuilder.accountAddress(params.closeAtaAddress ?? '');
|
|
1071
|
-
txBuilder.destinationAddress(params.recoveryDestination);
|
|
1072
|
-
txBuilder.authorityAddress(bs58EncodedPublicKey);
|
|
1073
|
-
txBuilder.associatedTokenAccountRent(rentExemptAmount.toString());
|
|
1074
|
-
return txBuilder;
|
|
1075
|
-
};
|
|
1076
|
-
txBuilder = ataCloseBuilder();
|
|
1077
|
-
}
|
|
1078
|
-
const closeATARecoveryTxn = await this.signAndGenerateBroadcastableTransaction(params, txBuilder, bs58EncodedPublicKey);
|
|
1079
|
-
const serializedCloseATARecoveryTxn = (await closeATARecoveryTxn).serializedTx;
|
|
1080
|
-
const broadcastCloseATARecoveryTxn = await this.broadcastTransaction({
|
|
1081
|
-
serializedSignedTransaction: serializedCloseATARecoveryTxn,
|
|
1082
|
-
});
|
|
1083
|
-
console.log(broadcastCloseATARecoveryTxn);
|
|
1084
|
-
recovertTxns.push(broadcastCloseATARecoveryTxn);
|
|
1085
|
-
return recovertTxns;
|
|
1086
|
-
}
|
|
1087
|
-
async signAndGenerateBroadcastableTransaction(params, txBuilder, bs58EncodedPublicKey) {
|
|
1088
|
-
// Sign the txn
|
|
1089
|
-
if (!params.userKey) {
|
|
1090
|
-
throw new Error('missing userKey');
|
|
1091
|
-
}
|
|
1092
|
-
if (!params.backupKey) {
|
|
1093
|
-
throw new Error('missing backupKey');
|
|
1094
|
-
}
|
|
1095
|
-
if (!params.walletPassphrase) {
|
|
1096
|
-
throw new Error('missing wallet passphrase');
|
|
1097
|
-
}
|
|
1098
|
-
const unsignedTransaction = (await txBuilder.build());
|
|
1099
|
-
const userKey = params.userKey.replace(/\s/g, '');
|
|
1100
|
-
const backupKey = params.backupKey.replace(/\s/g, '');
|
|
1101
|
-
// Decrypt private keys from KeyCard values
|
|
1102
|
-
let userPrv;
|
|
1103
|
-
try {
|
|
1104
|
-
userPrv = this.bitgo.decrypt({
|
|
1105
|
-
input: userKey,
|
|
1106
|
-
password: params.walletPassphrase,
|
|
1107
|
-
});
|
|
1108
|
-
}
|
|
1109
|
-
catch (e) {
|
|
1110
|
-
throw new Error(`Error decrypting user keychain: ${e.message}`);
|
|
1111
|
-
}
|
|
1112
|
-
const userSigningMaterial = JSON.parse(userPrv);
|
|
1113
|
-
let backupPrv;
|
|
1114
|
-
try {
|
|
1115
|
-
backupPrv = this.bitgo.decrypt({
|
|
1116
|
-
input: backupKey,
|
|
1117
|
-
password: params.walletPassphrase,
|
|
1118
|
-
});
|
|
1119
|
-
}
|
|
1120
|
-
catch (e) {
|
|
1121
|
-
throw new Error(`Error decrypting backup keychain: ${e.message}`);
|
|
1122
|
-
}
|
|
1123
|
-
const backupSigningMaterial = JSON.parse(backupPrv);
|
|
1124
|
-
const index = params.index || 0;
|
|
1125
|
-
const currPath = params.seed ? (0, sdk_lib_mpc_1.getDerivationPath)(params.seed) + `/${index}` : `m/${index}`;
|
|
1126
|
-
const signatureHex = await sdk_core_1.EDDSAMethods.getTSSSignature(userSigningMaterial, backupSigningMaterial, currPath, unsignedTransaction);
|
|
1127
|
-
const publicKeyObj = { pub: bs58EncodedPublicKey };
|
|
1128
|
-
txBuilder.addSignature(publicKeyObj, signatureHex);
|
|
1129
|
-
const completedTransaction = await txBuilder.build();
|
|
1130
|
-
const serializedTx = completedTransaction.toBroadcastFormat();
|
|
1131
|
-
const transaction = {
|
|
1132
|
-
serializedTx: serializedTx,
|
|
1133
|
-
scanIndex: index,
|
|
1134
|
-
};
|
|
1135
|
-
return transaction;
|
|
1136
|
-
}
|
|
1137
|
-
/**
|
|
1138
|
-
* Builds native SOL recoveries of receive addresses in batch without BitGo.
|
|
1139
|
-
* Funds will be recovered to base address first. You need to initiate another sweep txn after that.
|
|
1140
|
-
*
|
|
1141
|
-
* @param {SolConsolidationRecoveryOptions} params - options for consolidation recovery.
|
|
1142
|
-
* @param {string} [params.startingScanIndex] - receive address index to start scanning from. default to 1 (inclusive).
|
|
1143
|
-
* @param {string} [params.endingScanIndex] - receive address index to end scanning at. default to startingScanIndex + 20 (exclusive).
|
|
1144
|
-
*/
|
|
1145
|
-
async recoverConsolidations(params) {
|
|
1146
|
-
const isUnsignedSweep = !params.userKey && !params.backupKey && !params.walletPassphrase;
|
|
1147
|
-
const startIdx = params.startingScanIndex || 1;
|
|
1148
|
-
const endIdx = params.endingScanIndex || startIdx + exports.DEFAULT_SCAN_FACTOR;
|
|
1149
|
-
if (startIdx < 1 || endIdx <= startIdx || endIdx - startIdx > 10 * exports.DEFAULT_SCAN_FACTOR) {
|
|
1150
|
-
throw new Error(`Invalid starting or ending index to scan for addresses. startingScanIndex: ${startIdx}, endingScanIndex: ${endIdx}.`);
|
|
1151
|
-
}
|
|
1152
|
-
// validate durable nonces array
|
|
1153
|
-
if (!params.durableNonces) {
|
|
1154
|
-
throw new Error('Missing durable nonces');
|
|
1155
|
-
}
|
|
1156
|
-
if (!params.durableNonces.publicKeys) {
|
|
1157
|
-
throw new Error('Invalid durable nonces: missing public keys');
|
|
1158
|
-
}
|
|
1159
|
-
if (!params.durableNonces.secretKey) {
|
|
1160
|
-
throw new Error('Invalid durable nonces array: missing secret key');
|
|
1161
|
-
}
|
|
1162
|
-
const bitgoKey = params.bitgoKey.replace(/\s/g, '');
|
|
1163
|
-
const MPC = await sdk_core_1.EDDSAMethods.getInitializedMpcInstance();
|
|
1164
|
-
const baseAddressIndex = 0;
|
|
1165
|
-
const baseAddressPath = params.seed
|
|
1166
|
-
? (0, sdk_lib_mpc_1.getDerivationPath)(params.seed) + `/${baseAddressIndex}`
|
|
1167
|
-
: `m/${baseAddressIndex}`;
|
|
1168
|
-
const accountId = MPC.deriveUnhardened(bitgoKey, baseAddressPath).slice(0, 64);
|
|
1169
|
-
const baseAddress = new lib_1.KeyPair({ pub: accountId }).getAddress();
|
|
1170
|
-
let durableNoncePubKeysIndex = 0;
|
|
1171
|
-
const durableNoncePubKeysLength = params.durableNonces.publicKeys.length;
|
|
1172
|
-
const consolidationTransactions = [];
|
|
1173
|
-
let lastScanIndex = startIdx;
|
|
1174
|
-
for (let i = startIdx; i < endIdx; i++) {
|
|
1175
|
-
const recoverParams = {
|
|
1176
|
-
userKey: params.userKey,
|
|
1177
|
-
backupKey: params.backupKey,
|
|
1178
|
-
bitgoKey: params.bitgoKey,
|
|
1179
|
-
walletPassphrase: params.walletPassphrase,
|
|
1180
|
-
recoveryDestination: baseAddress,
|
|
1181
|
-
seed: params.seed,
|
|
1182
|
-
index: i,
|
|
1183
|
-
durableNonce: {
|
|
1184
|
-
publicKey: params.durableNonces.publicKeys[durableNoncePubKeysIndex],
|
|
1185
|
-
secretKey: params.durableNonces.secretKey,
|
|
1186
|
-
},
|
|
1187
|
-
tokenContractAddress: params.tokenContractAddress,
|
|
1188
|
-
apiKey: params.apiKey,
|
|
1189
|
-
programId: params.programId,
|
|
1190
|
-
};
|
|
1191
|
-
let recoveryTransaction;
|
|
1192
|
-
try {
|
|
1193
|
-
recoveryTransaction = await this.recover(recoverParams);
|
|
1194
|
-
}
|
|
1195
|
-
catch (e) {
|
|
1196
|
-
if (e.message === 'Did not find address with funds to recover' ||
|
|
1197
|
-
e.message === 'Did not find token account to recover tokens, please check token account' ||
|
|
1198
|
-
e.message === 'Not enough token funds to recover') {
|
|
1199
|
-
lastScanIndex = i;
|
|
1200
|
-
continue;
|
|
1201
|
-
}
|
|
1202
|
-
throw e;
|
|
1203
|
-
}
|
|
1204
|
-
if (isUnsignedSweep) {
|
|
1205
|
-
consolidationTransactions.push(recoveryTransaction.txRequests[0]);
|
|
1206
|
-
}
|
|
1207
|
-
else {
|
|
1208
|
-
consolidationTransactions.push(recoveryTransaction);
|
|
1209
|
-
}
|
|
1210
|
-
lastScanIndex = i;
|
|
1211
|
-
durableNoncePubKeysIndex++;
|
|
1212
|
-
if (durableNoncePubKeysIndex >= durableNoncePubKeysLength) {
|
|
1213
|
-
// no more available nonce accounts to create transactions
|
|
1214
|
-
break;
|
|
1215
|
-
}
|
|
1216
|
-
}
|
|
1217
|
-
if (consolidationTransactions.length === 0) {
|
|
1218
|
-
throw new Error('Did not find an address with funds to recover');
|
|
1219
|
-
}
|
|
1220
|
-
if (isUnsignedSweep) {
|
|
1221
|
-
// lastScanIndex will be used to inform user the last address index scanned for available funds (so they can
|
|
1222
|
-
// appropriately adjust the scan range on the next iteration of consolidation recoveries). In the case of unsigned
|
|
1223
|
-
// sweep consolidations, this lastScanIndex will be provided in the coinSpecific of the last txn made.
|
|
1224
|
-
const lastTransactionCoinSpecific = {
|
|
1225
|
-
commonKeychain: consolidationTransactions[consolidationTransactions.length - 1].transactions[0].unsignedTx.coinSpecific
|
|
1226
|
-
.commonKeychain,
|
|
1227
|
-
lastScanIndex: lastScanIndex,
|
|
1228
|
-
};
|
|
1229
|
-
consolidationTransactions[consolidationTransactions.length - 1].transactions[0].unsignedTx.coinSpecific =
|
|
1230
|
-
lastTransactionCoinSpecific;
|
|
1231
|
-
const consolidationSweepTransactions = { txRequests: consolidationTransactions };
|
|
1232
|
-
return consolidationSweepTransactions;
|
|
1233
|
-
}
|
|
1234
|
-
return { transactions: consolidationTransactions, lastScanIndex };
|
|
1235
|
-
}
|
|
1236
|
-
getTokenEnablementConfig() {
|
|
1237
|
-
return {
|
|
1238
|
-
requiresTokenEnablement: true,
|
|
1239
|
-
supportsMultipleTokenEnablements: true,
|
|
1240
|
-
};
|
|
1241
|
-
}
|
|
1242
|
-
getBuilder() {
|
|
1243
|
-
return new lib_1.TransactionBuilderFactory(statics_1.coins.get(this.getChain()));
|
|
1244
|
-
}
|
|
1245
|
-
async broadcastTransaction({ serializedSignedTransaction, }) {
|
|
1246
|
-
(0, utils_1.validateRawTransaction)(serializedSignedTransaction, true, true);
|
|
1247
|
-
const response = await this.getDataFromNode({
|
|
1248
|
-
payload: {
|
|
1249
|
-
id: '1',
|
|
1250
|
-
jsonrpc: '2.0',
|
|
1251
|
-
method: 'sendTransaction',
|
|
1252
|
-
params: [
|
|
1253
|
-
serializedSignedTransaction,
|
|
1254
|
-
{
|
|
1255
|
-
encoding: 'base64',
|
|
1256
|
-
},
|
|
1257
|
-
],
|
|
1258
|
-
},
|
|
1259
|
-
});
|
|
1260
|
-
if (response.body.error) {
|
|
1261
|
-
throw new Error('Error broadcasting transaction: ' + response.body.error.message);
|
|
1262
|
-
}
|
|
1263
|
-
return { txId: response.body.result };
|
|
1264
|
-
}
|
|
1265
|
-
/** @inheritDoc */
|
|
1266
|
-
auditDecryptedKey({ prv, publicKey, multiSigType }) {
|
|
1267
|
-
if (multiSigType !== 'tss') {
|
|
1268
|
-
throw new Error('Unsupported multiSigType');
|
|
1269
|
-
}
|
|
1270
|
-
(0, sdk_lib_mpc_1.auditEddsaPrivateKey)(prv, publicKey ?? '');
|
|
1271
|
-
}
|
|
1272
|
-
/** @inheritDoc */
|
|
1273
|
-
setCoinSpecificFieldsInIntent(intent, params) {
|
|
1274
|
-
// Handle custom instructions for Solana
|
|
1275
|
-
if (params.solInstructions) {
|
|
1276
|
-
intent.solInstructions = params.solInstructions;
|
|
1277
|
-
}
|
|
1278
|
-
// Handle versioned transaction data for Solana
|
|
1279
|
-
if (params.solVersionedTransactionData) {
|
|
1280
|
-
intent.solVersionedTransactionData = params.solVersionedTransactionData;
|
|
1281
|
-
}
|
|
1282
|
-
}
|
|
1283
|
-
}
|
|
1284
|
-
exports.Sol = Sol;
|
|
1285
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic29sLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3NvbC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7O0dBRUc7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUVILGlEQUE0RTtBQUM1RSxnRUFBcUM7QUFDckMsNkNBQStCO0FBQy9CLDBDQUE0QjtBQUM1QixvREFBc0M7QUFFdEMsbURBNEM4QjtBQUM5Qix5REFBa0Y7QUFDbEYsaURBQTJHO0FBQzNHLCtCQUEwRztBQUMxRyx1Q0FRcUI7QUFFUixRQUFBLG1CQUFtQixHQUFHLEVBQUUsQ0FBQyxDQUFDLHdEQUF3RDtBQThHL0YsTUFBTSxTQUFTLEdBQUcsZ0JBQWdCLENBQUM7QUFDbkMsTUFBTSwrQkFBK0IsR0FBRyxFQUFFLFdBQVcsRUFBRSxzQ0FBc0MsRUFBRSxDQUFDO0FBRWhHLE1BQWEsR0FBSSxTQUFRLG1CQUFRO0lBRy9CLFlBQVksS0FBZ0IsRUFBRSxXQUF1QztRQUNuRSxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUM7UUFFYixJQUFJLENBQUMsV0FBVyxFQUFFLENBQUM7WUFDakIsTUFBTSxJQUFJLEtBQUssQ0FBQyxvREFBb0QsQ0FBQyxDQUFDO1FBQ3hFLENBQUM7UUFFRCxJQUFJLENBQUMsWUFBWSxHQUFHLFdBQVcsQ0FBQztJQUNsQyxDQUFDO0lBRUQsTUFBTSxDQUFDLGNBQWMsQ0FBQyxLQUFnQixFQUFFLFdBQXVDO1FBQzdFLE9BQU8sSUFBSSxHQUFHLENBQUMsS0FBSyxFQUFFLFdBQVcsQ0FBQyxDQUFDO0lBQ3JDLENBQUM7SUFFRCwyQkFBMkI7UUFDekIsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBRUQsV0FBVztRQUNULE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQztJQUVELGtCQUFrQjtJQUNsQixzQkFBc0I7UUFDcEIsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBRUQsb0JBQW9CO0lBQ3BCLHNCQUFzQjtRQUNw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QyxJQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ3BGLENBQUM7UUFFRCxPQUFPLEVBQUUsSUFBSSxFQUFFLFFBQVEsQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7SUFDeEMsQ0FBQztJQUVELGtCQUFrQjtJQUNsQixpQkFBaUIsQ0FBQyxFQUFFLEdBQUcsRUFBRSxTQUFTLEVBQUUsWUFBWSxFQUEyQjtRQUN6RSxJQUFJLFlBQVksS0FBSyxLQUFLLEVBQUUsQ0FBQztZQUMzQixNQUFNLElBQUksS0FBSyxDQUFDLDBCQUEwQixDQUFDLENBQUM7UUFDOUMsQ0FBQztRQUNELElBQUEsa0NBQW9CLEVBQUMsR0FBRyxFQUFFLFNBQVMsSUFBSSxFQUFFLENBQUMsQ0FBQztJQUM3QyxDQUFDO0lBRUQsa0JBQWtCO0lBQ2xCLDZCQUE2QixDQUFDLE1BQXVCLEVBQUUsTUFBNEM7UUFDakcsd0NBQXdDO1FBQ3hDLElBQUksTUFBTSxDQUFDLGVBQWUsRUFBRSxDQUFDO1lBQzNCLE1BQU0sQ0FBQyxlQUFlLEdBQUcsTUFBTSxDQUFDLGVBQWUsQ0FBQztRQUNsRCxDQUFDO1FBRUQsK0NBQStDO1FBQy9DLElBQUksTUFBTSxDQUFDLDJCQUEyQixFQUFFLENBQUM7WUFDdkMsTUFBTSxDQUFDLDJCQUEyQixHQUFHLE1BQU0sQ0FBQywyQkFBMkIsQ0FBQztRQUMxRSxDQUFDO0lBQ0gsQ0FBQztDQUNGO0FBMytDRCxrQkEyK0NDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAcHJldHRpZXJcbiAqL1xuXG5pbXBvcnQgeyBUT0tFTl8yMDIyX1BST0dSQU1fSUQsIFRPS0VOX1BST0dSQU1fSUQgfSBmcm9tICdAc29sYW5hL3NwbC10b2tlbic7XG5pbXBvcnQgQmlnTnVtYmVyIGZyb20gJ2JpZ251bWJlci5qcyc7XG5pbXBvcnQgKiBhcyBiYXNlNTggZnJvbSAnYnM1OCc7XG5pbXBvcnQgKiBhcyBfIGZyb20gJ2xvZGFzaCc7XG5pbXBvcnQgKiBhcyByZXF1ZXN0IGZyb20gJ3N1cGVyYWdlbnQnO1xuXG5pbXBvcnQge1xuICBBdWRpdERlY3J5cHRlZEtleVBhcmFtcyxcbiAgQmFzZUJyb2FkY2FzdFRyYW5zYWN0aW9uT3B0aW9ucyxcbiAgQmFzZUJyb2FkY2FzdFRyYW5zYWN0aW9uUmVzdWx0LFxuICBCYXNlQ29pbixcbiAgUGFyc2VUcmFuc2FjdGlvbk9wdGlvbnMgYXMgQmFzZVBhcnNlVHJhbnNhY3Rpb25PcHRpb25zLFxuICBCYXNlVHJhbnNhY3Rpb24sXG4gIFRyYW5zYWN0aW9uUHJlYnVpbGQgYXMgQmFzZVRyYW5zYWN0aW9uUHJlYnVpbGQsXG4gIEJpdEdvQmFzZSxcbiAgRUREU0FNZXRob2RzLFxuICBFRERTQU1ldGhvZFR5cGVzLFxuICBFbnZpcm9ubWVudHMsXG4gIElUb2tlbkVuYWJsZW1lbnQsXG4gIEtleVBhaXIsXG4gIE1lbW8sXG4gIE1QQ0FsZ29yaXRobSxcbiAgTVBDQ29uc29saWRhdGlvblJlY292ZXJ5T3B0aW9ucyxcbiAgTVBDUmVjb3ZlcnlPcHRpb25zLFxuICBNUENTd2VlcFJlY292ZXJ5T3B0aW9ucyxcbiAgTVBDU3dlZXBUeHMsXG4gIE1QQ1R4LFxuICBNUENUeHMsXG4gIE1QQ1Vuc2lnbmVkVHgsXG4gIE11bHRpc2lnVHlwZSxcbiAgbXVsdGlzaWdUeXBlcyxcbiAgT3ZjSW5wdXQsXG4gIE92Y091dHB1dCxcbiAgUGFyc2VkVHJhbnNhY3Rpb24sXG4gIFBvcHVsYXRlZEludGVudCxcbiAgUHJlYnVpbGRUcmFuc2FjdGlvbldpdGhJbnRlbnRPcHRpb25zLFxuICBQcmVzaWduVHJhbnNhY3Rpb25PcHRpb25zLFxuICBQdWJsaWNLZXksXG4gIFJlY292ZXJ5VHhSZXF1ZXN0LFxuICBTaWduZWRUcmFuc2FjdGlvbixcbiAgU2lnblRyYW5zYWN0aW9uT3B0aW9ucyxcbiAgU29sVmVyc2lvbmVkVHJhbnNhY3Rpb25EYXRhLFxuICBUb2tlbkVuYWJsZW1lbnQsXG4gIFRva2VuRW5hYmxlbWVudENvbmZpZyxcbiAgVHJhbnNhY3Rpb25FeHBsYW5hdGlvbixcbiAgVHJhbnNhY3Rpb25QYXJhbXMsXG4gIFRyYW5zYWN0aW9uUmVjaXBpZW50LFxuICBWZXJpZnlUcmFuc2FjdGlvbk9wdGlvbnMsXG4gIFRzc1ZlcmlmeUFkZHJlc3NPcHRpb25zLFxuICB2ZXJpZnlFZGRzYVRzc1dhbGxldEFkZHJlc3MsXG59IGZyb20gJ0BiaXRnby1iZXRhL3Nkay1jb3JlJztcbmltcG9ydCB7IGF1ZGl0RWRkc2FQcml2YXRlS2V5LCBnZXREZXJpdmF0aW9uUGF0aCB9IGZyb20gJ0BiaXRnby1iZXRhL3Nkay1saWItbXBjJztcbmltcG9ydCB7IEJhc2VOZXR3b3JrLCBDb2luRmFtaWx5LCBjb2lucywgU29sQ29pbiwgQmFzZUNvaW4gYXMgU3RhdGljc0Jhc2VDb2luIH0gZnJvbSAnQGJpdGdvLWJldGEvc3RhdGljcyc7XG5pbXBvcnQgeyBLZXlQYWlyIGFzIFNvbEtleVBhaXIsIFRyYW5zYWN0aW9uLCBUcmFuc2FjdGlvbkJ1aWxkZXIsIFRyYW5zYWN0aW9uQnVpbGRlckZhY3RvcnkgfSBmcm9tICcuL2xpYic7XG5pbXBvcnQge1xuICBnZXRBc3NvY2lhdGVkVG9rZW5BY2NvdW50QWRkcmVzcyxcbiAgZ2V0U29sVG9rZW5Gcm9tQWRkcmVzcyxcbiAgZ2V0U29sVG9rZW5Gcm9tVG9rZW5OYW1lLFxuICBpc1ZhbGlkQWRkcmVzcyxcbiAgaXNWYWxpZFByaXZhdGVLZXksXG4gIGlzVmFsaWRQdWJsaWNLZXksXG4gIHZhbGlkYXRlUmF3VHJhbnNhY3Rpb24sXG59IGZyb20gJy4vbGliL3V0aWxzJztcblxuZXhwb3J0IGNvbnN0IERFRkFVTFRfU0NBTl9GQUNUT1IgPSAyMDsgLy8gZGVmYXVsdCBudW1iZXIgb2YgcmVjZWl2ZSBhZGRyZXNzZXMgdG8gc2NhbiBmb3IgZnVuZHNcblxuZXhwb3J0IGludGVyZmFjZSBUcmFuc2FjdGlvbkZlZSB7XG4gIGZlZTogc3RyaW5nO1xufVxuXG5leHBvcnQgdHlwZSBTb2xUcmFuc2FjdGlvbkV4cGxhbmF0aW9uID0gVHJhbnNhY3Rpb25FeHBsYW5hdGlvbjtcblxuZXhwb3J0IGludGVyZmFjZSBFeHBsYWluVHJhbnNhY3Rpb25PcHRpb25zIHtcbiAgdHhCYXNlNjQ6IHN0cmluZztcbiAgZmVlSW5mbzogVHJhbnNhY3Rpb25GZWU7XG4gIHRva2VuQWNjb3VudFJlbnRFeGVtcHRBbW91bnQ/OiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgVHhJbmZvIHtcbiAgcmVjaXBpZW50czogVHJhbnNhY3Rpb25SZWNpcGllbnRbXTtcbiAgZnJvbTogc3RyaW5nO1xuICB0eGlkOiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgU29sU2lnblRyYW5zYWN0aW9uT3B0aW9ucyBleHRlbmRzIFNpZ25UcmFuc2FjdGlvbk9wdGlvbnMge1xuICB0eFByZWJ1aWxkOiBUcmFuc2FjdGlvblByZWJ1aWxkO1xuICBwcnY6IHN0cmluZyB8IHN0cmluZ1tdO1xuICBwdWJLZXlzPzogc3RyaW5nW107XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgVHJhbnNhY3Rpb25QcmVidWlsZCBleHRlbmRzIEJhc2VUcmFuc2FjdGlvblByZWJ1aWxkIHtcbiAgdHhCYXNlNjQ6IHN0cmluZztcbiAgdHhJbmZvOiBUeEluZm87XG4gIHNvdXJjZTogc3RyaW5nO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFNvbFZlcmlmeVRyYW5zYWN0aW9uT3B0aW9ucyBleHRlbmRzIFZlcmlmeVRyYW5zYWN0aW9uT3B0aW9ucyB7XG4gIG1lbW8/OiBNZW1vO1xuICBmZWVQYXllcjogc3RyaW5nO1xuICBibG9ja2hhc2g6IHN0cmluZztcbiAgZHVyYWJsZU5vbmNlPzogeyB3YWxsZXROb25jZUFkZHJlc3M6IHN0cmluZzsgYXV0aFdhbGxldEFkZHJlc3M6IG51bWJlciB9O1xufVxuXG5pbnRlcmZhY2UgVHJhbnNhY3Rpb25PdXRwdXQge1xuICBhZGRyZXNzOiBzdHJpbmc7XG4gIGFtb3VudDogbnVtYmVyIHwgc3RyaW5nO1xuICB0b2tlbk5hbWU/OiBzdHJpbmc7XG59XG5cbnR5cGUgVHJhbnNhY3Rpb25JbnB1dCA9IFRyYW5zYWN0aW9uT3V0cHV0O1xuXG5leHBvcnQgaW50ZXJmYWNlIFNvbFBhcnNlZFRyYW5zYWN0aW9uIGV4dGVuZHMgUGFyc2VkVHJhbnNhY3Rpb24ge1xuICAvLyB0b3RhbCBhc3NldHMgYmVpbmcgbW92ZWQsIGluY2x1ZGluZyBmZWVzXG4gIGlucHV0czogVHJhbnNhY3Rpb25JbnB1dFtdO1xuXG4gIC8vIHdoZXJlIGFzc2V0cyBhcmUgbW92ZWQgdG9cbiAgb3V0cHV0czogVHJhbnNhY3Rpb25PdXRwdXRbXTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBTb2xQYXJzZVRyYW5zYWN0aW9uT3B0aW9ucyBleHRlbmRzIEJhc2VQYXJzZVRyYW5zYWN0aW9uT3B0aW9ucyB7XG4gIHR4QmFzZTY0OiBzdHJpbmc7XG4gIGZlZUluZm86IFRyYW5zYWN0aW9uRmVlO1xuICB0b2tlbkFjY291bnRSZW50RXhlbXB0QW1vdW50Pzogc3RyaW5nO1xufVxuXG5pbnRlcmZhY2UgU29sRHVyYWJsZU5vbmNlRnJvbU5vZGUge1xuICBhdXRob3JpdHk6IHN0cmluZztcbiAgYmxvY2toYXNoOiBzdHJpbmc7XG59XG5cbmludGVyZmFjZSBUb2tlbkFtb3VudCB7XG4gIGFtb3VudDogc3RyaW5nO1xuICBkZWNpbWFsczogbnVtYmVyO1xuICB1aUFtb3VudDogbnVtYmVyO1xuICB1aUFtb3VudFN0cmluZzogc3RyaW5nO1xufVxuXG5pbnRlcmZhY2UgVG9rZW5BY2NvdW50SW5mbyB7XG4gIGlzTmF0aXZlOiBib29sZWFuO1xuICBtaW50OiBzdHJpbmc7XG4gIG93bmVyOiBzdHJpbmc7XG4gIHN0YXRlOiBzdHJpbmc7XG4gIHRva2VuQW1vdW50OiBUb2tlbkFtb3VudDtcbn1cblxuaW50ZXJmYWNlIFRva2VuQWNjb3VudCB7XG4gIGluZm86IFRva2VuQWNjb3VudEluZm87XG4gIHB1YktleTogc3RyaW5nO1xuICB0b2tlbk5hbWU/OiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgU29sUmVjb3ZlcnlPcHRpb25zIGV4dGVuZHMgTVBDUmVjb3ZlcnlPcHRpb25zIHtcbiAgZHVyYWJsZU5vbmNlPzoge1xuICAgIHB1YmxpY0tleTogc3RyaW5nO1xuICAgIHNlY3JldEtleTogc3RyaW5nO1xuICB9O1xuICB0b2tlbkNvbnRyYWN0QWRkcmVzcz86IHN0cmluZztcbiAgY2xvc2VBdGFBZGRyZXNzPzogc3RyaW5nO1xuICAvLyBkZXN0aW5hdGlvbiBhZGRyZXNzIHdoZXJlIHRva2VuIHNob3VsZCBiZSBzZW50IGJlZm9yZSBjbG9zaW5nIHRoZSBBVEEgYWRkcmVzc1xuICByZWNvdmVyeURlc3RpbmF0aW9uQXRhQWRkcmVzcz86IHN0cmluZztcbiAgcHJvZ3JhbUlkPzogc3RyaW5nOyAvLyBwcm9ncmFtSWQgb2YgdGhlIHRva2VuXG4gIGFwaUtleT86IHN0cmluZzsgLy8gQVBJIGtleSBmb3Igbm9kZSByZXF1ZXN0c1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFNvbENvbnNvbGlkYXRpb25SZWNvdmVyeU9wdGlvbnMgZXh0ZW5kcyBNUENDb25zb2xpZGF0aW9uUmVjb3ZlcnlPcHRpb25zIHtcbiAgZHVyYWJsZU5vbmNlczoge1xuICAgIHB1YmxpY0tleXM6IHN0cmluZ1tdO1xuICAgIHNlY3JldEtleTogc3RyaW5nO1xuICB9O1xuICB0b2tlbkNvbnRyYWN0QWRkcmVzcz86IHN0cmluZztcbiAgYXBpS2V5Pzogc3RyaW5nOyAvLyBBUEkga2V5IGZvciBub2RlIHJlcXVlc3RzXG4gIHByb2dyYW1JZD86IHN0cmluZzsgLy8gcHJvZ3JhbUlkIG9mIHRoZSB0b2tlblxufVxuXG5jb25zdCBIRVhfUkVHRVggPSAvXlswLTlhLWZBLUZdKyQvO1xuY29uc3QgQkxJTkRfU0lHTklOR19UWF9UWVBFU19UT19DSEVDSyA9IHsgZW5hYmxldG9rZW46ICdBc3NvY2lhdGVkVG9rZW5BY2NvdW50SW5pdGlhbGl6YXRpb24nIH07XG5cbmV4cG9ydCBjbGFzcyBTb2wgZXh0ZW5kcyBCYXNlQ29pbiB7XG4gIHByb3RlY3RlZCByZWFkb25seSBfc3RhdGljc0NvaW46IFJlYWRvbmx5PFN0YXRpY3NCYXNlQ29pbj47XG5cbiAgY29uc3RydWN0b3IoYml0Z286IEJpdEdvQmFzZSwgc3RhdGljc0NvaW4/OiBSZWFkb25seTxTdGF0aWNzQmFzZUNvaW4+KSB7XG4gICAgc3VwZXIoYml0Z28pO1xuXG4gICAgaWYgKCFzdGF0aWNzQ29pbikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdtaXNzaW5nIHJlcXVpcmVkIGNvbnN0cnVjdG9yIHBhcmFtZXRlciBzdGF0aWNzQ29pbicpO1xuICAgIH1cblxuICAgIHRoaXMuX3N0YXRpY3NDb2luID0gc3RhdGljc0NvaW47XG4gIH1cblxuICBzdGF0aWMgY3JlYXRlSW5zdGFuY2UoYml0Z286IEJpdEdvQmFzZSwgc3RhdGljc0NvaW4/OiBSZWFkb25seTxTdGF0aWNzQmFzZUNvaW4+KTogQmFzZUNvaW4ge1xuICAgIHJldHVybiBuZXcgU29sKGJpdGdvLCBzdGF0aWNzQ29pbik7XG4gIH1cblxuICBhbGxvd3NBY2NvdW50Q29uc29saWRhdGlvbnMoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICBzdXBwb3J0c1RzcygpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIC8qKiBAaW5oZXJpdERvYyAqL1xuICBzdXBwb3J0c01lc3NhZ2VTaWduaW5nKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgLyoqIGluaGVyaXRlZCBkb2MgKi9cbiAgZ2V0RGVmYXVsdE11bHRpc2lnVHlwZSgpOiBNdWx0aXNpZ1R5cGUge1xuICAgIHJldHVybiBtdWx0aXNpZ1R5cGVzLnRzcztcbiAgfVxuXG4gIGdldE1QQ0FsZ29yaXRobSgpOiBNUENBbGdvcml0aG0ge1xuICAgIHJldHVybiAnZWRkc2EnO1xuICB9XG5cbiAgZ2V0Q2hhaW4oKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5fc3RhdGljc0NvaW4ubmFtZTtcbiAgfVxuXG4gIGdldEZhbWlseSgpOiBDb2luRmFtaWx5IHtcbiAgICByZXR1cm4gdGhpcy5fc3RhdGljc0NvaW4uZmFtaWx5O1xuICB9XG5cbiAgZ2V0RnVsbE5hbWUoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5fc3RhdGljc0NvaW4uZnVsbE5hbWU7XG4gIH1cblxuICBnZXROZXR3b3JrKCk6IEJhc2VOZXR3b3JrIHtcbiAgICByZXR1cm4gdGhpcy5fc3RhdGljc0NvaW4ubmV0d29yaztcbiAgfVxuXG4gIGdldEJhc2VGYWN0b3IoKTogc3RyaW5nIHwgbnVtYmVyIHtcbiAgICByZXR1cm4gTWF0aC5wb3coMTAsIHRoaXMuX3N0YXRpY3NDb2luLmRlY2ltYWxQbGFjZXMpO1xuICB9XG5cbiAgdmVyaWZ5VHhUeXBlKGV4cGVjdGVkVHlwZUZyb21Vc2VyUGFyYW1zOiBzdHJpbmcsIGFjdHVhbFR5cGVGcm9tRGVjb2RlZDogc3RyaW5nIHwgdW5kZWZpbmVkKTogdm9pZCB7XG4gICAgY29uc3QgbWF0Y2hGcm9tVXNlclRvRGVjb2RlZFR5cGUgPSBCTElORF9TSUdOSU5HX1RYX1RZUEVTX1RPX0NIRUNLW2V4cGVjdGVkVHlwZUZyb21Vc2VyUGFyYW1zXTtcbiAgICBpZiAobWF0Y2hGcm9tVXNlclRvRGVjb2RlZFR5cGUgIT09IGFjdHVhbFR5cGVGcm9tRGVjb2RlZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgSW52YWxpZCB0cmFuc2FjdGlvbiB0eXBlIG9uIHRva2VuIGVuYWJsZW1lbnQ6IGV4cGVjdGVkIFwiJHttYXRjaEZyb21Vc2VyVG9EZWNvZGVkVHlwZX1cIiwgZ290IFwiJHthY3R1YWxUeXBlRnJvbURlY29kZWR9XCIuYFxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICB0aHJvd0lmTWlzc2luZ1Rva2VuRW5hYmxlbWVudHNPclJldHVybihleHBsYW5hdGlvbjogVHJhbnNhY3Rpb25FeHBsYW5hdGlvbik6IElUb2tlbkVuYWJsZW1lbnRbXSB7XG4gICAgaWYgKCFleHBsYW5hdGlvbi50b2tlbkVuYWJsZW1lbnRzIHx8IGV4cGxhbmF0aW9uLnRva2VuRW5hYmxlbWVudHMubGVuZ3RoID09PSAwKVxuICAgICAgdGhyb3cgbmV3IEVycm9yKCdNaXNzaW5nIHR4IHRva2VuIGVuYWJsZW1lbnRzIGRhdGEgb24gdG9rZW4gZW5hYmxlbWVudCB0eCBwcmVidWlsZCcpO1xuICAgIHJldHVybiBleHBsYW5hdGlvbi50b2tlbkVuYWJsZW1lbnRzO1xuICB9XG5cbiAgdGhyb3dJZk1pc3NpbmdFbmFibGVUb2tlbkNvbmZpZ09yUmV0dXJuKHR4UGFyYW1zOiBUcmFuc2FjdGlvblBhcmFtcyk6IFRva2VuRW5hYmxlbWVudFtdIHtcbiAgICBpZiAoIXR4UGFyYW1zLmVuYWJsZVRva2VucyB8fCB0eFBhcmFtcy5lbmFibGVUb2tlbnMubGVuZ3RoID09PSAwKSB0aHJvdyBuZXcgRXJyb3IoJ01pc3NpbmcgZW5hYmxlIHRva2VuIGNvbmZpZycpO1xuICAgIHJldHVybiB0eFBhcmFtcy5lbmFibGVUb2tlbnM7XG4gIH1cblxuICB2ZXJpZnlUb2tlbk5hbWUodG9rZW5FbmFibGVtZW50c1ByZWJ1aWxkOiBJVG9rZW5FbmFibGVtZW50W10sIGVuYWJsZVRva2Vuc0NvbmZpZzogVG9rZW5FbmFibGVtZW50W10pOiB2b2lkIHtcbiAgICBlbmFibGVUb2tlbnNDb25maWcuZm9yRWFjaCgoZW5hYmxlVG9rZW5Db25maWcpID0+IHtcbiAgICAgIGNvbnN0IGV4cGVjdGVkVG9rZW5OYW1lID0gZW5hYmxlVG9rZW5Db25maWcubmFtZTtcbiAgICAgIHRva2VuRW5hYmxlbWVudHNQcmVidWlsZC5mb3JFYWNoKCh0b2tlbkVuYWJsZW1lbnQpID0+IHtcbiAgICAgICAgaWYgKCF0b2tlbkVuYWJsZW1lbnQudG9rZW5OYW1lKSB0aHJvdyBuZXcgRXJyb3IoJ01pc3NpbmcgdG9rZW4gbmFtZSBvbiB0b2tlbiBlbmFibGVtZW50IHR4Jyk7XG4gICAgICAgIGlmICh0b2tlbkVuYWJsZW1lbnQudG9rZW5OYW1lICE9PSBleHBlY3RlZFRva2VuTmFtZSlcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgICBgSW52YWxpZCB0b2tlbiBuYW1lOiBleHBlY3RlZCAke2V4cGVjdGVkVG9rZW5OYW1lfSwgZ290ICR7dG9rZW5FbmFibGVtZW50LnRva2VuTmFtZX0gb24gdG9rZW4gZW5hYmxlbWVudCB0eGBcbiAgICAgICAgICApO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICBhc3luYyB2ZXJpZnlUb2tlbkFkZHJlc3MoXG4gICAgdG9rZW5FbmFibGVtZW50c1ByZWJ1aWxkOiBJVG9rZW5FbmFibGVtZW50W10sXG4gICAgZW5hYmxlVG9rZW5zQ29uZmlnOiBUb2tlbkVuYWJsZW1lbnRbXVxuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBmb3IgKGNvbnN0IGVuYWJsZVRva2VuQ29uZmlnIG9mIGVuYWJsZVRva2Vuc0NvbmZpZykge1xuICAgICAgY29uc3QgZXhwZWN0ZWRUb2tlbkFkZHJlc3MgPSBlbmFibGVUb2tlbkNvbmZpZy5hZGRyZXNzO1xuICAgICAgY29uc3QgZXhwZWN0ZWRUb2tlbk5hbWUgPSBlbmFibGVUb2tlbkNvbmZpZy5uYW1lO1xuXG4gICAgICBpZiAoIWV4cGVjdGVkVG9rZW5BZGRyZXNzKSB0aHJvdyBuZXcgRXJyb3IoJ01pc3NpbmcgdG9rZW4gYWRkcmVzcyBvbiB0b2tlbiBlbmFibGVtZW50IHR4Jyk7XG4gICAgICBpZiAoIWV4cGVjdGVkVG9rZW5OYW1lKSB0aHJvdyBuZXcgRXJyb3IoJ01pc3NpbmcgdG9rZW4gbmFtZSBvbiB0b2tlbiBlbmFibGVtZW50IHR4Jyk7XG5cbiAgICAgIGZvciAoY29uc3QgdG9rZW5FbmFibGVtZW50IG9mIHRva2VuRW5hYmxlbWVudHNQcmVidWlsZCkge1xuICAgICAgICBsZXQgdG9rZW5NaW50QWRkcmVzczogUmVhZG9ubHk8U29sQ29pbj4gfCB1bmRlZmluZWQ7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgdG9rZW5NaW50QWRkcmVzcyA9IGdldFNvbFRva2VuRnJvbVRva2VuTmFtZShleHBlY3RlZFRva2VuTmFtZSk7XG4gICAgICAgIH0gY2F0Y2gge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgVW5hYmxlIHRvIGRlcml2ZSBBVEEgZm9yIHRva2VuIGFkZHJlc3M6ICR7ZXhwZWN0ZWRUb2tlbkFkZHJlc3N9YCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKFxuICAgICAgICAgICF0b2tlbk1pbnRBZGRyZXNzIHx8XG4gICAgICAgICAgdG9rZW5NaW50QWRkcmVzcy50b2tlbkFkZHJlc3MgPT09IHVuZGVmaW5lZCB8fFxuICAgICAgICAgIHRva2VuTWludEFkZHJlc3MucHJvZ3JhbUlkID09PSB1bmRlZmluZWRcbiAgICAgICAgKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbmFibGUgdG8gZ2V0IHRva2VuIG1pbnQgYWRkcmVzcyBmb3IgJHtleHBlY3RlZFRva2VuTmFtZX1gKTtcbiAgICAgICAgfVxuICAgICAgICBsZXQgYXRhOiBzdHJpbmc7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgYXRhID0gYXdhaXQgZ2V0QXNzb2NpYXRlZFRva2VuQWNjb3VudEFkZHJlc3MoXG4gICAgICAgICAgICB0b2tlbk1pbnRBZGRyZXNzLnRva2VuQWRkcmVzcyxcbiAgICAgICAgICAgIGV4cGVjdGVkVG9rZW5BZGRyZXNzLFxuICAgICAgICAgICAgdHJ1ZSxcbiAgICAgICAgICAgIHRva2VuTWludEFkZHJlc3MucHJvZ3JhbUlkXG4gICAgICAgICAgKTtcbiAgICAgICAgfSBjYXRjaCB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbmFibGUgdG8gZGVyaXZlIEFUQSBmb3IgdG9rZW4gYWRkcmVzczogJHtleHBlY3RlZFRva2VuQWRkcmVzc31gKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoYXRhICE9PSB0b2tlbkVuYWJsZW1lbnQuYWRkcmVzcykge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAgIGBJbnZhbGlkIHRva2VuIGFkZHJlc3M6IGV4cGVjdGVkICR7YXRhfSwgZ290ICR7dG9rZW5FbmFibGVtZW50LmFkZHJlc3N9IG9uIHRva2VuIGVuYWJsZW1lbnQgdHhgXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgaGFzU29sVmVyc2lvbmVkVHJhbnNhY3Rpb25EYXRhKFxuICAgIHR4UGFyYW1zOiBUcmFuc2FjdGlvblBhcmFtc1xuICApOiB0eFBhcmFtcyBpcyBUcmFuc2FjdGlvblBhcmFtcyAmIHsgc29sVmVyc2lvbmVkVHJhbnNhY3Rpb25EYXRhOiBTb2xWZXJzaW9uZWRUcmFuc2FjdGlvbkRhdGEgfSB7XG4gICAgcmV0dXJuICdzb2xWZXJzaW9uZWRUcmFuc2FjdGlvbkRhdGEnIGluIHR4UGFyYW1zICYmIHR4UGFyYW1zLnNvbFZlcnNpb25lZFRyYW5zYWN0aW9uRGF0YSAhPT0gdW5kZWZpbmVkO1xuICB9XG5cbiAgLyoqXG4gICAqIFZlcmlmeSBhIHZlcnNpb25lZCBTb2xhbmEgdHJhbnNhY3Rpb24gd2l0aCBiYXNpYyBzdHJ1Y3R1cmFsIHZhbGlkYXRpb25cbiAgICogQHBhcmFtIHBhcmFtcyAtIHZlcmlmaWNhdGlvbiBwYXJhbWV0ZXJzXG4gICAqIEByZXR1cm5zIHRydWUgaWYgdmVyaWZpY2F0aW9uIHBhc3Nlc1xuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyB2ZXJpZnlWZXJzaW9uZWRUcmFuc2FjdGlvbihwYXJhbXM6IFNvbFZlcmlmeVRyYW5zYWN0aW9uT3B0aW9ucyk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIGNvbnN0IHsgdHhQYXJhbXMsIHR4UHJlYnVpbGQgfSA9IHBhcmFtcztcbiAgICBjb25zdCByYXdUeCA9IHR4UHJlYnVpbGQudHhCYXNlNjQgfHwgdHhQcmVidWlsZC50eEhleDtcblxuICAgIGlmICghcmF3VHgpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignbWlzc2luZyByZXF1aXJlZCB0eCBwcmVidWlsZCBwcm9wZXJ0eSB0eEJhc2U2NCBvciB0eEhleCcpO1xuICAgIH1cblxuICAgIC8vIFZhbGlkYXRlIHRoYXQgdGhlIHZlcnNpb25lZCB0cmFuc2FjdGlvbiBkYXRhIGlzIHdlbGwtZm9ybWVkXG4gICAgaWYgKCF0aGlzLmhhc1NvbFZlcnNpb25lZFRyYW5zYWN0aW9uRGF0YSh0eFBhcmFtcykpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignc29sVmVyc2lvbmVkVHJhbnNhY3Rpb25EYXRhIGlzIHJlcXVpcmVkIGZvciB2ZXJzaW9uZWQgdHJhbnNhY3Rpb24gdmVyaWZpY2F0aW9uJyk7XG4gICAgfVxuXG4gICAgY29uc3QgdmVyc2lvbmVkRGF0YSA9IHR4UGFyYW1zLnNvbFZlcnNpb25lZFRyYW5zYWN0aW9uRGF0YTtcblxuICAgIGlmICghdmVyc2lvbmVkRGF0YS52ZXJzaW9uZWRJbnN0cnVjdGlvbnMgfHwgdmVyc2lvbmVkRGF0YS52ZXJzaW9uZWRJbnN0cnVjdGlvbnMubGVuZ3RoID09PSAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ3ZlcnNpb25lZCB0cmFuc2FjdGlvbiBtdXN0IGhhdmUgYXQgbGVhc3Qgb25lIGluc3RydWN0aW9uJyk7XG4gICAgfVxuXG4gICAgaWYgKCF2ZXJzaW9uZWREYXRhLnN0YXRpY0FjY291bnRLZXlzIHx8IHZlcnNpb25lZERhdGEuc3RhdGljQWNjb3VudEtleXMubGVuZ3RoID09PSAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ3ZlcnNpb25lZCB0cmFuc2FjdGlvbiBtdXN0IGhhdmUgYXQgbGVhc3Qgb25lIHN0YXRpYyBhY2NvdW50IGtleScpO1xuICAgIH1cblxuICAgIGlmICghdmVyc2lvbmVkRGF0YS5tZXNzYWdlSGVhZGVyKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ3ZlcnNpb25lZCB0cmFuc2FjdGlvbiBtdXN0IGhhdmUgYSBtZXNzYWdlIGhlYWRlcicpO1xuICAgIH1cblxuICAgIC8vIFZhbGlkYXRlIHRoYXQgd2UgY2FuIGRlc2VyaWFsaXplIHRoZSB0cmFuc2FjdGlvblxuICAgIGxldCByYXdUeEJhc2U2NCA9IHJhd1R4O1xuICAgIGlmIChIRVhfUkVHRVgudGVzdChyYXdUeCkpIHtcbiAgICAgIHJhd1R4QmFzZTY0ID0gQnVmZmVyLmZyb20ocmF3VHgsICdoZXgnKS50b1N0cmluZygnYmFzZTY0Jyk7XG4gICAgfVxuXG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHR4Qnl0ZXMgPSBCdWZmZXIuZnJvbShyYXdUeEJhc2U2NCwgJ2Jhc2U2NCcpO1xuICAgICAgaWYgKHR4Qnl0ZXMubGVuZ3RoIDwgMSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ3RyYW5zYWN0aW9uIGJ5dGVzIGFyZSBlbXB0eScpO1xuICAgICAgfVxuXG4gICAgICAvLyBDaGVjayB2ZXJzaW9uIGJ5dGUgKGFmdGVyIHNpZ25hdHVyZXMpXG4gICAgICBjb25zdCBudW1TaWduYXR1cmVzID0gdHhCeXRlc1swXTtcbiAgICAgIGNvbnN0IHNpZ25hdHVyZVNpemUgPSA2NDtcbiAgICAgIGNvbnN0IHZlcnNpb25CeXRlT2Zmc2V0ID0gMSArIG51bVNpZ25hdHVyZXMgKiBzaWduYXR1cmVTaXplO1xuXG4gICAgICBpZiAodHhCeXRlcy5sZW5ndGggPD0gdmVyc2lvbkJ5dGVPZmZzZXQpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCd0cmFuc2FjdGlvbiBieXRlcyBhcmUgdG9vIHNob3J0IHRvIGNvbnRhaW4gdmVyc2lvbiBieXRlJyk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHZlcnNpb25CeXRlID0gdHhCeXRlc1t2ZXJzaW9uQnl0ZU9mZnNldF07XG4gICAgICBjb25zdCBpc1ZlcnNpb25lZCA9ICh2ZXJzaW9uQnl0ZSAmIDB4ODApICE9PSAwO1xuXG4gICAgICBpZiAoIWlzVmVyc2lvbmVkKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcigndHJhbnNhY3Rpb24gZG9lcyBub3QgaGF2ZSB2ZXJzaW9uZWQgZm9ybWF0Jyk7XG4gICAgICB9XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgZmFpbGVkIHRvIHZhbGlkYXRlIHZlcnNpb25lZCB0cmFuc2FjdGlvbiBmb3JtYXQ6ICR7ZXJyb3IubWVzc2FnZX1gKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIGFzeW5jIHZlcmlmeVRyYW5zYWN0aW9uKHBhcmFtczogU29sVmVyaWZ5VHJhbnNhY3Rpb25PcHRpb25zKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgLy8gYXNzZXQgbmFtZSB0byB0cmFuc2ZlciBhbW91bnQgbWFwXG4gICAgY29uc3QgdG90YWxBbW91bnQ6IFJlY29yZDxzdHJpbmcsIEJpZ051bWJlcj4gPSB7fTtcbiAgICBjb25zdCBjb2luQ29uZmlnID0gY29pbnMuZ2V0KHRoaXMuZ2V0Q2hhaW4oKSk7XG4gICAgY29uc3Qge1xuICAgICAgdHhQYXJhbXM6IHR4UGFyYW1zLFxuICAgICAgdHhQcmVidWlsZDogdHhQcmVidWlsZCxcbiAgICAgIG1lbW86IG1lbW8sXG4gICAgICBkdXJhYmxlTm9uY2U6IGR1cmFibGVOb25jZSxcbiAgICAgIHZlcmlmaWNhdGlvbjogdmVyaWZpY2F0aW9uT3B0aW9ucyxcbiAgICB9ID0gcGFyYW1zO1xuXG4gICAgaWYgKHRoaXMuaGFzU29sVmVyc2lvbmVkVHJhbnNhY3Rpb25EYXRhKHR4UGFyYW1zKSkge1xuICAgICAgcmV0dXJuIHRoaXMudmVyaWZ5VmVyc2lvbmVkVHJhbnNhY3Rpb24ocGFyYW1zKTtcbiAgICB9XG5cbiAgICBjb25zdCB0cmFuc2FjdGlvbiA9IG5ldyBUcmFuc2FjdGlvbihjb2luQ29uZmlnKTtcbiAgICBjb25zdCByYXdUeCA9IHR4UHJlYnVpbGQudHhCYXNlNjQgfHwgdHhQcmVidWlsZC50eEhleDtcbiAgICBjb25zdCBjb25zb2xpZGF0ZUlkID0gdHhQcmVidWlsZC5jb25zb2xpZGF0ZUlkO1xuXG4gICAgY29uc3Qgd2FsbGV0Um9vdEFkZHJlc3MgPSBwYXJhbXMud2FsbGV0LmNvaW5TcGVjaWZpYygpPy5yb290QWRkcmVzcztcblxuICAgIGlmICghcmF3VHgpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignbWlzc2luZyByZXF1aXJlZCB0eCBwcmVidWlsZCBwcm9wZXJ0eSB0eEJhc2U2NCBvciB0eEhleCcpO1xuICAgIH1cblxuICAgIGxldCByYXdUeEJhc2U2NCA9IHJhd1R4O1xuICAgIGlmIChIRVhfUkVHRVgudGVzdChyYXdUeCkpIHtcbiAgICAgIHJhd1R4QmFzZTY0ID0gQnVmZmVyLmZyb20ocmF3VHgsICdoZXgnKS50b1N0cmluZygnYmFzZTY0Jyk7XG4gICAgfVxuICAgIHRyYW5zYWN0aW9uLmZyb21SYXdUcmFuc2FjdGlvbihyYXdUeEJhc2U2NCk7XG4gICAgY29uc3QgZXhwbGFpbmVkVHggPSB0cmFuc2FjdGlvbi5leHBsYWluVHJhbnNhY3Rpb24oKTtcblxuICAgIGlmICh0eFBhcmFtcy50eXBlID09PSAnZW5hYmxldG9rZW4nICYmIHZlcmlmaWNhdGlvbk9wdGlvbnM/LnZlcmlmeVRva2VuRW5hYmxlbWVudCkge1xuICAgICAgdGhpcy52ZXJpZnlUeFR5cGUodHhQYXJhbXMudHlwZSwgZXhwbGFpbmVkVHgudHlwZSk7XG4gICAgICBjb25zdCB0b2tlbkVuYWJsZW1lbnRzUHJlYnVpbGQgPSB0aGlzLnRocm93SWZNaXNzaW5nVG9rZW5FbmFibGVtZW50c09yUmV0dXJuKGV4cGxhaW5lZFR4KTtcbiAgICAgIGNvbnN0IGVuYWJsZVRva2Vuc0NvbmZpZyA9IHRoaXMudGhyb3dJZk1pc3NpbmdFbmFibGVUb2tlbkNvbmZpZ09yUmV0dXJuKHR4UGFyYW1zKTtcblxuICAgICAgdGhpcy52ZXJpZnlUb2tlbk5hbWUodG9rZW5FbmFibGVtZW50c1ByZWJ1aWxkLCBlbmFibGVUb2tlbnNDb25maWcpO1xuICAgICAgYXdhaXQgdGhpcy52ZXJpZnlUb2tlbkFkZHJlc3ModG9rZW5FbmFibGVtZW50c1ByZWJ1aWxkLCBlbmFibGVUb2tlbnNDb25maWcpO1xuICAgIH1cblxuICAgIC8vIHVzZXJzIGRvIG5vdCBpbnB1dCByZWNpcGllbnRzIGZvciBjb25zb2xpZGF0aW9uIHJlcXVlc3RzIGFzIHRoZXkgYXJlIGdlbmVyYXRlZCBieSB0aGUgc2VydmVyXG4gICAgaWYgKHR4UGFyYW1zLnJlY2lwaWVudHMgIT09IHVuZGVmaW5lZCkge1xuICAgICAgY29uc3QgZmlsdGVyZWRSZWNpcGllbnRzID0gdHhQYXJhbXMucmVjaXBpZW50cz8ubWFwKChyZWNpcGllbnQpID0+XG4gICAgICAgIF8ucGljayhyZWNpcGllbnQsIFsnYWRkcmVzcycsICdhbW91bnQnLCAndG9rZW5OYW1lJ10pXG4gICAgICApO1xuICAgICAgY29uc3QgZmlsdGVyZWRPdXRwdXRzID0gZXhwbGFpbmVkVHgub3V0cHV0cy5tYXAoKG91dHB1dCkgPT4gXy5waWNrKG91dHB1dCwgWydhZGRyZXNzJywgJ2Ftb3VudCcsICd0b2tlbk5hbWUnXSkpO1xuXG4gICAgICBpZiAoZmlsdGVyZWRSZWNpcGllbnRzLmxlbmd0aCAhPT0gZmlsdGVyZWRPdXRwdXRzLmxlbmd0aCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ051bWJlciBvZiB0eCBvdXRwdXRzIGRvZXMgbm90IG1hdGNoIHdpdGggbnVtYmVyIG9mIHR4UGFyYW1zIHJlY2lwaWVudHMnKTtcbiAgICAgIH1cblxuICAgICAgLy8gRm9yIGVhY2ggcmVjaXBpZW50LCBjaGVjayBpZiBpdCdzIGEgdG9rZW4gdHggKHRva2VuTmFtZSB3aWxsIGV4aXN0IGlmIHNvKVxuICAgICAgLy8gSWYgaXQgaXMgYSB0b2tlbiB0eCwgdmVyaWZ5IHRoYXQgdGhlIHJlY2lwaWVudCBhZGRyZXNzIGVxdWFscyB0aGUgZGVyaXZlZCBhZGRyZXNzIGZyb20gZXhwbGFpbmVkVHhcbiAgICAgIC8vIERlcml2ZSB0aGUgQVRBIGlmIGl0IGlzIGEgbmF0aXZlIGFkZHJlc3MgYW5kIGNvbmZpcm0gaXQgaXMgZXF1YWwgdG8gdGhlIGV4cGxhaW5lZCB0eCByZWNpcGllbnRcbiAgICAgIGNvbnN0IHJlY2lwaWVudENoZWNrcyA9IGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgICBmaWx0ZXJlZFJlY2lwaWVudHMubWFwKGFzeW5jIChyZWNpcGllbnRGcm9tVXNlciwgaW5kZXgpID0+IHtcbiAgICAgICAgICBjb25zdCByZWNpcGllbnRGcm9tVHggPSBmaWx0ZXJlZE91dHB1dHNbaW5kZXhdOyAvLyBUaGlzIGFkZHJlc3Mgc2hvdWxkIGJlIGFuIEFUQVxuXG4gICAgICAgICAgLy8gQ29tcGFyZSB0aGUgQmlnTnVtYmVyIHZhbHVlcyBiZWNhdXNlIGFtb3VudCBpcyAoc3RyaW5nIHwgbnVtYmVyKVxuICAgICAgICAgIGNvbnN0IHVzZXJBbW91bnQgPSBuZXcgQmlnTnVtYmVyKHJlY2lwaWVudEZyb21Vc2VyLmFtb3VudCk7XG4gICAgICAgICAgY29uc3QgdHhBbW91bnQgPSBuZXcgQmlnTnVtYmVyKHJlY2lwaWVudEZyb21UeC5hbW91bnQpO1xuICAgICAgICAgIGlmICghdXNlckFtb3VudC5pc0VxdWFsVG8odHhBbW91bnQpKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgLy8gQ29tcGFyZSB0aGUgYWRkcmVzc2VzIGFuZCB0b2tlbk5hbWVzXG4gICAgICAgICAgLy8gRWxzZSBpZiB0aGUgYWRkcmVzc2VzIGFyZSBub3QgdGhlIHNhbWUsIGNoZWNrIHRoZSBkZXJpdmVkIEFUQSBmb3IgcGFyaXR5XG4gICAgICAgICAgaWYgKFxuICAgICAgICAgICAgcmVjaXBpZW50RnJvbVVzZXIuYWRkcmVzcyA9PT0gcmVjaXBpZW50RnJvbVR4LmFkZHJlc3MgJiZcbiAgICAgICAgICAgIHJlY2lwaWVudEZyb21Vc2VyLnRva2VuTmFtZSA9PT0gcmVjaXBpZW50RnJvbVR4LnRva2VuTmFtZVxuICAgICAgICAgICkge1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgfSBlbHNlIGlmIChyZWNpcGllbnRGcm9tVXNlci5hZGRyZXNzICE9PSByZWNpcGllbnRGcm9tVHguYWRkcmVzcyAmJiByZWNpcGllbnRGcm9tVXNlci50b2tlbk5hbWUpIHtcbiAgICAgICAgICAgIC8vIFRyeSB0byBjaGVjayBpZiB0aGUgdXNlcidzIGRlcml2ZWQgQVRBIGlzIGVxdWFsIHRvIHRoZSB0eCByZWNpcGllbnQgYWRkcmVzc1xuICAgICAgICAgICAgLy8gSWYgZ2V0QXNzb2NpYXRlZFRva2VuQWNjb3VudEFkZHJlc3MgdGhyb3dzIGFuIGVycm9yLCB0aGVuIHdlIGFyZSB1bmFibGUgdG8gZGVyaXZlIHRoZSBBVEEgZm9yIHRoYXQgYWRkcmVzcy5cbiAgICAgICAgICAgIC8vIFJldHVybiBmYWxzZSBhbmQgdGhyb3cgYW4gZXJyb3IgaWYgdGhhdCBpcyB0aGUgY2FzZS5cbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgIGNvbnN0IHRva2VuTWludEFkZHJlc3MgPSBnZXRTb2xUb2tlbkZyb21Ub2tlbk5hbWUocmVjaXBpZW50RnJvbVVzZXIudG9rZW5OYW1lKTtcbiAgICAgICAgICAgICAgcmV0dXJuIGdldEFzc29jaWF0ZWRUb2tlbkFjY291bnRBZGRyZXNzKFxuICAgICAgICAgICAgICAgIHRva2VuTWludEFkZHJlc3MhLnRva2VuQWRkcmVzcyxcbiAgICAgICAgICAgICAgICByZWNpcGllbnRGcm9tVXNlci5hZGRyZXNzLFxuICAgICAgICAgICAgICAgIHRydWUsXG4gICAgICAgICAgICAgICAgdG9rZW5NaW50QWRkcmVzcyEucHJvZ3JhbUlkXG4gICAgICAgICAgICAgICkudGhlbigoYXRhOiBzdHJpbmcpID0+IHtcbiAgICAgICAgICAgICAgICByZXR1cm4gYXRhID09PSByZWNpcGllbnRGcm9tVHguYWRkcmVzcztcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9IGNhdGNoIHtcbiAgICAgICAgICAgICAgLy8gVW5hYmxlIHRvIGRlcml2ZSBBVEFcbiAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH0pXG4gICAgICApO1xuXG4gICAgICBpZiAocmVjaXBpZW50Q2hlY2tzLmluY2x1ZGVzKGZhbHNlKSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1R4IG91dHB1dHMgZG9lcyBub3QgbWF0Y2ggd2l0aCBleHBlY3RlZCB0eFBhcmFtcyByZWNpcGllbnRzJyk7XG4gICAgICB9XG4gICAgfSBlbHNlIGlmICh2ZXJpZmljYXRpb25PcHRpb25zPy5jb25zb2xpZGF0aW9uVG9CYXNlQWRkcmVzcykge1xuICAgICAgLy92ZXJpZnkgZnVuZHMgYXJlIHNlbnQgdG8gd2FsbGV0Um9vdEFkZHJlc3MgZm9yIGEgY29uc29saWRhdGlvblxuICAgICAgY29uc3QgZmlsdGVyZWRPdXRwdXRzID0gZXhwbGFpbmVkVHgub3V0cHV0cy5tYXAoKG91dHB1dCkgPT4gXy5waWNrKG91dHB1dCwgWydhZGRyZXNzJywgJ2Ftb3VudCcsICd0b2tlbk5hbWUnXSkpO1xuXG4gICAgICAvLyBDYWNoZSB0byBzdG9yZSBhbHJlYWR5IGRlcml2ZWQgQVRBIGFkZHJlc3Nlc1xuICAgICAgY29uc3QgYXRhQWRkcmVzc0NhY2hlOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0ge307XG5cbiAgICAgIGZvciAoY29uc3Qgb3V0cHV0IG9mIGZpbHRlcmVkT3V0cHV0cykge1xuICAgICAgICBpZiAob3V0cHV0LnRva2VuTmFtZSkge1xuICAgICAgICAgIC8vIENoZWNrIGNhY2hlIGZpcnN0IGJlZm9yZSBkZXJpdmluZyBBVEEgYWRkcmVzc1xuICAgICAgICAgIGlmICghYXRhQWRkcmVzc0NhY2hlW291dHB1dC50b2tlbk5hbWVdKSB7XG4gICAgICAgICAgICBjb25zdCB0b2tlbk1pbnRBZGRyZXNzID0gZ2V0U29sVG9rZW5Gcm9tVG9rZW5OYW1lKG91dHB1dC50b2tlbk5hbWUpO1xuICAgICAgICAgICAgaWYgKHRva2VuTWludEFkZHJlc3M/LnRva2VuQWRkcmVzcyAmJiB0b2tlbk1pbnRBZGRyZXNzPy5wcm9ncmFtSWQpIHtcbiAgICAgICAgICAgICAgYXRhQWRkcmVzc0NhY2hlW291dHB1dC50b2tlbk5hbWVdID0gYXdhaXQgZ2V0QXNzb2NpYXRlZFRva2VuQWNjb3VudEFkZHJlc3MoXG4gICAgICAgICAgICAgICAgdG9rZW5NaW50QWRkcmVzcy50b2tlbkFkZHJlc3MsXG4gICAgICAgICAgICAgICAgd2FsbGV0Um9vdEFkZHJlc3MgYXMgc3RyaW5nLFxuICAgICAgICAgICAgICAgIHRydWUsXG4gICAgICAgICAgICAgICAgdG9rZW5NaW50QWRkcmVzcy5wcm9ncmFtSWRcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgVW5hYmxlIHRvIGdldCB0b2tlbiBpbmZvcm1hdGlvbiBmb3IgJHtvdXRwdXQudG9rZW5OYW1lfWApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmIChhdGFBZGRyZXNzQ2FjaGVbb3V0cHV0LnRva2VuTmFtZV0gIT09IG91dHB1dC5hZGRyZXNzKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ3R4IG91dHB1dHMgZG9lcyBub3QgbWF0Y2ggd2l0aCBleHBlY3RlZCBhZGRyZXNzJyk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKG91dHB1dC5hZGRyZXNzICE9PSB3YWxsZXRSb290QWRkcmVzcykge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcigndHggb3V0cHV0cyBkb2VzIG5vdCBtYXRjaCB3aXRoIGV4cGVjdGVkIGFkZHJlc3MnKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IHRyYW5zYWN0aW9uSnNvbiA9IHRyYW5zYWN0aW9uLnRvSnNvbigpO1xuICAgIGlmIChtZW1vICYmIG1lbW8udmFsdWUgIT09IGV4cGxhaW5lZFR4Lm1lbW8pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignVHggbWVtbyBkb2VzIG5vdCBtYXRjaCB3aXRoIGV4cGVjdGVkIHR4UGFyYW1zIHJlY2lwaWVudCBtZW1vJyk7XG4gICAgfVxuICAgIGlmICh0eFBhcmFtcy5yZWNpcGllbnRzKSB7XG4gICAgICBmb3IgKGNvbnN0IHJlY2lwaWVudHMgb2YgdHhQYXJhbXMucmVjaXBpZW50cykge1xuICAgICAgICAvLyB0b3RhbEFtb3VudCBiYXNlZCBvbiBlYWNoIHRva2VuXG4gICAgICAgIGNvbnN0IGFzc2V0TmFtZSA9IHJlY2lwaWVudHMudG9rZW5OYW1lIHx8IHRoaXMuZ2V0Q2hhaW4oKTtcbiAgICAgICAgY29uc3QgYW1vdW50ID0gdG90YWxBbW91bnRbYXNzZXROYW1lXSB8fCBuZXcgQmlnTnVtYmVyKDApO1xuICAgICAgICB0b3RhbEFtb3VudFthc3NldE5hbWVdID0gYW1vdW50LnBsdXMocmVjaXBpZW50cy5hbW91bnQpO1xuICAgICAgfVxuXG4gICAgICAvLyB0b3RhbCBvdXRwdXQgYW1vdW50IGZyb20gZXhwbGFpbmVkVHhcbiAgICAgIGNvbnN0IGV4cGxhaW5lZFR4VG90YWw6IFJlY29yZDxzdHJpbmcsIEJpZ051bWJlcj4gPSB7fTtcblxuICAgICAgZm9yIChjb25zdCBvdXRwdXQgb2YgZXhwbGFpbmVkVHgub3V0cHV0cykge1xuICAgICAgICAvLyB0b3RhbCBvdXRwdXQgYW1vdW50IGJhc2VkIG9uIGVhY2ggdG9rZW5cbiAgICAgICAgY29uc3QgYXNzZXROYW1lID0gb3V0cHV0LnRva2VuTmFtZSB8fCB0aGlzLmdldENoYWluKCk7XG4gICAgICAgIGNvbnN0IGFtb3VudCA9IGV4cGxhaW5lZFR4VG90YWxbYXNzZXROYW1lXSB8fCBuZXcgQmlnTnVtYmVyKDApO1xuICAgICAgICBleHBsYWluZWRUeFRvdGFsW2Fzc2V0TmFtZV0gPSBhbW91bnQucGx1cyhvdXRwdXQuYW1vdW50KTtcbiAgICAgIH1cblxuICAgICAgaWYgKCFfLmlzRXF1YWwoZXhwbGFpbmVkVHhUb3RhbCwgdG90YWxBbW91bnQpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignVHggdG90YWwgYW1vdW50IGRvZXMgbm90IG1hdGNoIHdpdGggZXhwZWN0ZWQgdG90YWwgYW1vdW50IGZpZWxkJyk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gRm9yIG5vbi1jb25zb2xpZGF0ZSB0cmFuc2FjdGlvbnMsIGZlZVBheWVyIG11c3QgYmUgdGhlIHdhbGxldCdzIHJvb3QgYWRkcmVzc1xuICAgIGlmIChjb25zb2xpZGF0ZUlkID09PSB1bmRlZmluZWQgJiYgdHJhbnNhY3Rpb25Kc29uLmZlZVBheWVyICE9PSB3YWxsZXRSb290QWRkcmVzcykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdUeCBmZWUgcGF5ZXIgaXMgbm90IHRoZSB3YWxsZXQgcm9vdCBhZGRyZXNzJyk7XG4gICAgfVxuXG4gICAgaWYgKGR1cmFibGVOb25jZSAmJiAhXy5pc0VxdWFsKGV4cGxhaW5lZFR4LmR1cmFibGVOb25jZSwgZHVyYWJsZU5vbmNlKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdUeCBkdXJhYmxlTm9uY2UgZG9lcyBub3QgbWF0Y2ggd2l0aCBwYXJhbSBkdXJhYmxlTm9uY2UnKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIGFzeW5jIGlzV2FsbGV0QWRkcmVzcyhwYXJhbXM6IFRzc1ZlcmlmeUFkZHJlc3NPcHRpb25zKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgcmV0dXJuIHZlcmlmeUVkZHNhVHNzV2FsbGV0QWRkcmVzcyhcbiAgICAgIHBhcmFtcyxcbiAgICAgIChhZGRyZXNzKSA9PiB0aGlzLmlzVmFsaWRBZGRyZXNzKGFkZHJlc3MpLFxuICAgICAgKHB1YmxpY0tleSkgPT4gdGhpcy5nZXRBZGRyZXNzRnJvbVB1YmxpY0tleShwdWJsaWNLZXkpXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDb252ZXJ0cyBhIFNvbGFuYSBwdWJsaWMga2V5IHRvIGFuIGFkZHJlc3NcbiAgICogQHBhcmFtIHB1YmxpY0tleSBIZXgtZW5jb2RlZCBwdWJsaWMga2V5ICg2NCBoZXggY2hhcmFjdGVycyA9IDMyIGJ5dGVzKVxuICAgKiBAcmV0dXJucyBCYXNlNTgtZW5jb2RlZCBTb2xhbmEgYWRkcmVzc1xuICAgKi9cbiAgZ2V0QWRkcmVzc0Zyb21QdWJsaWNLZXkocHVibGljS2V5OiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIGNvbnN0IHB1YmxpY0tleUJ1ZmZlciA9IEJ1ZmZlci5mcm9tKHB1YmxpY0tleSwgJ2hleCcpO1xuICAgIHJldHVybiBiYXNlNTguZW5jb2RlKHB1YmxpY0tleUJ1ZmZlcik7XG4gIH1cblxuICAvKipcbiAgICogR2VuZXJhdGUgU29sYW5hIGtleSBwYWlyXG4gICAqXG4gICAqIEBwYXJhbSB7QnVmZmVyfSBzZWVkIC0gU2VlZCBmcm9tIHdoaWNoIHRoZSBuZXcgU29sS2V5UGFpciBzaG91bGQgYmUgZ2VuZXJhdGVkLCBvdGhlcndpc2UgYSByYW5kb20gc2VlZCBpcyB1c2VkXG4gICAqIEByZXR1cm5zIHtPYmplY3R9IG9iamVjdCB3aXRoIGdlbmVyYXRlZCBwdWIgYW5kIHBydlxuICAgKi9cbiAgZ2VuZXJhdGVLZXlQYWlyKHNlZWQ/OiBCdWZmZXIgfCB1bmRlZmluZWQpOiBLZXlQYWlyIHtcbiAgICBjb25zdCByZXN1bHQgPSBzZWVkID8gbmV3IFNvbEtleVBhaXIoeyBzZWVkIH0pLmdldEtleXMoKSA6IG5ldyBTb2xLZXlQYWlyKCkuZ2V0S2V5cygpO1xuICAgIHJldHVybiByZXN1bHQgYXMgS2V5UGFpcjtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm4gYm9vbGVhbiBpbmRpY2F0aW5nIHdoZXRoZXIgaW5wdXQgaXMgdmFsaWQgcHVibGljIGtleSBmb3IgdGhlIGNvaW5cbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IHB1YiB0aGUgcHJ2IHRvIGJlIGNoZWNrZWRcbiAgICogQHJldHVybnMgaXMgaXQgdmFsaWQ/XG4gICAqL1xuICBpc1ZhbGlkUHViKHB1Yjogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIGlzVmFsaWRQdWJsaWNLZXkocHViKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm4gYm9vbGVhbiBpbmRpY2F0aW5nIHdoZXRoZXIgaW5wdXQgaXMgdmFsaWQgcHJpdmF0ZSBrZXkgZm9yIHRoZSBjb2luXG4gICAqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBwcnYgdGhlIHBydiB0byBiZSBjaGVja2VkXG4gICAqIEByZXR1cm5zIGlzIGl0IHZhbGlkP1xuICAgKi9cbiAgaXNWYWxpZFBydihwcnY6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIHJldHVybiBpc1ZhbGlkUHJpdmF0ZUtleShwcnYpO1xuICB9XG5cbiAgaXNWYWxpZEFkZHJlc3MoYWRkcmVzczogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIGlzVmFsaWRBZGRyZXNzKGFkZHJlc3MpO1xuICB9XG5cbiAgYXN5bmMgc2lnbk1lc3NhZ2Uoa2V5OiBLZXlQYWlyLCBtZXNzYWdlOiBzdHJpbmcgfCBCdWZmZXIpOiBQcm9taXNlPEJ1ZmZlcj4ge1xuICAgIGNvbnN0IHNvbEtleXBhaXIgPSBuZXcgU29sS2V5UGFpcih7IHBydjoga2V5LnBydiB9KTtcbiAgICBpZiAoQnVmZmVyLmlzQnVmZmVyKG1lc3NhZ2UpKSB7XG4gICAgICBtZXNzYWdlID0gYmFzZTU4LmVuY29kZShtZXNzYWdlKTtcbiAgICB9XG5cbiAgICByZXR1cm4gQnVmZmVyLmZyb20oc29sS2V5cGFpci5zaWduTWVzc2FnZShtZXNzYWdlKSk7XG4gIH1cblxuICAvKipcbiAgICogU2lnbnMgU29sYW5hIHRyYW5zYWN0aW9uXG4gICAqIEBwYXJhbSBwYXJhbXNcbiAgICogQHBhcmFtIGNhbGxiYWNrXG4gICAqL1xuICBhc3luYyBzaWduVHJhbnNhY3Rpb24ocGFyYW1zOiBTb2xTaWduVHJhbnNhY3Rpb25PcHRpb25zKTogUHJvbWlzZTxTaWduZWRUcmFuc2FjdGlvbj4ge1xuICAgIGNvbnN0IGZhY3RvcnkgPSB0aGlzLmdldEJ1aWxkZXIoKTtcbiAgICBjb25zdCByYXdUeCA9IHBhcmFtcy50eFByZWJ1aWxkLnR4SGV4IHx8IHBhcmFtcy50eFByZWJ1aWxkLnR4QmFzZTY0O1xuICAgIGNvbnN0IHR4QnVpbGRlciA9IGZhY3RvcnkuZnJvbShyYXdUeCk7XG4gICAgdHhCdWlsZGVyLnNpZ24oeyBrZXk6IHBhcmFtcy5wcnYgfSk7XG4gICAgY29uc3QgdHJhbnNhY3Rpb246IEJhc2VUcmFuc2FjdGlvbiA9IGF3YWl0IHR4QnVpbGRlci5idWlsZCgpO1xuXG4gICAgaWYgKCF0cmFuc2FjdGlvbikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIHRyYW5zYWN0aW9uJyk7XG4gICAgfVxuXG4gICAgY29uc3Qgc2VyaWFsaXplZFR4ID0gKHRyYW5zYWN0aW9uIGFzIEJhc2VUcmFuc2FjdGlvbikudG9Ccm9hZGNhc3RGb3JtYXQoKTtcblxuICAgIHJldHVybiB7XG4gICAgICB0eEhleDogc2VyaWFsaXplZFR4LFxuICAgIH0gYXMgYW55O1xuICB9XG5cbiAgYXN5bmMgcGFyc2VUcmFuc2FjdGlvbihwYXJhbXM6IFNvbFBhcnNlVHJhbnNhY3Rpb25PcHRpb25zKTogUHJvbWlzZTxTb2xQYXJzZWRUcmFuc2FjdGlvbj4ge1xuICAgIGNvbnN0IHRyYW5zYWN0aW9uRXhwbGFuYXRpb24gPSBhd2FpdCB0aGlzLmV4cGxhaW5UcmFuc2FjdGlvbih7XG4gICAgICB0eEJhc2U2NDogcGFyYW1zLnR4QmFzZTY0LFxuICAgICAgZmVlSW5mbzogcGFyYW1zLmZlZUluZm8sXG4gICAgICB0b2tlbkFjY291bnRSZW50RXhlbXB0QW1vdW50OiBwYXJhbXMudG9rZW5BY2NvdW50UmVudEV4ZW1wdEFtb3VudCxcbiAgICB9KTtcblxuICAgIGlmICghdHJhbnNhY3Rpb25FeHBsYW5hdGlvbikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIHRyYW5zYWN0aW9uJyk7XG4gICAgfVxuXG4gICAgY29uc3Qgc29sVHJhbnNhY3Rpb24gPSB0cmFuc2FjdGlvbkV4cGxhbmF0aW9uIGFzIFNvbFRyYW5zYWN0aW9uRXhwbGFuYXRpb247XG4gICAgaWYgKHNvbFRyYW5zYWN0aW9uLm91dHB1dHMubGVuZ3RoIDw9IDApIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIGlucHV0czogW10sXG4gICAgICAgIG91dHB1dHM6IFtdLFxuICAgICAgfTtcbiAgICB9XG5cbiAgICBjb25zdCBzZW5kZXJBZGRyZXNzID0gc29sVHJhbnNhY3Rpb24ub3V0cHV0c1swXS5hZGRyZXNzO1xuICAgIGNvbnN0IGZlZUFtb3VudCA9IG5ldyBCaWdOdW1iZXIoc29sVHJhbnNhY3Rpb24uZmVlLmZlZSk7XG5cbiAgICAvLyBhc3N1bWUgMSBzZW5kZXIsIHdobyBpcyBhbHNvIHRoZSBmZWUgcGF5ZXJcbiAgICBjb25zdCBpbnB1dHMgPSBbXG4gICAgICB7XG4gICAgICAgIGFkZHJlc3M6IHNlbmRlckFkZHJlc3MsXG4gICAgICAgIGFtb3VudDogbmV3IEJpZ051bWJlcihzb2xUcmFuc2FjdGlvbi5vdXRwdXRBbW91bnQpLnBsdXMoZmVlQW1vdW50KS50b051bWJlcigpLFxuICAgICAgfSxcbiAgICBdO1xuXG4gICAgY29uc3Qgb3V0cHV0czogVHJhbnNhY3Rpb25PdXRwdXRbXSA9IHNvbFRyYW5zYWN0aW9uLm91dHB1dHMubWFwKCh7IGFkZHJlc3MsIGFtb3VudCwgdG9rZW5OYW1lIH0pID0+IHtcbiAgICAgIGNvbnN0IG91dHB1dDogVHJhbnNhY3Rpb25PdXRwdXQgPSB7IGFkZHJlc3MsIGFtb3VudCB9O1xuICAgICAgaWYgKHRva2VuTmFtZSkge1xuICAgICAgICBvdXRwdXQudG9rZW5OYW1lID0gdG9rZW5OYW1lO1xuICAgICAgfVxuICAgICAgcmV0dXJuIG91dHB1dDtcbiAgICB9KTtcblxuICAgIHJldHVybiB7XG4gICAgICBpbnB1dHMsXG4gICAgICBvdXRwdXRzLFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogRXhwbGFpbiBhIFNvbGFuYSB0cmFuc2FjdGlvbiBmcm9tIHR4QmFzZTY0XG4gICAqIEBwYXJhbSBwYXJhbXNcbiAgICovXG4gIGFzeW5jIGV4cGxhaW5UcmFuc2FjdGlvbihwYXJhbXM6IEV4cGxhaW5UcmFuc2FjdGlvbk9wdGlvbnMpOiBQcm9taXNlPFNvbFRyYW5zYWN0aW9uRXhwbGFuYXRpb24+IHtcbiAgICBjb25zdCBmYWN0b3J5ID0gdGhpcy5nZXRCdWlsZGVyKCk7XG4gICAgbGV0IHJlYnVpbHRUcmFuc2FjdGlvbjtcblxuICAgIHRyeSB7XG4gICAgICBjb25zdCB0cmFuc2FjdGlvbkJ1aWxkZXIgPSBmYWN0b3J5LmZyb20ocGFyYW1zLnR4QmFzZTY0KTtcbiAgICAgIGlmICh0cmFuc2FjdGlvbkJ1aWxkZXIgaW5zdGFuY2VvZiBUcmFuc2FjdGlvbkJ1aWxkZXIpIHtcbiAgICAgICAgY29uc3QgdHhCdWlsZGVyID0gdHJhbnNhY3Rpb25CdWlsZGVyIGFzIFRyYW5zYWN0aW9uQnVpbGRlcjtcbiAgICAgICAgdHhCdWlsZGVyLmZlZSh7IGFtb3VudDogcGFyYW1zLmZlZUluZm8uZmVlIH0pO1xuICAgICAgICBpZiAocGFyYW1zLnRva2VuQWNjb3VudFJlbnRFeGVtcHRBbW91bnQpIHtcbiAgICAgICAgICB0eEJ1aWxkZXIuYXNzb2NpYXRlZFRva2VuQWNjb3VudFJlbnQocGFyYW1zLnRva2VuQWNjb3VudFJlbnRFeGVtcHRBbW91bnQpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZWJ1aWx0VHJhbnNhY3Rpb24gPSBhd2FpdCB0cmFuc2FjdGlvbkJ1aWxkZXIuYnVpbGQoKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBjb25zb2xlLmxvZyhlKTtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCB0cmFuc2FjdGlvbicpO1xuICAgIH1cblxuICAgIGNvbnN0IGV4cGxhaW5lZFRyYW5zYWN0aW9uID0gKHJlYnVpbHRUcmFuc2FjdGlvbiBhcyBCYXNlVHJhbnNhY3Rpb24pLmV4cGxhaW5UcmFuc2FjdGlvbigpO1xuXG4gICAgcmV0dXJuIGV4cGxhaW5lZFRyYW5zYWN0aW9uIGFzIFNvbFRyYW5zYWN0aW9uRXhwbGFuYXRpb247XG4gIH1cblxuICAvKiogQGluaGVyaXREb2MgKi9cbiAgYXN5bmMgZ2V0U2lnbmFibGVQYXlsb2FkKHNlcmlhbGl6ZWRUeDogc3RyaW5nKTogUHJvbWlzZTxCdWZmZXI+IHtcbiAgICBjb25zdCBmYWN0b3J5ID0gdGhpcy5nZXRCdWlsZGVyKCk7XG4gICAgY29uc3QgcmVidWlsdFRyYW5zYWN0aW9uID0gYXdhaXQgZmFjdG9yeS5mcm9tKHNlcmlhbGl6ZWRUeCkuYnVpbGQoKTtcbiAgICByZXR1cm4gcmVidWlsdFRyYW5zYWN0aW9uLnNpZ25hYmxlUGF5bG9hZDtcbiAgfVxuXG4gIC8qKiBAaW5oZXJpdERvYyAqL1xuICBhc3luYyBwcmVzaWduVHJhbnNhY3Rpb24ocGFyYW1zOiBQcmVzaWduVHJhbnNhY3Rpb25PcHRpb25zKTogUHJvbWlzZTxQcmVzaWduVHJhbnNhY3Rpb25PcHRpb25zPiB7XG4gICAgLy8gSG90IHdhbGxldCB0eG5zIGFyZSBvbmx5IHZhbGlkIGZvciAxLTIgbWludXRlcy5cbiAgICAvLyBUbyBidXkgbW9yZSB0aW1lLCB3ZSByZWJ1aWxkIHRoZSB0cmFuc2FjdGlvbiB3aXRoIGEgbmV3IGJsb2NraGFzaCByaWdodCBiZWZvcmUgd2Ugc2lnbi5cbiAgICBpZiAocGFyYW1zLndhbGxldERhdGEudHlwZSAhPT0gJ2hvdCcpIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUocGFyYW1zKTtcbiAgICB9XG5cbiAgICBjb25zdCB0eFJlcXVlc3RJZCA9IHBhcmFtcy50eFByZWJ1aWxkPy50eFJlcXVlc3RJZDtcbiAgICBpZiAodHhSZXF1ZXN0SWQgPT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdNaXNzaW5nIHR4UmVxdWVzdElkJyk7XG4gICAgfVxuXG4gICAgY29uc3QgeyB0c3NVdGlscyB9ID0gcGFyYW1zO1xuXG4gICAgYXdhaXQgdHNzVXRpbHMhLmRlbGV0ZVNpZ25hdHVyZVNoYXJlcyh0eFJlcXVlc3RJZCk7XG4gICAgY29uc3QgcmVjcmVhdGVkID0gYXdhaXQgdHNzVXRpbHMhLmdldFR4UmVxdWVzdCh0eFJlcXVlc3RJZCk7XG4gICAgbGV0IHR4SGV4ID0gJyc7XG4gICAgaWYgKHJlY3JlYXRlZC51bnNpZ25lZFR4cykge1xuICAgICAgdHhIZXggPSByZWNyZWF0ZWQudW5zaWduZWRUeHNbMF0/LnNlcmlhbGl6ZWRUeEhleDtcbiAgICB9IGVsc2Uge1xuICAgICAgdHhIZXggPSByZWNyZWF0ZWQudHJhbnNhY3Rpb25zID8gcmVjcmVhdGVkLnRyYW5zYWN0aW9uc1swXT8udW5zaWduZWRUeC5zZXJpYWxpemVkVHhIZXggOiAnJztcbiAgICB9XG5cbiAgICBpZiAoIXR4SGV4KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ01pc3Npbmcgc2VyaWFsaXplZCB0eCBoZXgnKTtcbiAgICB9XG5cbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHtcbiAgICAgIC4uLnBhcmFtcyxcbiAgICAgIHR4UHJlYnVpbGQ6IHJlY3JlYXRlZCxcbiAgICAgIHR4SGV4LFxuICAgIH0pO1xuICB9XG5cbiAgcHJvdGVjdGVkIGdldFB1YmxpY05vZGVVcmwoYXBpS2V5Pzogc3RyaW5nKTogc3RyaW5nIHtcbiAgICBpZiAoYXBpS2V5KSB7XG4gICAgICByZXR1cm4gRW52aXJvbm1lbnRzW3RoaXMuYml0Z28uZ2V0RW52KCldLnNvbEFsY2hlbXlOb2RlVXJsICsgYC8ke2FwaUtleX1gO1xuICAgIH1cbiAgICByZXR1cm4gRW52aXJvbm1lbnRzW3RoaXMuYml0Z28uZ2V0RW52KCldLnNvbE5vZGVVcmw7XG4gIH1cblxuICAvKipcbiAgICogTWFrZSBhIHJlcXVlc3QgdG8gb25lIG9mIHRoZSBwdWJsaWMgU09MIG5vZGVzIGF2YWlsYWJsZVxuICAgKiBAcGFyYW0gcGFyYW1zLnBheWxvYWRcbiAgICovXG4gIHByb3RlY3RlZCBhc3luYyBnZXREYXRhRnJvbU5vZGUoXG4gICAgcGFyYW1zOiB7IHBheWxvYWQ/OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiB9LFxuICAgIGFwaUtleT86IHN0cmluZ1xuICApOiBQcm9taXNlPHJlcXVlc3QuUmVzcG9uc2U+IHtcbiAgICBjb25zdCBub2RlVXJsID0gdGhpcy5nZXRQdWJsaWNOb2RlVXJsKGFwaUtleSk7XG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiBhd2FpdCByZXF1ZXN0LnBvc3Qobm9kZVVybCkuc2VuZChwYXJhbXMucGF5bG9hZCk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgY29uc29sZS5kZWJ1ZyhlKTtcbiAgICB9XG4gICAgdGhyb3cgbmV3IEVycm9yKGBVbmFibGUgdG8gY2FsbCBlbmRwb2ludDogJy8nIGZyb20gbm9kZTogJHtub2RlVXJsfWApO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIGdldEJsb2NraGFzaChhcGlLZXk/OiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5nZXREYXRhRnJvbU5vZGUoXG4gICAgICB7XG4gICAgICAgIHBheWxvYWQ6IHtcbiAgICAgICAgICBpZDogJzEnLFxuICAgICAgICAgIGpzb25ycGM6ICcyLjAnLFxuICAgICAgICAgIG1ldGhvZDogJ2dldExhdGVzdEJsb2NraGFzaCcsXG4gICAgICAgICAgcGFyYW1zOiBbXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIGNvbW1pdG1lbnQ6ICdmaW5hbGl6ZWQnLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICBdLFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICAgIGFwaUtleVxuICAgICk7XG4gICAgaWYgKHJlc3BvbnNlLnN0YXR1cyAhPT0gMjAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0FjY291bnQgbm90IGZvdW5kJyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlc3BvbnNlLmJvZHkucmVzdWx0LnZhbHVlLmJsb2NraGFzaDtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBnZXRGZWVGb3JNZXNzYWdlKG1lc3NhZ2U6IHN0cmluZywgYXBpS2V5Pzogc3RyaW5nKTogUHJvbWlzZTxudW1iZXI+IHtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMuZ2V0RGF0YUZyb21Ob2RlKFxuICAgICAge1xuICAgICAgICBwYXlsb2FkOiB7XG4gICAgICAgICAgaWQ6ICcxJyxcbiAgICAgICAgICBqc29ucnBjOiAnMi4wJyxcbiAgICAgICAgICBtZXRob2Q6ICdnZXRGZWVGb3JNZXNzYWdlJyxcbiAgICAgICAgICBwYXJhbXM6IFtcbiAgICAgICAgICAgIG1lc3NhZ2UsXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIGNvbW1pdG1lbnQ6ICdmaW5hbGl6ZWQnLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICBdLFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICAgIGFwaUtleVxuICAgICk7XG4gICAgaWYgKHJlc3BvbnNlLnN0YXR1cyAhPT0gMjAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0FjY291bnQgbm90IGZvdW5kJyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlc3BvbnNlLmJvZHkucmVzdWx0LnZhbHVlO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIGdldFJlbnRFeGVtcHRBbW91bnQoYXBpS2V5Pzogc3RyaW5nKTogUHJvbWlzZTxudW1iZXI+IHtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMuZ2V0RGF0YUZyb21Ob2RlKFxuICAgICAge1xuICAgICAgICBwYXlsb2FkOiB7XG4gICAgICAgICAganNvbnJwYzogJzIuMCcsXG4gICAgICAgICAgaWQ6ICcxJyxcbiAgICAgICAgICBtZXRob2Q6ICdnZXRNaW5pbXVtQmFsYW5jZUZvclJlbnRFeGVtcHRpb24nLFxuICAgICAgICAgIHBhcmFtczogWzE2NV0sXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgICAgYXBpS2V5XG4gICAgKTtcbiAgICBpZiAocmVzcG9uc2Uuc3RhdHVzICE9PSAyMDAgfHwgcmVzcG9uc2UuZXJyb3IpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihKU09OLnN0cmluZ2lmeShyZXNwb25zZS5lcnJvcikpO1xuICAgIH1cblxuICAgIHJldHVybiByZXNwb25zZS5ib2R5LnJlc3VsdDtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBnZXRBY2NvdW50QmFsYW5jZShwdWJLZXk6IHN0cmluZywgYXBpS2V5Pzogc3RyaW5nKTogUHJvbWlzZTxudW1iZXI+IHtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMuZ2V0RGF0YUZyb21Ob2RlKFxuICAgICAge1xuICAgICAgICBwYXlsb2FkOiB7XG4gICAgICAgICAgaWQ6ICcxJyxcbiAgICAgICAgICBqc29ucnBjOiAnMi4wJyxcbiAgICAgICAgICBtZXRob2Q6ICdnZXRCYWxhbmNlJyxcbiAgICAgICAgICBwYXJhbXM6IFtwdWJLZXldLFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICAgIGFwaUtleVxuICAgICk7XG4gICAgaWYgKHJlc3BvbnNlLnN0YXR1cyAhPT0gMjAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0FjY291bnQgbm90IGZvdW5kJyk7XG4gICAgfVxuICAgIHJldHVybiByZXNwb25zZS5ib2R5LnJlc3VsdC52YWx1ZTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBnZXRBY2NvdW50SW5mbyhwdWJLZXk6IHN0cmluZywgYXBpS2V5Pzogc3RyaW5nKTogUHJvbWlzZTxTb2xEdXJhYmxlTm9uY2VGcm9tTm9kZT4ge1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5nZXREYXRhRnJvbU5vZGUoXG4gICAgICB7XG4gICAgICAgIHBheWxvYWQ6IHtcbiAgICAgICAgICBpZDogJzEnLFxuICAgICAgICAgIGpzb25ycGM6ICcyLjAnLFxuICAgICAgICAgIG1ldGhvZDogJ2dldEFjY291bnRJbmZvJyxcbiAgICAgICAgICBwYXJhbXM6IFtcbiAgICAgICAgICAgIHB1YktleSxcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgZW5jb2Rpbmc6ICdqc29uUGFyc2VkJyxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgXSxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgICBhcGlLZXlcbiAgICApO1xuICAgIGlmIChyZXNwb25zZS5zdGF0dXMgIT09IDIwMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdBY2NvdW50IG5vdCBmb3VuZCcpO1xuICAgIH1cbiAgICByZXR1cm4ge1xuICAgICAgYXV0aG9yaXR5OiByZXNwb25zZS5ib2R5LnJlc3VsdC52YWx1ZS5kYXRhLnBhcnNlZC5pbmZvLmF1dGhvcml0eSxcbiAgICAgIGJsb2NraGFzaDogcmVzcG9uc2UuYm9keS5yZXN1bHQudmFsdWUuZGF0YS5wYXJzZWQuaW5mby5ibG9ja2hhc2gsXG4gICAgfTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBnZXRUb2tlbkFjY291bnRzQnlPd25lcihwdWJLZXkgPSAnJywgcHJvZ3JhbUlkID0gJycsIGFwaUtleT86IHN0cmluZyk6IFByb21pc2U8W10gfCBUb2tlbkFjY291bnRbXT4ge1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5nZXREYXRhRnJvbU5vZGUoXG4gICAgICB7XG4gICAgICAgIHBheWxvYWQ6IHtcbiAgICAgICAgICBpZDogJzEnLFxuICAgICAgICAgIGpzb25ycGM6ICcyLjAnLFxuICAgICAgICAgIG1ldGhvZDogJ2dldFRva2VuQWNjb3VudHNCeU93bmVyJyxcbiAgICAgICAgICBwYXJhbXM6IFtcbiAgICAgICAgICAgIHB1YktleSxcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgcHJvZ3JhbUlkOlxuICAgICAgICAgICAgICAgIHByb2dyYW1JZC50b1N0cmluZygpLnRvTG93ZXJDYXNlKCkgPT09IFRPS0VOXzIwMjJfUFJPR1JBTV9JRC50b1N0cmluZygpLnRvTG93ZXJDYXNlKClcbiAgICAgICAgICAgICAgICAgID8gVE9LRU5fMjAyMl9QUk9HUkFNX0lELnRvU3RyaW5nKClcbiAgICAgICAgICAgICAgICAgIDogVE9LRU5fUFJPR1JBTV9JRC50b1N0cmluZygpLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgZW5jb2Rpbmc6ICdqc29uUGFyc2VkJyxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgXSxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgICBhcGlLZXlcbiAgICApO1xuICAgIGlmIChyZXNwb25zZS5zdGF0dXMgIT09IDIwMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdBY2NvdW50IG5vdCBmb3VuZCcpO1xuICAgIH1cblxuICAgIGlmIChyZXNwb25zZS5ib2R5LnJlc3VsdC52YWx1ZS5sZW5ndGggIT09IDApIHtcbiAgICAgIGNvbnN0IHRva2VuQWNjb3VudHM6IFRva2VuQWNjb3VudFtdID0gW107XG4gICAgICBmb3IgKGNvbnN0IHRva2VuQWNjb3VudCBvZiByZXNwb25zZS5ib2R5LnJlc3VsdC52YWx1ZSkge1xuICAgICAgICB0b2tlbkFjY291bnRzLnB1c2goeyBpbmZvOiB0b2tlbkFjY291bnQuYWNjb3VudC5kYXRhLnBhcnNlZC5pbmZvLCBwdWJLZXk6IHRva2VuQWNjb3VudC5wdWJLZXkgfSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gdG9rZW5BY2NvdW50cztcbiAgICB9XG5cbiAgICByZXR1cm4gW107XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgZ2V0VG9rZW5BY2NvdW50SW5mbyhwdWJLZXk6IHN0cmluZywgYXBpS2V5Pzogc3RyaW5nKTogUHJvbWlzZTxUb2tlbkFjY291bnQ+IHtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMuZ2V0RGF0YUZyb21Ob2RlKFxuICAgICAge1xuICAgICAgICBwYXlsb2FkOiB7XG4gICAgICAgICAgaWQ6ICcxJyxcbiAgICAgICAgICBqc29ucnBjOiAnMi4wJyxcbiAgICAgICAgICBtZXRob2Q6ICdnZXRBY2NvdW50SW5mbycsXG4gICAgICAgICAgcGFyYW1zOiBbXG4gICAgICAgICAgICBwdWJLZXksXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIGVuY29kaW5nOiAnanNvblBhcnNlZCcsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIF0sXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgICAgYXBpS2V5XG4gICAgKTtcbiAgICBpZiAocmVzcG9uc2Uuc3RhdHVzICE9PSAyMDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQWNjb3VudCBub3QgZm91bmQnKTtcbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgIHB1YktleTogcHViS2V5LFxuICAgICAgaW5mbzogcmVzcG9uc2UuYm9keS5yZXN1bHQudmFsdWUuZGF0YS5wYXJzZWQuaW5mbyxcbiAgICB9O1xuICB9XG5cbiAgLyoqIGluaGVyaXRlZCBkb2MgKi9cbiAgYXN5bmMgY3JlYXRlQnJvYWRjYXN0YWJsZVN3ZWVwVHJhbnNhY3Rpb24ocGFyYW1zOiBNUENTd2VlcFJlY292ZXJ5T3B0aW9ucyk6IFByb21pc2U8TVBDVHhzPiB7XG4gICAgaWYgKCFwYXJhbXMuc2lnbmF0dXJlU2hhcmVzKSB7XG4gICAgICAoJ01pc3NpbmcgdHJhbnNhY3Rpb24ocyknKTtcbiAgICB9XG4gICAgY29uc3QgcmVxID0gcGFyYW1zLnNpZ25hdHVyZVNoYXJlcztcbiAgICBjb25zdCBicm9hZGNhc3RhYmxlVHJhbnNhY3Rpb25zOiBNUENUeFtdID0gW107XG4gICAgbGV0IGxhc3RTY2FuSW5kZXggPSAwO1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCByZXEubGVuZ3RoOyBpKyspIHtcbiAgICAgIGNvbnN0IE1QQyA9IGF3YWl0IEVERFNBTWV0aG9kcy5nZXRJbml0aWFsaXplZE1wY0luc3RhbmNlKCk7XG4gICAgICBjb25zdCB0cmFuc2FjdGlvbiA9IHJlcVtpXS50eFJlcXVlc3QudHJhbnNhY3Rpb25zWzBdLnVuc2lnbmVkVHg7XG4gICAgICBpZiAoIXJlcVtpXS5vdmMgfHwgIXJlcVtpXS5vdmNbMF0uZWRkc2FTaWduYXR1cmUpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdNaXNzaW5nIHNpZ25hdHVyZShzKScpO1xuICAgICAgfVxuICAgICAgY29uc3Qgc2lnbmF0dXJlID0gcmVxW2ldLm92Y1swXS5lZGRzYVNpZ25hdHVyZTtcbiAgICAgIGlmICghdHJhbnNhY3Rpb24uc2lnbmFibGVIZXgpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdNaXNzaW5nIHNpZ25hYmxlIGhleCcpO1xuICAgICAgfVxuICAgICAgY29uc3QgbWVzc2FnZUJ1ZmZlciA9IEJ1ZmZlci5mcm9tKHRyYW5zYWN0aW9uLnNpZ25hYmxlSGV4ISwgJ2hleCcpO1xuICAgICAgY29uc3QgcmVzdWx0ID0gTVBDLnZlcmlmeShtZXNzYWdlQnVmZmVyLCBzaWduYXR1cmUpO1xuICAgICAgaWYgKCFyZXN1bHQpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIHNpZ25hdHVyZScpO1xuICAgICAgfVxuICAgICAgY29uc3Qgc2lnbmF0dXJlSGV4ID0gQnVmZmVyLmNvbmNhdChbQnVmZmVyLmZyb20oc2lnbmF0dXJlLlIsICdoZXgnKSwgQnVmZmVyLmZyb20oc2lnbmF0dXJlLnNpZ21hLCAnaGV4JyldKTtcbiAgICAgIGNvbnN0IHR4QnVpbGRlciA9IHRoaXMuZ2V0QnVpbGRlcigpLmZyb20odHJhbnNhY3Rpb24uc2VyaWFsaXplZFR4IGFzIHN0cmluZyk7XG4gICAgICBpZiAoIXRyYW5zYWN0aW9uLmNvaW5TcGVjaWZpYz8uY29tbW9uS2V5Y2hhaW4pIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdNaXNzaW5nIGNvbW1vbiBrZXljaGFpbicpO1xuICAgICAgfVxuICAgICAgY29uc3QgY29tbW9uS2V5Y2hhaW4gPSB0cmFuc2FjdGlvbi5jb2luU3BlY2lmaWMhLmNvbW1vbktleWNoYWluISBhcyBzdHJpbmc7XG4gICAgICBpZiAoIXRyYW5zYWN0aW9uLmRlcml2YXRpb25QYXRoKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignTWlzc2luZyBkZXJpdmF0aW9uIHBhdGgnKTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGRlcml2YXRpb25QYXRoID0gdHJhbnNhY3Rpb24uZGVyaXZhdGlvblBhdGggYXMgc3RyaW5nO1xuICAgICAgY29uc3QgYWNjb3VudElkID0gTVBDLmRlcml2ZVVuaGFyZGVuZWQoY29tbW9uS2V5Y2hhaW4sIGRlcml2YXRpb25QYXRoKS5zbGljZSgwLCA2NCk7XG4gICAgICBjb25zdCBiczU4RW5jb2RlZFB1YmxpY0tleSA9IG5ldyBTb2xLZXlQYWlyKHsgcHViOiBhY2NvdW50SWQgfSkuZ2V0QWRkcmVzcygpO1xuXG4gICAgICAvLyBhZGQgY29tYmluZWQgc2lnbmF0dXJlIGZyb20gb3ZjXG4gICAgICBjb25zdCBwdWJsaWNLZXlPYmogPSB7IHB1YjogYnM1OEVuY29kZWRQdWJsaWNLZXkgfTtcbiAgICAgIHR4QnVpbGRlci5hZGRTaWduYXR1cmUocHVibGljS2V5T2JqIGFzIFB1YmxpY0tleSwgc2lnbmF0dXJlSGV4KTtcblxuICAgICAgY29uc3Qgc2lnbmVkVHJhbnNhY3Rpb24gPSBhd2FpdCB0eEJ1aWxkZXIuYnVpbGQoKTtcbiAgICAgIGNvbnN0IHNlcmlhbGl6ZWRUeCA9IHNpZ25lZFRyYW5zYWN0aW9uLnRvQnJvYWRjYXN0Rm9ybWF0KCk7XG5cbiAgICAgIGJyb2FkY2FzdGFibGVUcmFuc2FjdGlvbnMucHVzaCh7XG4gICAgICAgIHNlcmlhbGl6ZWRUeDogc2VyaWFsaXplZFR4LFxuICAgICAgICBzY2FuSW5kZXg6IHRyYW5zYWN0aW9uLnNjYW5JbmRleCxcbiAgICAgIH0pO1xuXG4gICAgICBpZiAoaSA9PT0gcmVxLmxlbmd0aCAtIDEgJiYgdHJhbnNhY3Rpb24uY29pblNwZWNpZmljIS5sYXN0U2NhbkluZGV4KSB7XG4gICAgICAgIGxhc3RTY2FuSW5kZXggPSB0cmFuc2FjdGlvbi5jb2luU3BlY2lmaWMhLmxhc3RTY2FuSW5kZXggYXMgbnVtYmVyO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB7IHRyYW5zYWN0aW9uczogYnJvYWRjYXN0YWJsZVRyYW5zYWN0aW9ucywgbGFzdFNjYW5JbmRleCB9O1xuICB9XG5cbiAgLyoqXG4gICAqIEJ1aWxkcyBhIGZ1bmRzIHJlY292ZXJ5IHRyYW5zYWN0aW9uIHdpdGhvdXQgQml0R29cbiAgICogQHBhcmFtIHtTb2xSZWNvdmVyeU9wdGlvbnN9IHBhcmFtcyBwYXJhbWV0ZXJzIG5lZWRlZCB0byBjb25zdHJ1Y3QgYW5kXG4gICAqIChtYXliZSkgc2lnbiB0aGUgdHJhbnNhY3Rpb25cbiAgICpcbiAgICogQHJldHVybnMge01QQ1R4IHwgTVBDU3dlZXBUeHN9IHRoZSBzZXJpYWxpemVkIHRyYW5zYWN0aW9uIGhleCBzdHJpbmcgYW5kIGluZGV4XG4gICAqIG9mIHRoZSBhZGRyZXNzIGJlaW5nIHN3ZXB0XG4gICAqL1xuICBhc3luYyByZWNvdmVyKHBhcmFtczogU29sUmVjb3ZlcnlPcHRpb25zKTogUHJvbWlzZTxNUENUeCB8IE1QQ1N3ZWVwVHhzPiB7XG4gICAgaWYgKCFwYXJhbXMuYml0Z29LZXkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignbWlzc2luZyBiaXRnb0tleScpO1xuICAgIH1cblxuICAgIGlmICghcGFyYW1zLnJlY292ZXJ5RGVzdGluYXRpb24gfHwgIXRoaXMuaXNWYWxpZEFkZHJlc3MocGFyYW1zLnJlY292ZXJ5RGVzdGluYXRpb24pKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2ludmFsaWQgcmVjb3ZlcnlEZXN0aW5hdGlvbicpO1xuICAgIH1cblxuICAgIGNvbnN0IGJpdGdvS2V5ID0gcGFyYW1zLmJpdGdvS2V5LnJlcGxhY2UoL1xccy9nLCAnJyk7XG4gICAgY29uc3QgaXNVbnNpZ25lZFN3ZWVwID0gIXBhcmFtcy51c2VyS2V5ICYmICFwYXJhbXMuYmFja3VwS2V5ICYmICFwYXJhbXMud2FsbGV0UGFzc3BocmFzZTtcblxuICAgIC8vIEJ1aWxkIHRoZSB0cmFuc2FjdGlvblxuICAgIGNvbnN0IE1QQyA9IGF3YWl0IEVERFNBTWV0aG9kcy5nZXRJbml0aWFsaXplZE1wY0luc3RhbmNlKCk7XG4gICAgbGV0IGJhbGFuY2UgPSAwO1xuXG4gICAgY29uc3QgaW5kZXggPSBwYXJhbXMuaW5kZXggfHwgMDtcbiAgICBjb25zdCBjdXJyUGF0aCA9IHBhcmFtcy5zZWVkID8gZ2V0RGVyaXZhdGlvblBhdGgocGFyYW1zLnNlZWQpICsgYC8ke2luZGV4fWAgOiBgbS8ke2luZGV4fWA7XG4gICAgY29uc3QgYWNjb3VudElkID0gTVBDLmRlcml2ZVVuaGFyZGVuZWQoYml0Z29LZXksIGN1cnJQYXRoKS5zbGljZSgwLCA2NCk7XG4gICAgY29uc3QgYnM1OEVuY29kZWRQdWJsaWNLZXkgPSBuZXcgU29sS2V5UGFpcih7IHB1YjogYWNjb3VudElkIH0pLmdldEFkZHJlc3MoKTtcblxuICAgIGJhbGFuY2UgPSBhd2FpdCB0aGlzLmdldEFjY291bnRCYWxhbmNlKGJzNThFbmNvZGVkUHVibGljS2V5LCBwYXJhbXMuYXBpS2V5KTtcblxuICAgIGNvbnN0IGZhY3RvcnkgPSB0aGlzLmdldEJ1aWxkZXIoKTtcbiAgICBjb25zdCB3YWxsZXRDb2luID0gdGhpcy5nZXRDaGFpbigpO1xuXG4gICAgbGV0IHR4QnVpbGRlcjtcbiAgICBsZXQgYmxvY2toYXNoID0gYXdhaXQgdGhpcy5nZXRCbG9ja2hhc2gocGFyYW1zLmFwaUtleSk7XG4gICAgbGV0IHJlbnRFeGVtcHRBbW91bnQ7XG4gICAgbGV0IGF1dGhvcml0eSA9ICcnO1xuICAgIGxldCB0b3RhbEZlZSA9IG5ldyBCaWdOdW1iZXIoMCk7XG4gICAgbGV0IHRvdGFsRmVlRm9yVG9rZW5SZWNvdmVyeSA9IG5ldyBCaWdOdW1iZXIoMCk7XG5cbiAgICAvLyBjaGVjayBmb3IgcG9zc2libGUgdG9rZW4gcmVjb3ZlcnksIHJlY292ZXIgdGhlIHRva2VuIHByb3ZpZGUgYnkgdXNlclxuICAgIGlmIChwYXJhbXMudG9rZW5Db250cmFjdEFkZHJlc3MpIHtcbiAgICAgIGxldCBpc1Vuc3VwcG9ydGVkVG9rZW4gPSBmYWxzZTtcbiAgICAgIGNvbnN0IHRva2VuQWNjb3VudHMgPSBhd2FpdCB0aGlzLmdldFRva2VuQWNjb3VudHNCeU93bmVyKGJzNThFbmNvZGVkUHVibGljS2V5LCBwYXJhbXMucHJvZ3JhbUlkLCBwYXJhbXMuYXBpS2V5KTtcbiAgICAgIGlmICh0b2tlbkFjY291bnRzLmxlbmd0aCAhPT0gMCkge1xuICAgICAgICAvLyB0aGVyZSBleGlzdHMgdG9rZW4gYWNjb3VudHMgb24gdGhlIGdpdmVuIGFkZHJlc3MsIGJ1dCBuZWVkIHRvIGNoZWNrIGNlcnRhaW4gY29uZGl0aW9uczpcbiAgICAgICAgLy8gMS4gaWYgdGhlcmUgaXMgYSByZWNvdmVyYWJsZSBiYWxhbmNlXG4gICAgICAgIC8vIDIuIGlmIHRoZSB0b2tlbiBpcyBzdXBwb3J0ZWQgYnkgYml0Z29cbiAgICAgICAgY29uc3QgcmVjb3ZlcmVhYmxlVG9rZW5BY2NvdW50czogVG9rZW5BY2NvdW50W10gPSBbXTtcbiAgICAgICAgZm9yIChjb25zdCB0b2tlbkFjY291bnQgb2YgdG9rZW5BY2NvdW50cykge1xuICAgICAgICAgIGlmIChwYXJhbXMudG9rZW5Db250cmFjdEFkZHJlc3MgPT09IHRva2VuQWNjb3VudC5pbmZvLm1pbnQpIHtcbiAgICAgICAgICAgIGNvbnN0IHRva2VuQW1vdW50ID0gbmV3IEJpZ051bWJlcih0b2tlbkFjY291bnQuaW5mby50b2tlbkFtb3VudC5hbW91bnQpO1xuICAgICAgICAgICAgY29uc3QgbmV0d29yayA9IHRoaXMuZ2V0TmV0d29yaygpO1xuICAgICAgICAgICAgY29uc3QgdG9rZW4gPSBnZXRTb2xUb2tlbkZyb21BZGRyZXNzKHRva2VuQWNjb3VudC5pbmZvLm1pbnQsIG5ldHdvcmspOyAvLyB0b2RvKFdJTi01ODk0KSBmaXggZm9yIGFtc1xuXG4gICAgICAgICAgICBpZiAoIXRva2VuKSB7XG4gICAgICAgICAgICAgIGlzVW5zdXBwb3J0ZWRUb2tlbiA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodG9rZW5BbW91bnQuZ3QobmV3IEJpZ051bWJlcigwKSkpIHtcbiAgICAgICAgICAgICAgdG9rZW5BY2NvdW50LnRva2VuTmFtZSA9IHRva2VuPy5uYW1lIHx8ICdVbnN1cHBvcnRlZCBUb2tlbic7XG4gICAgICAgICAgICAgIHJlY292ZXJlYWJsZVRva2VuQWNjb3VudHMucHVzaCh0b2tlbkFjY291bnQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHJlY292ZXJlYWJsZVRva2VuQWNjb3VudHMubGVuZ3RoICE9PSAwKSB7XG4gICAgICAgICAgcmVudEV4ZW1wdEFtb3VudCA9IGF3YWl0IHRoaXMuZ2V0UmVudEV4ZW1wdEFtb3VudChwYXJhbXMuYXBpS2V5KTtcblxuICAgICAgICAgIHR4QnVpbGRlciA9IGZhY3RvcnlcbiAgICAgICAgICAgIC5nZXRUb2tlblRyYW5zZmVyQnVpbGRlcigpXG4gICAgICAgICAgICAubm9uY2UoYmxvY2toYXNoKVxuICAgICAgICAgICAgLnNlbmRlcihiczU4RW5jb2RlZFB1YmxpY0tleSlcbiAgICAgICAgICAgIC5hc3NvY2lhdGVkVG9rZW5BY2NvdW50UmVudChyZW50RXhlbXB0QW1vdW50LnRvU3RyaW5nKCkpXG4gICAgICAgICAgICAuZmVlUGF5ZXIoYnM1OEVuY29kZWRQdWJsaWNLZXkpO1xuXG4gICAgICAgICAgLy8gbmVlZCB0byBnZXQgYWxsIHRva2VuIGFjY291bnRzIG9mIHRoZSByZWNpcGllbnQgYWRkcmVzcyBhbmQgbmVlZCB0byBjcmVhdGUgdGhlbSBpZiB0aGV5IGRvIG5vdCBleGlzdFxuICAgICAgICAgIGNvbnN0IHJlY2lwaWVudFRva2VuQWNjb3VudHMgPSBhd2FpdCB0aGlzLmdldFRva2VuQWNjb3VudHNCeU93bmVyKFxuICAgICAgICAgICAgcGFyYW1zLnJlY292ZXJ5RGVzdGluYXRpb24sXG4gICAgICAgICAgICBwYXJhbXMucHJvZ3JhbUlkLFxuICAgICAgICAgICAgcGFyYW1zLmFwaUtleVxuICAgICAgICAgICk7XG5cbiAgICAgICAgICBmb3IgKGNvbnN0IHRva2VuQWNjb3VudCBvZiByZWNvdmVyZWFibGVUb2tlbkFjY291bnRzKSB7XG4gICAgICAgICAgICBsZXQgcmVjaXBpZW50VG9rZW5BY2NvdW50RXhpc3RzID0gZmFsc2U7XG4gICAgICAgICAgICBmb3IgKGNvbnN0IHJlY2lwaWVudFRva2VuQWNjb3VudCBvZiByZWNpcGllbnRUb2tlbkFjY291bnRzIGFzIFRva2VuQWNjb3VudFtdKSB7XG4gICAgICAgICAgICAgIGlmIChyZWNpcGllbnRUb2tlbkFjY291bnQuaW5mby5taW50ID09PSB0b2tlbkFjY291bnQuaW5mby5taW50KSB7XG4gICAgICAgICAgICAgICAgcmVjaXBpZW50VG9rZW5BY2NvdW50RXhpc3RzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBjb25zdCByZWNpcGllbnRUb2tlbkFjY291bnQgPSBhd2FpdCBnZXRBc3NvY2lhdGVkVG9rZW5BY2NvdW50QWRkcmVzcyhcbiAgICAgICAgICAgICAgdG9rZW5BY2NvdW50LmluZm8ubWludCxcbiAgICAgICAgICAgICAgcGFyYW1zLnJlY292ZXJ5RGVzdGluYXRpb24sXG4gICAgICAgICAgICAgIGZhbHNlLFxuICAgICAgICAgICAgICBwYXJhbXMucHJvZ3JhbUlkPy50b1N0cmluZygpXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgY29uc3QgdG9rZW5OYW1lID0gdG9rZW5BY2NvdW50LnRva2VuTmFtZSBhcyBzdHJpbmc7XG4gICAgICAgICAgICBjb25zdCBzZW5kUGFyYW1zID0ge1xuICAgICAgICAgICAgICBhZGRyZXNzOiByZWNpcGllbnRUb2tlbkFjY291bnQsXG4gICAgICAgICAgICAgIGFtb3VudDogdG9rZW5BY2NvdW50LmluZm8udG9rZW5BbW91bnQuYW1vdW50LFxuICAgICAgICAgICAgICB0b2tlbk5hbWUsXG4gICAgICAgICAgICAgIC4uLihpc1Vuc3VwcG9ydGVkVG9rZW5cbiAgICAgICAgICAgICAgICA/IHtcbiAgICAgICAgICAgICAgICAgICAgdG9rZW5BZGRyZXNzOiB0b2tlbkFjY291bnQuaW5mby5taW50LFxuICAgICAgICAgICAgICAgICAgICBwcm9ncmFtSWQ6IHBhcmFtcy5wcm9ncmFtSWQ/LnRvU3RyaW5nKCksXG4gICAgICAgICAgICAgICAgICAgIGRlY2ltYWxQbGFjZXM6IHRva2VuQWNjb3VudC5pbmZvLnRva2VuQW1vdW50LmRlY2ltYWxzLFxuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIDoge30pLFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHR4QnVpbGRlci5zZW5kKHNlbmRQYXJhbXMpO1xuXG4gICAgICAgICAgICBpZiAoIXJlY2lwaWVudFRva2VuQWNjb3VudEV4aXN0cykge1xuICAgICAgICAgICAgICAvLyByZWNpcGllbnQgdG9rZW4gYWNjb3VudCBkb2VzIG5vdCBleGlzdCBmb3IgdG9rZW4gYW5kIG11c3QgYmUgY3JlYXRlZFxuICAgICAgICAgICAgICB0eEJ1aWxkZXIuY3JlYXRlQXNzb2NpYXRlZFRva2VuQWNjb3VudCh7XG4gICAgICAgICAgICAgICAgb3duZXJBZGRyZXNzOiBwYXJhbXMucmVjb3ZlcnlEZXN0aW5hdGlvbixcbiAgICAgICAgICAgICAgICB0b2tlbk5hbWU6IHRva2VuTmFtZSxcbiAgICAgICAgICAgICAgICAuLi4oaXNVbnN1cHBvcnRlZFRva2VuID8geyB0b2tlbkFkZHJlc3M6IHRva2VuQWNjb3VudC5pbmZvLm1pbnQgfSA6IHt9KSxcbiAgICAgICAgICAgICAgICBwcm9ncmFtSWQ6XG4gICAgICAgICAgICAgICAgICBwYXJhbXMucHJvZ3JhbUlkPy50b1N0cmluZygpLnRvTG93ZXJDYXNlKCkgPT09IFRPS0VOXzIwMjJfUFJPR1JBTV9JRC50b1N0cmluZygpLnRvTG93ZXJDYXNlKClcbiAgICAgICAgICAgICAgICAgICAgPyBUT0tFTl8yMDIyX1BST0dSQU1fSUQudG9TdHJpbmcoKVxuICAgICAgICAgICAgICAgICAgICA6IFRPS0VOX1BST0dSQU1fSUQudG9TdHJpbmcoKSxcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgIC8vIGFkZCByZW50IGV4ZW1wdCBhbW91bnQgdG8gdG90YWwgZmVlIGZvciBlYWNoIHRva2VuIGFjY291bnQgdGhhdCBoYXMgdG8gYmUgY3JlYXRlZFxuICAgICAgICAgICAgICB0b3RhbEZlZUZvclRva2VuUmVjb3ZlcnkgPSB0b3RhbEZlZUZvclRva2VuUmVjb3ZlcnkucGx1cyhyZW50RXhlbXB0QW1vdW50KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhyb3cgRXJyb3IoJ05vdCBlbm91Z2ggdG9rZW4gZnVuZHMgdG8gcmVjb3ZlcicpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyB0aGVyZSBhcmUgbm8gcmVjb3ZlcmFibGUgdG9rZW4gYWNjb3VudHMgLCBuZWVkIHRvIGNoZWNrIGlmIHRoZXJlIGFyZSB0b2tlbnMgdG8gcmVjb3ZlclxuICAgICAgICB0aHJvdyBFcnJvcignRGlkIG5vdCBmaW5kIHRva2VuIGFjY291bnQgdG8gcmVjb3ZlciB0b2tlbnMsIHBsZWFzZSBjaGVjayB0b2tlbiBhY2NvdW50Jyk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHR4QnVpbGRlciA9IGZhY3RvcnlcbiAgICAgICAgLmdldFRyYW5zZmVyQnVpbGRlcigpXG4gICAgICAgIC5ub25jZShibG9ja2hhc2gpXG4gICAgICAgIC5zZW5kZXIoYnM1OEVuY29kZWRQdWJsaWNLZXkpXG4gICAgICAgIC5zZW5kKHsgYWRkcmVzczogcGFyYW1zLnJlY292ZXJ5RGVzdGluYXRpb24sIGFtb3VudDogYmFsYW5jZS50b1N0cmluZygpIH0pXG4gICAgICAgIC5mZWVQYXllcihiczU4RW5jb2RlZFB1YmxpY0tleSk7XG4gICAgfVxuXG4gICAgaWYgKHBhcmFtcy5kdXJhYmxlTm9uY2UpIHtcbiAgICAgIGNvbnN0IGR1cmFibGVOb25jZUluZm8gPSBhd2FpdCB0aGlzLmdldEFjY291bnRJbmZvKHBhcmFtcy5kdXJhYmxlTm9uY2UucHVibGljS2V5LCBwYXJhbXMuYXBpS2V5KTtcbiAgICAgIGJsb2NraGFzaCA9IGR1cmFibGVOb25jZUluZm8uYmxvY2toYXNoO1xuICAgICAgYXV0aG9yaXR5ID0gZHVyYWJsZU5vbmNlSW5mby5hdXRob3JpdHk7XG5cbiAgICAgIHR4QnVpbGRlci5ub25jZShibG9ja2hhc2gsIHtcbiAgICAgICAgd2FsbGV0Tm9uY2VBZGRyZXNzOiBwYXJhbXMuZHVyYWJsZU5vbmNlLnB1YmxpY0tleSxcbiAgICAgICAgYXV0aFdhbGxldEFkZHJlc3M6IGF1dGhvcml0eSxcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8vIGJ1aWxkIHRoZSB0cmFuc2FjdGlvbiB3aXRob3V0IGZlZVxuICAgIGNvbnN0IHVuc2lnbmVkVHJhbnNhY3Rpb25XaXRob3V0RmVlID0gKGF3YWl0IHR4QnVpbGRlci5idWlsZCgpKSBhcyBUcmFuc2FjdGlvbjtcbiAgICBjb25zdCBzZXJpYWxpemVkTWVzc2FnZSA9IHVuc2lnbmVkVHJhbnNhY3Rpb25XaXRob3V0RmVlLnNvbFRyYW5zYWN0aW9uLnNlcmlhbGl6ZU1lc3NhZ2UoKS50b1N0cmluZygnYmFzZTY0Jyk7XG5cbiAgICBjb25zdCBiYXNlRmVlID0gYXdhaXQgdGhpcy5nZXRGZWVGb3JNZXNzYWdlKHNlcmlhbGl6ZWRNZXNzYWdlLCBwYXJhbXMuYXBpS2V5KTtcbiAgICBjb25zdCBmZWVQZXJTaWduYXR1cmUgPSBwYXJhbXMuZHVyYWJsZU5vbmNlID8gYmFzZUZlZSAvIDIgOiBiYXNlRmVlO1xuICAgIHRvdGFsRmVlID0gdG90YWxGZWUucGx1cyhuZXcgQmlnTnVtYmVyKGJhc2VGZWUpKTtcbiAgICB0b3RhbEZlZUZvclRva2VuUmVjb3ZlcnkgPSB0b3RhbEZlZUZvclRva2VuUmVjb3ZlcnkucGx1cyhuZXcgQmlnTnVtYmVyKGJhc2VGZWUpKTtcbiAgICBpZiAodG90YWxGZWUuZ3QoYmFsYW5jZSkpIHtcbiAgICAgIHRocm93IEVycm9yKCdEaWQgbm90IGZpbmQgYWRkcmVzcyB3aXRoIGZ1bmRzIHRvIHJlY292ZXInKTtcbiAgICB9XG5cbiAgICBpZiAocGFyYW1zLnRva2VuQ29udHJhY3RBZGRyZXNzKSB7XG4gICAgICAvLyBDaGVjayBpZiB0aGVyZSBpcyBzdWZmaWNpZW50IG5hdGl2ZSBzb2xhbmEgdG8gcmVjb3ZlciB0b2tlbnNcbiAgICAgIGlmIChuZXcgQmlnTnVtYmVyKGJhbGFuY2UpLmx0KHRvdGFsRmVlRm9yVG9rZW5SZWNvdmVyeSkpIHtcbiAgICAgICAgdGhyb3cgRXJyb3IoXG4gICAgICAgICAgJ05vdCBlbm91Z2ggZnVuZHMgdG8gcGF5IGZvciByZWNvdmVyIHRva2VucyBmZWVzLCBoYXZlOiAnICtcbiAgICAgICAgICAgIGJhbGFuY2UgK1xuICAgICAgICAgICAgJyBuZWVkOiAnICtcbiAgICAgICAgICAgIHRvdGFsRmVlRm9yVG9rZW5SZWNvdmVyeS50b1N0cmluZygpXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICB0eEJ1aWxkZXIuZmVlKHsgYW1vdW50OiBmZWVQZXJTaWduYXR1cmUgfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IG5ldEFtb3VudCA9IG5ldyBCaWdOdW1iZXIoYmFsYW5jZSkubWludXModG90YWxGZWUpO1xuICAgICAgdHhCdWlsZGVyID0gZmFjdG9yeVxuICAgICAgICAuZ2V0VHJhbnNmZXJCdWlsZGVyKClcbiAgICAgICAgLm5vbmNlKGJsb2NraGFzaClcbiAgICAgICAgLnNlbmRlcihiczU4RW5jb2RlZFB1YmxpY0tleSlcbiAgICAgICAgLnNlbmQoeyBhZGRyZXNzOiBwYXJhbXMucmVjb3ZlcnlEZXN0aW5hdGlvbiwgYW1vdW50OiBuZXRBbW91bnQudG9TdHJpbmcoKSB9KVxuICAgICAgICAuZmVlUGF5ZXIoYnM1OEVuY29kZWRQdWJsaWNLZXkpXG4gICAgICAgIC5mZWUoeyBhbW91bnQ6IGZlZVBlclNpZ25hdHVyZSB9KTtcblxuICAgICAgaWYgKHBhcmFtcy5kdXJhYmxlTm9uY2UpIHtcbiAgICAgICAgdHhCdWlsZGVyLm5vbmNlKGJsb2NraGFzaCwge1xuICAgICAgICAgIHdhbGxldE5vbmNlQWRkcmVzczogcGFyYW1zLmR1cmFibGVOb25jZS5wdWJsaWNLZXksXG4gICAgICAgICAgYXV0aFdhbGxldEFkZHJlc3M6IGF1dGhvcml0eSxcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKCFpc1Vuc2lnbmVkU3dlZXApIHtcbiAgICAgIC8vIFNpZ24gdGhlIHR4blxuICAgICAgaWYgKCFwYXJhbXMudXNlcktleSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ21pc3NpbmcgdXNlcktleScpO1xuICAgICAgfVxuXG4gICAgICBpZiAoIXBhcmFtcy5iYWNrdXBLZXkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdtaXNzaW5nIGJhY2t1cEtleScpO1xuICAgICAgfVxuXG4gICAgICBpZiAoIXBhcmFtcy53YWxsZXRQYXNzcGhyYXNlKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignbWlzc2luZyB3YWxsZXQgcGFzc3BocmFzZScpO1xuICAgICAgfVxuXG4gICAgICAvLyBidWlsZCB0aGUgdHJhbnNhY3Rpb24gd2l0aCBmZWVcbiAgICAgIGNvbnN0IHVuc2lnbmVkVHJhbnNhY3Rpb24gPSAoYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCkpIGFzIFRyYW5zYWN0aW9uO1xuXG4gICAgICBjb25zdCB1c2VyS2V5ID0gcGFyYW1zLnVzZXJLZXkucmVwbGFjZSgvXFxzL2csICcnKTtcbiAgICAgIGNvbnN0IGJhY2t1cEtleSA9IHBhcmFtcy5iYWNrdXBLZXkucmVwbGFjZSgvXFxzL2csICcnKTtcblxuICAgICAgLy8gRGVjcnlwdCBwcml2YXRlIGtleXMgZnJvbSBLZXlDYXJkIHZhbHVlc1xuICAgICAgbGV0IHVzZXJQcnY7XG5cbiAgICAgIHRyeSB7XG4gICAgICAgIHVzZXJQcnYgPSB0aGlzLmJpdGdvLmRlY3J5cHQoe1xuICAgICAgICAgIGlucHV0OiB1c2VyS2V5LFxuICAgICAgICAgIHBhc3N3b3JkOiBwYXJhbXMud2FsbGV0UGFzc3BocmFzZSxcbiAgICAgICAgfSk7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgRXJyb3IgZGVjcnlwdGluZyB1c2VyIGtleWNoYWluOiAke2UubWVzc2FnZX1gKTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgdXNlclNpZ25pbmdNYXRlcmlhbCA9IEpTT04ucGFyc2UodXNlclBydikgYXMgRUREU0FNZXRob2RUeXBlcy5Vc2VyU2lnbmluZ01hdGVyaWFsO1xuXG4gICAgICBsZXQgYmFja3VwUHJ2O1xuICAgICAgdHJ5IHtcbiAgICAgICAgYmFja3VwUHJ2ID0gdGhpcy5iaXRnby5kZWNyeXB0KHtcbiAgICAgICAgICBpbnB1dDogYmFja3VwS2V5LFxuICAgICAgICAgIHBhc3N3b3JkOiBwYXJhbXMud2FsbGV0UGFzc3BocmFzZSxcbiAgICAgICAgfSk7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgRXJyb3IgZGVjcnlwdGluZyBiYWNrdXAga2V5Y2hhaW46ICR7ZS5tZXNzYWdlfWApO1xuICAgICAgfVxuICAgICAgY29uc3QgYmFja3VwU2lnbmluZ01hdGVyaWFsID0gSlNPTi5wYXJzZShiYWNrdXBQcnYpIGFzIEVERFNBTWV0aG9kVHlwZXMuQmFja3VwU2lnbmluZ01hdGVyaWFsO1xuXG4gICAgICBjb25zdCBzaWduYXR1cmVIZXggPSBhd2FpdCBFRERTQU1ldGhvZHMuZ2V0VFNTU2lnbmF0dXJlKFxuICAgICAgICB1c2VyU2lnbmluZ01hdGVyaWFsLFxuICAgICAgICBiYWNrdXBTaWduaW5nTWF0ZXJpYWwsXG4gICAgICAgIGN1cnJQYXRoLFxuICAgICAgICB1bnNpZ25lZFRyYW5zYWN0aW9uXG4gICAgICApO1xuXG4gICAgICBjb25zdCBwdWJsaWNLZXlPYmogPSB7IHB1YjogYnM1OEVuY29kZWRQdWJsaWNLZXkgfTtcbiAgICAgIHR4QnVpbGRlci5hZGRTaWduYXR1cmUocHVibGljS2V5T2JqIGFzIFB1YmxpY0tleSwgc2lnbmF0dXJlSGV4KTtcbiAgICB9XG5cbiAgICBpZiAocGFyYW1zLmR1cmFibGVOb25jZSkge1xuICAgICAgLy8gYWRkIGR1cmFibGUgbm9uY2UgYWNjb3VudCBzaWduYXR1cmVcbiAgICAgIHR4QnVpbGRlci5zaWduKHsga2V5OiBwYXJhbXMuZHVyYWJsZU5vbmNlLnNlY3JldEtleSB9KTtcbiAgICB9XG5cbiAgICBjb25zdCBjb21wbGV0ZWRUcmFuc2FjdGlvbiA9IGF3YWl0IHR4QnVpbGRlci5idWlsZCgpO1xuICAgIGNvbnN0IHNlcmlhbGl6ZWRUeCA9IGNvbXBsZXRlZFRyYW5zYWN0aW9uLnRvQnJvYWRjYXN0Rm9ybWF0KCk7XG4gICAgY29uc3QgZGVyaXZhdGlvblBhdGggPSBwYXJhbXMuc2VlZCA/IGdldERlcml2YXRpb25QYXRoKHBhcmFtcy5zZWVkKSArIGAvJHtpbmRleH1gIDogYG0vJHtpbmRleH1gO1xuICAgIGNvbnN0IGlucHV0czogT3ZjSW5wdXRbXSA9IFtdO1xuICAgIGZvciAoY29uc3QgaW5wdXQgb2YgY29tcGxldGVkVHJhbnNhY3Rpb24uaW5wdXRzKSB7XG4gICAgICBpbnB1dHMucHVzaCh7XG4gICAgICAgIGFkZHJlc3M6IGlucHV0LmFkZHJlc3MsXG4gICAgICAgIHZhbHVlU3RyaW5nOiBpbnB1dC52YWx1ZSxcbiAgICAgICAgdmFsdWU6IG5ldyBCaWdOdW1iZXIoaW5wdXQudmFsdWUpLnRvTnVtYmVyKCksXG4gICAgICB9KTtcbiAgICB9XG4gICAgY29uc3Qgb3V0cHV0czogT3ZjT3V0cHV0W10gPSBbXTtcbiAgICBmb3IgKGNvbnN0IG91dHB1dCBvZiBjb21wbGV0ZWRUcmFuc2FjdGlvbi5vdXRwdXRzKSB7XG4gICAgICBvdXRwdXRzLnB1c2goe1xuICAgICAgICBhZGRyZXNzOiBvdXRwdXQuYWRkcmVzcyxcbiAgICAgICAgdmFsdWVTdHJpbmc6IG91dHB1dC52YWx1ZSxcbiAgICAgICAgY29pbk5hbWU6IG91dHB1dC5jb2luID8gb3V0cHV0LmNvaW4gOiB3YWxsZXRDb2luLFxuICAgICAgfSk7XG4gICAgfVxuICAgIGNvbnN0IHNwZW5kQW1vdW50ID0gY29tcGxldGVkVHJhbnNhY3Rpb24uaW5wdXRzLmxlbmd0aCA9PT0gMSA/IGNvbXBsZXRlZFRyYW5zYWN0aW9uLmlucHV0c1swXS52YWx1ZSA6IDA7XG4gICAgY29uc3QgcGFyc2VkVHggPSB7IGlucHV0czogaW5wdXRzLCBvdXRwdXRzOiBvdXRwdXRzLCBzcGVuZEFtb3VudDogc3BlbmRBbW91bnQsIHR5cGU6ICcnIH07XG4gICAgY29uc3QgZmVlSW5mbyA9IHsgZmVlOiB0b3RhbEZlZUZvclRva2VuUmVjb3ZlcnkudG9OdW1iZXIoKSwgZmVlU3RyaW5nOiB0b3RhbEZlZS50b1N0cmluZygpIH07XG4gICAgY29uc3QgY29pblNwZWNpZmljID0geyBjb21tb25LZXljaGFpbjogYml0Z29LZXkgfTtcbiAgICBpZiAoaXNVbnNpZ25lZFN3ZWVwKSB7XG4gICAgICBjb25zdCB0cmFuc2FjdGlvbjogTVBDVHggPSB7XG4gICAgICAgIHNlcmlhbGl6ZWRUeDogc2VyaWFsaXplZFR4LFxuICAgICAgICBzY2FuSW5kZXg6IGluZGV4LFxuICAgICAgICBjb2luOiB3YWxsZXRDb2luLFxuICAgICAgICBzaWduYWJsZUhleDogY29tcGxldGVkVHJhbnNhY3Rpb24uc2lnbmFibGVQYXlsb2FkLnRvU3RyaW5nKCdoZXgnKSxcbiAgICAgICAgZGVyaXZhdGlvblBhdGg6IGRlcml2YXRpb25QYXRoLFxuICAgICAgICBwYXJzZWRUeDogcGFyc2VkVHgsXG4gICAgICAgIGZlZUluZm86IGZlZUluZm8sXG4gICAgICAgIGNvaW5TcGVjaWZpYzogY29pblNwZWNpZmljLFxuICAgICAgfTtcbiAgICAgIGNvbnN0IHVuc2lnbmVkVHg6IE1QQ1Vuc2lnbmVkVHggPSB7IHVuc2lnbmVkVHg6IHRyYW5zYWN0aW9uLCBzaWduYXR1cmVTaGFyZXM6IFtdIH07XG4gICAgICBjb25zdCB0cmFuc2FjdGlvbnM6IE1QQ1Vuc2lnbmVkVHhbXSA9IFt1bnNpZ25lZFR4XTtcbiAgICAgIGNvbnN0IHR4UmVxdWVzdDogUmVjb3ZlcnlUeFJlcXVlc3QgPSB7XG4gICAgICAgIHRyYW5zYWN0aW9uczogdHJhbnNhY3Rpb25zLFxuICAgICAgICB3YWxsZXRDb2luOiB3YWxsZXRDb2luLFxuICAgICAgfTtcbiAgICAgIGNvbnN0IHR4UmVxdWVzdHM6IE1QQ1N3ZWVwVHhzID0geyB0eFJlcXVlc3RzOiBbdHhSZXF1ZXN0XSB9O1xuICAgICAgcmV0dXJuIHR4UmVxdWVzdHM7XG4gICAgfVxuICAgIGNvbnN0IHRyYW5zYWN0aW9uOiBNUENUeCA9IHtcbiAgICAgIHNlcmlhbGl6ZWRUeDogc2VyaWFsaXplZFR4LFxuICAgICAgc2NhbkluZGV4OiBpbmRleCxcbiAgICB9O1xuICAgIHJldHVybiB0cmFuc2FjdGlvbjtcbiAgfVxuXG4gIC8qKlxuICAgKiBCdWlsZHMgYSBmdW5kcyByZWNvdmVyeSB0cmFuc2FjdGlvbiB3aXRob3V0IEJpdEdvXG4gICAqIEBwYXJhbSB7U29sUmVjb3ZlcnlPcHRpb25zfSBwYXJhbXMgcGFyYW1ldGVycyBuZWVkZWQgdG8gY29uc3RydWN0IGFuZFxuICAgKiAobWF5YmUpIHNpZ24gdGhlIHRyYW5zYWN0aW9uXG4gICAqXG4gICAqIEByZXR1cm5zIHtCYXNlQnJvYWRjYXN0VHJhbnNhY3Rpb25SZXN1bHRbXX0gdGhlIHNlcmlhbGl6ZWQgdHJhbnNhY3Rpb24gaGV4IHN0cmluZyBhbmQgaW5kZXhcbiAgICogb2YgdGhlIGFkZHJlc3MgYmVpbmcgc3dlcHRcbiAgICovXG4gIGFzeW5jIHJlY292ZXJDbG9zZUFUQShwYXJhbXM6IFNvbFJlY292ZXJ5T3B0aW9ucyk6IFByb21pc2U8QmFzZUJyb2FkY2FzdFRyYW5zYWN0aW9uUmVzdWx0W10+IHtcbiAgICBpZiAoIXBhcmFtcy5iaXRnb0tleSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdtaXNzaW5nIGJpdGdvS2V5Jyk7XG4gICAgfVxuXG4gICAgaWYgKCFwYXJhbXMucmVjb3ZlcnlEZXN0aW5hdGlvbiB8fCAhdGhpcy5pc1ZhbGlkQWRkcmVzcyhwYXJhbXMucmVjb3ZlcnlEZXN0aW5hdGlvbikpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignaW52YWxpZCByZWNvdmVyeURlc3RpbmF0aW9uJyk7XG4gICAgfVxuXG4gICAgaWYgKCFwYXJhbXMuY2xvc2VBdGFBZGRyZXNzIHx8ICF0aGlzLmlzVmFsaWRBZGRyZXNzKHBhcmFtcy5jbG9zZUF0YUFkZHJlc3MpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2ludmFsaWQgY2xvc2VBdGFBZGRyZXNzJyk7XG4gICAgfVxuXG4gICAgY29uc3QgYml0Z29LZXkgPSBwYXJhbXMuYml0Z29LZXkucmVwbGFjZSgvXFxzL2csICcnKTtcblxuICAgIC8vIEJ1aWxkIHRoZSB0cmFuc2FjdGlvblxuICAgIGNvbnN0IE1QQyA9IGF3YWl0IEVERFNBTWV0aG9kcy5nZXRJbml0aWFsaXplZE1wY0luc3RhbmNlKCk7XG4gICAgbGV0IGJhbGFuY2UgPSAwO1xuXG4gICAgY29uc3QgaW5kZXggPSBwYXJhbXMuaW5kZXggfHwgMDtcbiAgICBjb25zdCBjdXJyUGF0aCA9IHBhcmFtcy5zZWVkID8gZ2V0RGVyaXZhdGlvblBhdGgocGFyYW1zLnNlZWQpICsgYC8ke2luZGV4fWAgOiBgbS8ke2luZGV4fWA7XG4gICAgY29uc3QgYWNjb3VudElkID0gTVBDLmRlcml2ZVVuaGFyZGVuZWQoYml0Z29LZXksIGN1cnJQYXRoKS5zbGljZSgwLCA2NCk7XG4gICAgY29uc3QgYnM1OEVuY29kZWRQdWJsaWNLZXkgPSBuZXcgU29sS2V5UGFpcih7IHB1YjogYWNjb3VudElkIH0pLmdldEFkZHJlc3MoKTtcblxuICAgIGNvbnN0IGFjY291bnRCYWxhbmNlID0gYXdhaXQgdGhpcy5nZXRBY2NvdW50QmFsYW5jZShiczU4RW5jb2RlZFB1YmxpY0tleSk7XG5cbiAgICBiYWxhbmNlID0gYXdhaXQgdGhpcy5nZXRBY2NvdW50QmFsYW5jZShwYXJhbXMuY2xvc2VBdGFBZGRyZXNzKTtcbiAgICBpZiAoYmFsYW5jZSA8PSAwKSB7XG4gICAgICB0aHJvdyBFcnJvcignRGlkIG5vdCBmaW5kIGNsb3NlQXRhQWRkcmVzcyB3aXRoIHNvbCBmdW5kcyB0byByZWNvdmVyJyk7XG4gICAgfVxuXG4gICAgY29uc3QgZmFjdG9yeSA9IHRoaXMuZ2V0QnVpbGRlcigpO1xuXG4gICAgbGV0IHR4QnVpbGRlcjtcbiAgICBsZXQgYmxvY2toYXNoO1xuICAgIGNvbnN0IHJlY292ZXJ0VHhuczogQmFzZUJyb2FkY2FzdFRyYW5zYWN0aW9uUmVzdWx0W10gPSBbXTtcblxuICAgIGNvbnN0IHJlbnRFeGVtcHRBbW91bnQgPSBhd2FpdCB0aGlzLmdldFJlbnRFeGVtcHRBbW91bnQoKTtcblxuICAgIC8vIGRvIHRva2VuIHJlY292ZXJ5IGJlZm9yZSBjbG9zaW5nIEFUQSBhZGRyZXNzXG4gICAgLy8gY2hlY2sgaWYgYW55IHRva2VuIGlzIHByZXNlbnQgb24gdGhlIGNsb3NlQXRhQWRkcmVzc1xuICAgIGNvbnN0IHRva2VuSW5mbyA9IGF3YWl0IHRoaXMuZ2V0VG9rZW5BY2NvdW50SW5mbyhwYXJhbXMuY2xvc2VBdGFBZGRyZXNzKTtcbiAgICBjb25zdCB0b2tlbkJhbGFuY2UgPSBOdW1iZXIodG9rZW5JbmZvLmluZm8udG9rZW5BbW91bnQuYW1vdW50KTtcblxuICAgIGlmICh0b2tlbkJhbGFuY2UgPiAwKSB7XG4gICAgICAvLyBjbG9zZUFUQSBhZGRyZXNzIGhhcyBzb21lIHRva2VuIGJhbGFuY2UsIGl0IG5lZWRzIHRvIGJlIHdpdGhkcmF3biBiZWZvcmUgY2xvc2luZyBBVEFcbiAgICAgIGNvbnNvbGUubG9nKFxuICAgICAgICBgY2xvc2VBVEEgYWRkcmVzcyAke3BhcmFtcy5jbG9zZUF0YUFkZHJlc3N9IGhhcyB0b2tlbiBiYWxhbmNlICR7dG9rZW5CYWxhbmNlfSwgaXQgbmVlZHMgdG8gYmUgd2l0aGRyYXduIGJlZm9yZSBjbG9zaW5nIEFUQSBhZGRyZXNzYFxuICAgICAgKTtcblxuICAgICAgaWYgKCFwYXJhbXMucmVjb3ZlcnlEZXN0aW5hdGlvbkF0YUFkZHJlc3MgfHwgIXRoaXMuaXNWYWxpZEFkZHJlc3MocGFyYW1zLnJlY292ZXJ5RGVzdGluYXRpb25BdGFBZGRyZXNzKSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2ludmFsaWQgcmVjb3ZlcnlEZXN0aW5hdGlvbkF0YUFkZHJlc3MnKTtcbiAgICAgIH1cblxuICAgICAgYmxvY2toYXNoID0gYXdhaXQgdGhpcy5nZXRCbG9ja2hhc2gocGFyYW1zLmFwaUtleSk7XG5cbiAgICAgIHR4QnVpbGRlciA9IGZhY3RvcnlcbiAgICAgICAgLmdldFRva2VuVHJhbnNmZXJCdWlsZGVyKClcbiAgICAgICAgLm5vbmNlKGJsb2NraGFzaClcbiAgICAgICAgLnNlbmRlcihiczU4RW5jb2RlZFB1YmxpY0tleSlcbiAgICAgICAgLmFzc29jaWF0ZWRUb2tlbkFjY291bnRSZW50KHJlbnRFeGVtcHRBbW91bnQudG9TdHJpbmcoKSlcbiAgICAgICAgLmZlZVBheWVyKGJzNThFbmNvZGVkUHVibGljS2V5KTtcbiAgICAgIGNvbnN0IHVuc2lnbmVkVHJhbnNhY3Rpb24gPSAoYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCkpIGFzIFRyYW5zYWN0aW9uO1xuICAgICAgY29uc3Qgc2VyaWFsaXplZE1lc3NhZ2UgPSB1bnNpZ25lZFRyYW5zYWN0aW9uLnNvbFRyYW5zYWN0aW9uLnNlcmlhbGl6ZU1lc3NhZ2UoKS50b1N0cmluZygnYmFzZTY0Jyk7XG4gICAgICBjb25zdCBmZWVQZXJTaWduYXR1cmUgPSBhd2FpdCB0aGlzLmdldEZlZUZvck1lc3NhZ2Uoc2VyaWFsaXplZE1lc3NhZ2UsIHBhcmFtcy5hcGlLZXkpO1xuICAgICAgY29uc3QgYmFzZUZlZSA9IHBhcmFtcy5kdXJhYmxlTm9uY2UgPyBmZWVQZXJTaWduYXR1cmUgKiAyIDogZmVlUGVyU2lnbmF0dXJlO1xuICAgICAgY29uc3QgdG90YWxGZWUgPSBuZXcgQmlnTnVtYmVyKGJhc2VGZWUpO1xuICAgICAgaWYgKHRvdGFsRmVlLmd0KGFjY291bnRCYWxhbmNlKSkge1xuICAgICAgICB0aHJvdyBFcnJvcignRGlkIG5vdCBmaW5kIGFkZHJlc3Mgd2l0aCBmdW5kcyB0byByZWNvdmVyJyk7XG4gICAgICB9XG4gICAgICB0eEJ1aWxkZXIuZmVlKHsgYW1vdW50OiBmZWVQZXJTaWduYXR1cmUgfSk7XG5cbiAgICAgIGNvbnN0IG5ldHdvcmsgPSB0aGlzLmdldE5ldHdvcmsoKTtcbiAgICAgIGNvbnN0IHRva2VuID0gZ2V0U29sVG9rZW5Gcm9tQWRkcmVzcyh0b2tlbkluZm8uaW5mby5taW50LCBuZXR3b3JrKTsgLy8gdG9kbyhXSU4tNTg5NCkgZml4IGZvciBhbXNcbiAgICAgIHR4QnVpbGRlci5zZW5kKHtcbiAgICAgICAgYWRkcmVzczogcGFyYW1zLnJlY292ZXJ5RGVzdGluYXRpb25BdGFBZGRyZXNzLFxuICAgICAgICBhbW91bnQ6IHRva2VuQmFsYW5jZSxcbiAgICAgICAgdG9rZW5OYW1lOiB0b2tlbj8ubmFtZSxcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCB0b2tlblJlY292ZXJ5VHhuID0gYXdhaXQgdGhpcy5zaWduQW5kR2VuZXJhdGVCcm9hZGNhc3RhYmxlVHJhbnNhY3Rpb24oXG4gICAgICAgIHBhcmFtcyxcbiAgICAgICAgdHhCdWlsZGVyLFxuICAgICAgICBiczU4RW5jb2RlZFB1YmxpY0tleVxuICAgICAgKTtcbiAgICAgIGNvbnN0IHNlcmlhbGl6ZWRUb2tlblJlY292ZXJ5VHhuID0gKGF3YWl0IHRva2VuUmVjb3ZlcnlUeG4pLnNlcmlhbGl6ZWRUeDtcbiAgICAgIGNvbnN0IGJyb2FkY2FzdFRva2VuUmVjb3ZlcnlUeG4gPSBhd2FpdCB0aGlzLmJyb2FkY2FzdFRyYW5zYWN0aW9uKHtcbiAgICAgICAgc2VyaWFsaXplZFNpZ25lZFRyYW5zYWN0aW9uOiBzZXJpYWxpemVkVG9rZW5SZWNvdmVyeVR4bixcbiAgICAgIH0pO1xuICAgICAgY29uc29sZS5sb2coYnJvYWRjYXN0VG9rZW5SZWNvdmVyeVR4bik7XG4gICAgICByZWNvdmVydFR4bnMucHVzaChicm9hZGNhc3RUb2tlblJlY292ZXJ5VHhuKTtcbiAgICB9XG5cbiAgICAvLyBhZnRlciByZWNvdmVyaW5nIHRoZSB0b2tlbiBhbW91bnQsIGF0dGVtcHRpbmcgdG8gY2xvc2UgdGhlIEFUQSBhZGRyZXNzXG4gICAgaWYgKHBhcmFtcy5jbG9zZUF0YUFkZHJlc3MpIHtcbiAgICAgIGJsb2NraGFzaCA9IGF3YWl0IHRoaXMuZ2V0QmxvY2toYXNoKHBhcmFtcy5hcGlLZXkpO1xuXG4gICAgICBjb25zdCBhdGFDbG9zZUJ1aWxkZXIgPSAoKSA9PiB7XG4gICAgICAgIGNvbnN0IHR4QnVpbGRlciA9IGZhY3RvcnkuZ2V0Q2xvc2VBdGFJbml0aWFsaXphdGlvbkJ1aWxkZXIoKTtcbiAgICAgICAgdHhCdWlsZGVyLm5vbmNlKGJsb2NraGFzaCk7XG4gICAgICAgIHR4QnVpbGRlci5zZW5kZXIoYnM1OEVuY29kZWRQdWJsaWNLZXkpO1xuICAgICAgICB0eEJ1aWxkZXIuYWNjb3VudEFkZHJlc3MocGFyYW1zLmNsb3NlQXRhQWRkcmVzcyA/PyAnJyk7XG4gICAgICAgIHR4QnVpbGRlci5kZXN0aW5hdGlvbkFkZHJlc3MocGFyYW1zLnJlY292ZXJ5RGVzdGluYXRpb24pO1xuICAgICAgICB0eEJ1aWxkZXIuYXV0aG9yaXR5QWRkcmVzcyhiczU4RW5jb2RlZFB1YmxpY0tleSk7XG4gICAgICAgIHR4QnVpbGRlci5hc3NvY2lhdGVkVG9rZW5BY2NvdW50UmVudChyZW50RXhlbXB0QW1vdW50LnRvU3RyaW5nKCkpO1xuICAgICAgICByZXR1cm4gdHhCdWlsZGVyO1xuICAgICAgfTtcbiAgICAgIHR4QnVpbGRlciA9IGF0YUNsb3NlQnVpbGRlcigpO1xuICAgIH1cbiAgICBjb25zdCBjbG9zZUFUQVJlY292ZXJ5VHhuID0gYXdhaXQgdGhpcy5zaWduQW5kR2VuZXJhdGVCcm9hZGNhc3RhYmxlVHJhbnNhY3Rpb24oXG4gICAgICBwYXJhbXMsXG4gICAgICB0eEJ1aWxkZXIsXG4gICAgICBiczU4RW5jb2RlZFB1YmxpY0tleVxuICAgICk7XG4gICAgY29uc3Qgc2VyaWFsaXplZENsb3NlQVRBUmVjb3ZlcnlUeG4gPSAoYXdhaXQgY2xvc2VBVEFSZWNvdmVyeVR4bikuc2VyaWFsaXplZFR4O1xuICAgIGNvbnN0IGJyb2FkY2FzdENsb3NlQVRBUmVjb3ZlcnlUeG4gPSBhd2FpdCB0aGlzLmJyb2FkY2FzdFRyYW5zYWN0aW9uKHtcbiAgICAgIHNlcmlhbGl6ZWRTaWduZWRUcmFuc2FjdGlvbjogc2VyaWFsaXplZENsb3NlQVRBUmVjb3ZlcnlUeG4sXG4gICAgfSk7XG4gICAgY29uc29sZS5sb2coYnJvYWRjYXN0Q2xvc2VBVEFSZWNvdmVyeVR4bik7XG4gICAgcmVjb3ZlcnRUeG5zLnB1c2goYnJvYWRjYXN0Q2xvc2VBVEFSZWNvdmVyeVR4bik7XG5cbiAgICByZXR1cm4gcmVjb3ZlcnRUeG5zO1xuICB9XG5cbiAgYXN5bmMgc2lnbkFuZEdlbmVyYXRlQnJvYWRjYXN0YWJsZVRyYW5zYWN0aW9uKFxuICAgIHBhcmFtczogU29sUmVjb3ZlcnlPcHRpb25zLFxuICAgIHR4QnVpbGRlcjogYW55LFxuICAgIGJzNThFbmNvZGVkUHVibGljS2V5OiBzdHJpbmdcbiAgKTogUHJvbWlzZTxNUENUeD4ge1xuICAgIC8vIFNpZ24gdGhlIHR4blxuICAgIGlmICghcGFyYW1zLnVzZXJLZXkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignbWlzc2luZyB1c2VyS2V5Jyk7XG4gICAgfVxuXG4gICAgaWYgKCFwYXJhbXMuYmFja3VwS2V5KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ21pc3NpbmcgYmFja3VwS2V5Jyk7XG4gICAgfVxuXG4gICAgaWYgKCFwYXJhbXMud2FsbGV0UGFzc3BocmFzZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdtaXNzaW5nIHdhbGxldCBwYXNzcGhyYXNlJyk7XG4gICAgfVxuXG4gICAgY29uc3QgdW5zaWduZWRUcmFuc2FjdGlvbiA9IChhd2FpdCB0eEJ1aWxkZXIuYnVpbGQoKSkgYXMgVHJhbnNhY3Rpb247XG5cbiAgICBjb25zdCB1c2VyS2V5ID0gcGFyYW1zLnVzZXJLZXkucmVwbGFjZSgvXFxzL2csICcnKTtcbiAgICBjb25zdCBiYWNrdXBLZXkgPSBwYXJhbXMuYmFja3VwS2V5LnJlcGxhY2UoL1xccy9nLCAnJyk7XG5cbiAgICAvLyBEZWNyeXB0IHByaXZhdGUga2V5cyBmcm9tIEtleUNhcmQgdmFsdWVzXG4gICAgbGV0IHVzZXJQcnY7XG5cbiAgICB0cnkge1xuICAgICAgdXNlclBydiA9IHRoaXMuYml0Z28uZGVjcnlwdCh7XG4gICAgICAgIGlucHV0OiB1c2VyS2V5LFxuICAgICAgICBwYXNzd29yZDogcGFyYW1zLndhbGxldFBhc3NwaHJhc2UsXG4gICAgICB9KTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEVycm9yIGRlY3J5cHRpbmcgdXNlciBrZXljaGFpbjogJHtlLm1lc3NhZ2V9YCk7XG4gICAgfVxuXG4gICAgY29uc3QgdXNlclNpZ25pbmdNYXRlcmlhbCA9IEpTT04ucGFyc2UodXNlclBydikgYXMgRUREU0FNZXRob2RUeXBlcy5Vc2VyU2lnbmluZ01hdGVyaWFsO1xuXG4gICAgbGV0IGJhY2t1cFBydjtcbiAgICB0cnkge1xuICAgICAgYmFja3VwUHJ2ID0gdGhpcy5iaXRnby5kZWNyeXB0KHtcbiAgICAgICAgaW5wdXQ6IGJhY2t1cEtleSxcbiAgICAgICAgcGFzc3dvcmQ6IHBhcmFtcy53YWxsZXRQYXNzcGhyYXNlLFxuICAgICAgfSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBFcnJvciBkZWNyeXB0aW5nIGJhY2t1cCBrZXljaGFpbjogJHtlLm1lc3NhZ2V9YCk7XG4gICAgfVxuICAgIGNvbnN0IGJhY2t1cFNpZ25pbmdNYXRlcmlhbCA9IEpTT04ucGFyc2UoYmFja3VwUHJ2KSBhcyBFRERTQU1ldGhvZFR5cGVzLkJhY2t1cFNpZ25pbmdNYXRlcmlhbDtcblxuICAgIGNvbnN0IGluZGV4ID0gcGFyYW1zLmluZGV4IHx8IDA7XG4gICAgY29uc3QgY3VyclBhdGggPSBwYXJhbXMuc2VlZCA/IGdldERlcml2YXRpb25QYXRoKHBhcmFtcy5zZWVkKSArIGAvJHtpbmRleH1gIDogYG0vJHtpbmRleH1gO1xuXG4gICAgY29uc3Qgc2lnbmF0dXJlSGV4ID0gYXdhaXQgRUREU0FNZXRob2RzLmdldFRTU1NpZ25hdHVyZShcbiAgICAgIHVzZXJTaWduaW5nTWF0ZXJpYWwsXG4gICAgICBiYWNrdXBTaWduaW5nTWF0ZXJpYWwsXG4gICAgICBjdXJyUGF0aCxcbiAgICAgIHVuc2lnbmVkVHJhbnNhY3Rpb25cbiAgICApO1xuXG4gICAgY29uc3QgcHVibGljS2V5T2JqID0geyBwdWI6IGJzNThFbmNvZGVkUHVibGljS2V5IH07XG4gICAgdHhCdWlsZGVyLmFkZFNpZ25hdHVyZShwdWJsaWNLZXlPYmogYXMgUHVibGljS2V5LCBzaWduYXR1cmVIZXgpO1xuXG4gICAgY29uc3QgY29tcGxldGVkVHJhbnNhY3Rpb24gPSBhd2FpdCB0eEJ1aWxkZXIuYnVpbGQoKTtcbiAgICBjb25zdCBzZXJpYWxpemVkVHggPSBjb21wbGV0ZWRUcmFuc2FjdGlvbi50b0Jyb2FkY2FzdEZvcm1hdCgpO1xuICAgIGNvbnN0IHRyYW5zYWN0aW9uOiBNUENUeCA9IHtcbiAgICAgIHNlcmlhbGl6ZWRUeDogc2VyaWFsaXplZFR4LFxuICAgICAgc2NhbkluZGV4OiBpbmRleCxcbiAgICB9O1xuICAgIHJldHVybiB0cmFuc2FjdGlvbjtcbiAgfVxuXG4gIC8qKlxuICAgKiBCdWlsZHMgbmF0aXZlIFNPTCByZWNvdmVyaWVzIG9mIHJlY2VpdmUgYWRkcmVzc2VzIGluIGJhdGNoIHdpdGhvdXQgQml0R28uXG4gICAqIEZ1bmRzIHdpbGwgYmUgcmVjb3ZlcmVkIHRvIGJhc2UgYWRkcmVzcyBmaXJzdC4gWW91IG5lZWQgdG8gaW5pdGlhdGUgYW5vdGhlciBzd2VlcCB0eG4gYWZ0ZXIgdGhhdC5cbiAgICpcbiAgICogQHBhcmFtIHtTb2xDb25zb2xpZGF0aW9uUmVjb3ZlcnlPcHRpb25zfSBwYXJhbXMgLSBvcHRpb25zIGZvciBjb25zb2xpZGF0aW9uIHJlY292ZXJ5LlxuICAgKiBAcGFyYW0ge3N0cmluZ30gW3BhcmFtcy5zdGFydGluZ1NjYW5JbmRleF0gLSByZWNlaXZlIGFkZHJlc3MgaW5kZXggdG8gc3RhcnQgc2Nhbm5pbmcgZnJvbS4gZGVmYXVsdCB0byAxIChpbmNsdXNpdmUpLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gW3BhcmFtcy5lbmRpbmdTY2FuSW5kZXhdIC0gcmVjZWl2ZSBhZGRyZXNzIGluZGV4IHRvIGVuZCBzY2FubmluZyBhdC4gZGVmYXVsdCB0byBzdGFydGluZ1NjYW5JbmRleCArIDIwIChleGNsdXNpdmUpLlxuICAgKi9cbiAgYXN5bmMgcmVjb3ZlckNvbnNvbGlkYXRpb25zKHBhcmFtczogU29sQ29uc29saWRhdGlvblJlY292ZXJ5T3B0aW9ucyk6IFByb21pc2U8TVBDVHhzIHwgTVBDU3dlZXBUeHM+IHtcbiAgICBjb25zdCBpc1Vuc2lnbmVkU3dlZXAgPSAhcGFyYW1zLnVzZXJLZXkgJiYgIXBhcmFtcy5iYWNrdXBLZXkgJiYgIXBhcmFtcy53YWxsZXRQYXNzcGhyYXNlO1xuICAgIGNvbnN0IHN0YXJ0SWR4ID0gcGFyYW1zLnN0YXJ0aW5nU2NhbkluZGV4IHx8IDE7XG4gICAgY29uc3QgZW5kSWR4ID0gcGFyYW1zLmVuZGluZ1NjYW5JbmRleCB8fCBzdGFydElkeCArIERFRkFVTFRfU0NBTl9GQUNUT1I7XG5cbiAgICBpZiAoc3RhcnRJZHggPCAxIHx8IGVuZElkeCA8PSBzdGFydElkeCB8fCBlbmRJZHggLSBzdGFydElkeCA+IDEwICogREVGQVVMVF9TQ0FOX0ZBQ1RPUikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgSW52YWxpZCBzdGFydGluZyBvciBlbmRpbmcgaW5kZXggdG8gc2NhbiBmb3IgYWRkcmVzc2VzLiBzdGFydGluZ1NjYW5JbmRleDogJHtzdGFydElkeH0sIGVuZGluZ1NjYW5JbmRleDogJHtlbmRJZHh9LmBcbiAgICAgICk7XG4gICAgfVxuXG4gICAgLy8gdmFsaWRhdGUgZHVyYWJsZSBub25jZXMgYXJyYXlcbiAgICBpZiAoIXBhcmFtcy5kdXJhYmxlTm9uY2VzKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ01pc3NpbmcgZHVyYWJsZSBub25jZXMnKTtcbiAgICB9XG4gICAgaWYgKCFwYXJhbXMuZHVyYWJsZU5vbmNlcy5wdWJsaWNLZXlzKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgZHVyYWJsZSBub25jZXM6IG1pc3NpbmcgcHVibGljIGtleXMnKTtcbiAgICB9XG4gICAgaWYgKCFwYXJhbXMuZHVyYWJsZU5vbmNlcy5zZWNyZXRLZXkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBkdXJhYmxlIG5vbmNlcyBhcnJheTogbWlzc2luZyBzZWNyZXQga2V5Jyk7XG4gICAgfVxuXG4gICAgY29uc3QgYml0Z29LZXkgPSBwYXJhbXMuYml0Z29LZXkucmVwbGFjZSgvXFxzL2csICcnKTtcbiAgICBjb25zdCBNUEMgPSBhd2FpdCBFRERTQU1ldGhvZHMuZ2V0SW5pdGlhbGl6ZWRNcGNJbnN0YW5jZSgpO1xuICAgIGNvbnN0IGJhc2VBZGRyZXNzSW5kZXggPSAwO1xuICAgIGNvbnN0IGJhc2VBZGRyZXNzUGF0aCA9IHBhcmFtcy5zZWVkXG4gICAgICA/IGdldERlcml2YXRpb25QYXRoKHBhcmFtcy5zZWVkKSArIGAvJHtiYXNlQWRkcmVzc0luZGV4fWBcbiAgICAgIDogYG0vJHtiYXNlQWRkcmVzc0luZGV4fWA7XG4gICAgY29uc3QgYWNjb3VudElkID0gTVBDLmRlcml2ZVVuaGFyZGVuZWQoYml0Z29LZXksIGJhc2VBZGRyZXNzUGF0aCkuc2xpY2UoMCwgNjQpO1xuICAgIGNvbnN0IGJhc2VBZGRyZXNzID0gbmV3IFNvbEtleVBhaXIoeyBwdWI6IGFjY291bnRJZCB9KS5nZXRBZGRyZXNzKCk7XG5cbiAgICBsZXQgZHVyYWJsZU5vbmNlUHViS2V5c0luZGV4ID0gMDtcbiAgICBjb25zdCBkdXJhYmxlTm9uY2VQdWJLZXlzTGVuZ3RoID0gcGFyYW1zLmR1cmFibGVOb25jZXMucHVibGljS2V5cy5sZW5ndGg7XG4gICAgY29uc3QgY29uc29saWRhdGlvblRyYW5zYWN0aW9uczogYW55W10gPSBbXTtcbiAgICBsZXQgbGFzdFNjYW5JbmRleCA9IHN0YXJ0SWR4O1xuXG4gICAgZm9yIChsZXQgaSA9IHN0YXJ0SWR4OyBpIDwgZW5kSWR4OyBpKyspIHtcbiAgICAgIGNvbnN0IHJlY292ZXJQYXJhbXMgPSB7XG4gICAgICAgIHVzZXJLZXk6IHBhcmFtcy51c2VyS2V5LFxuICAgICAgICBiYWNrdXBLZXk6IHBhcmFtcy5iYWNrdXBLZXksXG4gICAgICAgIGJpdGdvS2V5OiBwYXJhbXMuYml0Z29LZXksXG4gICAgICAgIHdhbGxldFBhc3NwaHJhc2U6IHBhcmFtcy53YWxsZXRQYXNzcGhyYXNlLFxuICAgICAgICByZWNvdmVyeURlc3RpbmF0aW9uOiBiYXNlQWRkcmVzcyxcbiAgICAgICAgc2VlZDogcGFyYW1zLnNlZWQsXG4gICAgICAgIGluZGV4OiBpLFxuICAgICAgICBkdXJhYmxlTm9uY2U6IHtcbiAgICAgICAgICBwdWJsaWNLZXk6IHBhcmFtcy5kdXJhYmxlTm9uY2VzLnB1YmxpY0tleXNbZHVyYWJsZU5vbmNlUHViS2V5c0luZGV4XSxcbiAgICAgICAgICBzZWNyZXRLZXk6IHBhcmFtcy5kdXJhYmxlTm9uY2VzLnNlY3JldEtleSxcbiAgICAgICAgfSxcbiAgICAgICAgdG9rZW5Db250cmFjdEFkZHJlc3M6IHBhcmFtcy50b2tlbkNvbnRyYWN0QWRkcmVzcyxcbiAgICAgICAgYXBpS2V5OiBwYXJhbXMuYXBpS2V5LFxuICAgICAgICBwcm9ncmFtSWQ6IHBhcmFtcy5wcm9ncmFtSWQsXG4gICAgICB9O1xuXG4gICAgICBsZXQgcmVjb3ZlcnlUcmFuc2FjdGlvbjtcbiAgICAgIHRyeSB7XG4gICAgICAgIHJlY292ZXJ5VHJhbnNhY3Rpb24gPSBhd2FpdCB0aGlzLnJlY292ZXIocmVjb3ZlclBhcmFtcyk7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIGlmIChcbiAgICAgICAgICBlLm1lc3NhZ2UgPT09ICdEaWQgbm90IGZpbmQgYWRkcmVzcyB3aXRoIGZ1bmRzIHRvIHJlY292ZXInIHx8XG4gICAgICAgICAgZS5tZXNzYWdlID09PSAnRGlkIG5vdCBmaW5kIHRva2VuIGFjY291bnQgdG8gcmVjb3ZlciB0b2tlbnMsIHBsZWFzZSBjaGVjayB0b2tlbiBhY2NvdW50JyB8fFxuICAgICAgICAgIGUubWVzc2FnZSA9PT0gJ05vdCBlbm91Z2ggdG9rZW4gZnVuZHMgdG8gcmVjb3ZlcidcbiAgICAgICAgKSB7XG4gICAgICAgICAgbGFzdFNjYW5JbmRleCA9IGk7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH1cblxuICAgICAgaWYgKGlzVW5zaWduZWRTd2VlcCkge1xuICAgICAgICBjb25zb2xpZGF0aW9uVHJhbnNhY3Rpb25zLnB1c2goKHJlY292ZXJ5VHJhbnNhY3Rpb24gYXMgTVBDU3dlZXBUeHMpLnR4UmVxdWVzdHNbMF0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc29saWRhdGlvblRyYW5zYWN0aW9ucy5wdXNoKHJlY292ZXJ5VHJhbnNhY3Rpb24pO1xuICAgICAgfVxuXG4gICAgICBsYXN0U2NhbkluZGV4ID0gaTtcbiAgICAgIGR1cmFibGVOb25jZVB1YktleXNJbmRleCsrO1xuICAgICAgaWYgKGR1cmFibGVOb25jZVB1YktleXNJbmRleCA+PSBkdXJhYmxlTm9uY2VQdWJLZXlzTGVuZ3RoKSB7XG4gICAgICAgIC8vIG5vIG1vcmUgYXZhaWxhYmxlIG5vbmNlIGFjY291bnRzIHRvIGNyZWF0ZSB0cmFuc2FjdGlvbnNcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGNvbnNvbGlkYXRpb25UcmFuc2FjdGlvbnMubGVuZ3RoID09PSAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0RpZCBub3QgZmluZCBhbiBhZGRyZXNzIHdpdGggZnVuZHMgdG8gcmVjb3ZlcicpO1xuICAgIH1cblxuICAgIGlmIChpc1Vuc2lnbmVkU3dlZXApIHtcbiAgICAgIC8vIGxhc3RTY2FuSW5kZXggd2lsbCBiZSB1c2VkIHRvIGluZm9ybSB1c2VyIHRoZSBsYXN0IGFkZHJlc3MgaW5kZXggc2Nhbm5lZCBmb3IgYXZhaWxhYmxlIGZ1bmRzIChzbyB0aGV5IGNhblxuICAgICAgLy8gYXBwcm9wcmlhdGVseSBhZGp1c3QgdGhlIHNjYW4gcmFuZ2Ugb24gdGhlIG5leHQgaXRlcmF0aW9uIG9mIGNvbnNvbGlkYXRpb24gcmVjb3ZlcmllcykuIEluIHRoZSBjYXNlIG9mIHVuc2lnbmVkXG4gICAgICAvLyBzd2VlcCBjb25zb2xpZGF0aW9ucywgdGhpcyBsYXN0U2NhbkluZGV4IHdpbGwgYmUgcHJvdmlkZWQgaW4gdGhlIGNvaW5TcGVjaWZpYyBvZiB0aGUgbGFzdCB0eG4gbWFkZS5cbiAgICAgIGNvbnN0IGxhc3RUcmFuc2FjdGlvbkNvaW5TcGVjaWZpYyA9IHtcbiAgICAgICAgY29tbW9uS2V5Y2hhaW46XG4gICAgICAgICAgY29uc29saWRhdGlvblRyYW5zYWN0aW9uc1tjb25zb2xpZGF0aW9uVHJhbnNhY3Rpb25zLmxlbmd0aCAtIDFdLnRyYW5zYWN0aW9uc1swXS51bnNpZ25lZFR4LmNvaW5TcGVjaWZpY1xuICAgICAgICAgICAgLmNvbW1vbktleWNoYWluLFxuICAgICAgICBsYXN0U2NhbkluZGV4OiBsYXN0U2NhbkluZGV4LFxuICAgICAgfTtcbiAgICAgIGNvbnNvbGlkYXRpb25UcmFuc2FjdGlvbnNbY29uc29saWRhdGlvblRyYW5zYWN0aW9ucy5sZW5ndGggLSAxXS50cmFuc2FjdGlvbnNbMF0udW5zaWduZWRUeC5jb2luU3BlY2lmaWMgPVxuICAgICAgICBsYXN0VHJhbnNhY3Rpb25Db2luU3BlY2lmaWM7XG4gICAgICBjb25zdCBjb25zb2xpZGF0aW9uU3dlZXBUcmFuc2FjdGlvbnM6IE1QQ1N3ZWVwVHhzID0geyB0eFJlcXVlc3RzOiBjb25zb2xpZGF0aW9uVHJhbnNhY3Rpb25zIH07XG4gICAgICByZXR1cm4gY29uc29saWRhdGlvblN3ZWVwVHJhbnNhY3Rpb25zO1xuICAgIH1cblxuICAgIHJldHVybiB7IHRyYW5zYWN0aW9uczogY29uc29saWRhdGlvblRyYW5zYWN0aW9ucywgbGFzdFNjYW5JbmRleCB9O1xuICB9XG5cbiAgZ2V0VG9rZW5FbmFibGVtZW50Q29uZmlnKCk6IFRva2VuRW5hYmxlbWVudENvbmZpZyB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHJlcXVpcmVzVG9rZW5FbmFibGVtZW50OiB0cnVlLFxuICAgICAgc3VwcG9ydHNNdWx0aXBsZVRva2VuRW5hYmxlbWVudHM6IHRydWUsXG4gICAgfTtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0QnVpbGRlcigpOiBUcmFuc2FjdGlvbkJ1aWxkZXJGYWN0b3J5IHtcbiAgICByZXR1cm4gbmV3IFRyYW5zYWN0aW9uQnVpbGRlckZhY3RvcnkoY29pbnMuZ2V0KHRoaXMuZ2V0Q2hhaW4oKSkpO1xuICB9XG5cbiAgYXN5bmMgYnJvYWRjYXN0VHJhbnNhY3Rpb24oe1xuICAgIHNlcmlhbGl6ZWRTaWduZWRUcmFuc2FjdGlvbixcbiAgfTogQmFzZUJyb2FkY2FzdFRyYW5zYWN0aW9uT3B0aW9ucyk6IFByb21pc2U8QmFzZUJyb2FkY2FzdFRyYW5zYWN0aW9uUmVzdWx0PiB7XG4gICAgdmFsaWRhdGVSYXdUcmFuc2FjdGlvbihzZXJpYWxpemVkU2lnbmVkVHJhbnNhY3Rpb24sIHRydWUsIHRydWUpO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5nZXREYXRhRnJvbU5vZGUoe1xuICAgICAgcGF5bG9hZDoge1xuICAgICAgICBpZDogJzEnLFxuICAgICAgICBqc29ucnBjOiAnMi4wJyxcbiAgICAgICAgbWV0aG9kOiAnc2VuZFRyYW5zYWN0aW9uJyxcbiAgICAgICAgcGFyYW1zOiBbXG4gICAgICAgICAgc2VyaWFsaXplZFNpZ25lZFRyYW5zYWN0aW9uLFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIGVuY29kaW5nOiAnYmFzZTY0JyxcbiAgICAgICAgICB9LFxuICAgICAgICBdLFxuICAgICAgfSxcbiAgICB9KTtcblxuICAgIGlmIChyZXNwb25zZS5ib2R5LmVycm9yKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Vycm9yIGJyb2FkY2FzdGluZyB0cmFuc2FjdGlvbjogJyArIHJlc3BvbnNlLmJvZHkuZXJyb3IubWVzc2FnZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHsgdHhJZDogcmVzcG9uc2UuYm9keS5yZXN1bHQgfTtcbiAgfVxuXG4gIC8qKiBAaW5oZXJpdERvYyAqL1xuICBhdWRpdERlY3J5cHRlZEtleSh7IHBydiwgcHVibGljS2V5LCBtdWx0aVNpZ1R5cGUgfTogQXVkaXREZWNyeXB0ZWRLZXlQYXJhbXMpIHtcbiAgICBpZiAobXVsdGlTaWdUeXBlICE9PSAndHNzJykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdVbnN1cHBvcnRlZCBtdWx0aVNpZ1R5cGUnKTtcbiAgICB9XG4gICAgYXVkaXRFZGRzYVByaXZhdGVLZXkocHJ2LCBwdWJsaWNLZXkgPz8gJycpO1xuICB9XG5cbiAgLyoqIEBpbmhlcml0RG9jICovXG4gIHNldENvaW5TcGVjaWZpY0ZpZWxkc0luSW50ZW50KGludGVudDogUG9wdWxhdGVkSW50ZW50LCBwYXJhbXM6IFByZWJ1aWxkVHJhbnNhY3Rpb25XaXRoSW50ZW50T3B0aW9ucyk6IHZvaWQge1xuICAgIC8vIEhhbmRsZSBjdXN0b20gaW5zdHJ1Y3Rpb25zIGZvciBTb2xhbmFcbiAgICBpZiAocGFyYW1zLnNvbEluc3RydWN0aW9ucykge1xuICAgICAgaW50ZW50LnNvbEluc3RydWN0aW9ucyA9IHBhcmFtcy5zb2xJbnN0cnVjdGlvbnM7XG4gICAgfVxuXG4gICAgLy8gSGFuZGxlIHZlcnNpb25lZCB0cmFuc2FjdGlvbiBkYXRhIGZvciBTb2xhbmFcbiAgICBpZiAocGFyYW1zLnNvbFZlcnNpb25lZFRyYW5zYWN0aW9uRGF0YSkge1xuICAgICAgaW50ZW50LnNvbFZlcnNpb25lZFRyYW5zYWN0aW9uRGF0YSA9IHBhcmFtcy5zb2xWZXJzaW9uZWRUcmFuc2FjdGlvbkRhdGE7XG4gICAgfVxuICB9XG59XG4iXX0=
|