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