@bitgo-beta/sdk-coin-ada 0.0.0-semantic-release-managed

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. package/.eslintignore +5 -0
  2. package/.mocharc.yml +8 -0
  3. package/CHANGELOG.md +1207 -0
  4. package/LICENSE +191 -0
  5. package/README.md +30 -0
  6. package/dist/src/ada.d.ts +116 -0
  7. package/dist/src/ada.d.ts.map +1 -0
  8. package/dist/src/ada.js +556 -0
  9. package/dist/src/adaToken.d.ts +31 -0
  10. package/dist/src/adaToken.d.ts.map +1 -0
  11. package/dist/src/adaToken.js +72 -0
  12. package/dist/src/index.d.ts +6 -0
  13. package/dist/src/index.d.ts.map +1 -0
  14. package/dist/src/index.js +22 -0
  15. package/dist/src/lib/index.d.ts +15 -0
  16. package/dist/src/lib/index.d.ts.map +1 -0
  17. package/dist/src/lib/index.js +65 -0
  18. package/dist/src/lib/keyPair.d.ts +20 -0
  19. package/dist/src/lib/keyPair.d.ts.map +1 -0
  20. package/dist/src/lib/keyPair.js +91 -0
  21. package/dist/src/lib/messages/cip8/cip8Message.d.ts +25 -0
  22. package/dist/src/lib/messages/cip8/cip8Message.d.ts.map +1 -0
  23. package/dist/src/lib/messages/cip8/cip8Message.js +140 -0
  24. package/dist/src/lib/messages/cip8/cip8MessageBuilder.d.ts +19 -0
  25. package/dist/src/lib/messages/cip8/cip8MessageBuilder.d.ts.map +1 -0
  26. package/dist/src/lib/messages/cip8/cip8MessageBuilder.js +27 -0
  27. package/dist/src/lib/messages/cip8/index.d.ts +3 -0
  28. package/dist/src/lib/messages/cip8/index.d.ts.map +1 -0
  29. package/dist/src/lib/messages/cip8/index.js +19 -0
  30. package/dist/src/lib/messages/cip8/utils.d.ts +24 -0
  31. package/dist/src/lib/messages/cip8/utils.d.ts.map +1 -0
  32. package/dist/src/lib/messages/cip8/utils.js +73 -0
  33. package/dist/src/lib/messages/index.d.ts +3 -0
  34. package/dist/src/lib/messages/index.d.ts.map +1 -0
  35. package/dist/src/lib/messages/index.js +19 -0
  36. package/dist/src/lib/messages/messageBuilderFactory.d.ts +7 -0
  37. package/dist/src/lib/messages/messageBuilderFactory.d.ts.map +1 -0
  38. package/dist/src/lib/messages/messageBuilderFactory.js +20 -0
  39. package/dist/src/lib/stakingActivateBuilder.d.ts +24 -0
  40. package/dist/src/lib/stakingActivateBuilder.d.ts.map +1 -0
  41. package/dist/src/lib/stakingActivateBuilder.js +88 -0
  42. package/dist/src/lib/stakingBaseClaimBuilder.d.ts +20 -0
  43. package/dist/src/lib/stakingBaseClaimBuilder.d.ts.map +1 -0
  44. package/dist/src/lib/stakingBaseClaimBuilder.js +35 -0
  45. package/dist/src/lib/stakingClaimRewardsBuilder.d.ts +10 -0
  46. package/dist/src/lib/stakingClaimRewardsBuilder.d.ts.map +1 -0
  47. package/dist/src/lib/stakingClaimRewardsBuilder.js +22 -0
  48. package/dist/src/lib/stakingDeactivateBuilder.d.ts +22 -0
  49. package/dist/src/lib/stakingDeactivateBuilder.d.ts.map +1 -0
  50. package/dist/src/lib/stakingDeactivateBuilder.js +75 -0
  51. package/dist/src/lib/stakingPledgeBuilder.d.ts +23 -0
  52. package/dist/src/lib/stakingPledgeBuilder.d.ts.map +1 -0
  53. package/dist/src/lib/stakingPledgeBuilder.js +43 -0
  54. package/dist/src/lib/stakingWithdrawBuilder.d.ts +12 -0
  55. package/dist/src/lib/stakingWithdrawBuilder.d.ts.map +1 -0
  56. package/dist/src/lib/stakingWithdrawBuilder.js +22 -0
  57. package/dist/src/lib/transaction.d.ts +133 -0
  58. package/dist/src/lib/transaction.d.ts.map +1 -0
  59. package/dist/src/lib/transaction.js +371 -0
  60. package/dist/src/lib/transactionBuilder.d.ts +59 -0
  61. package/dist/src/lib/transactionBuilder.d.ts.map +1 -0
  62. package/dist/src/lib/transactionBuilder.js +445 -0
  63. package/dist/src/lib/transactionBuilderFactory.d.ts +36 -0
  64. package/dist/src/lib/transactionBuilderFactory.d.ts.map +1 -0
  65. package/dist/src/lib/transactionBuilderFactory.js +92 -0
  66. package/dist/src/lib/transferBuilder.d.ts +14 -0
  67. package/dist/src/lib/transferBuilder.d.ts.map +1 -0
  68. package/dist/src/lib/transferBuilder.js +27 -0
  69. package/dist/src/lib/utils.d.ts +52 -0
  70. package/dist/src/lib/utils.d.ts.map +1 -0
  71. package/dist/src/lib/utils.js +277 -0
  72. package/dist/src/lib/voteDelegationBuilder.d.ts +24 -0
  73. package/dist/src/lib/voteDelegationBuilder.d.ts.map +1 -0
  74. package/dist/src/lib/voteDelegationBuilder.js +84 -0
  75. package/dist/src/lib/walletInitializationBuilder.d.ts +14 -0
  76. package/dist/src/lib/walletInitializationBuilder.d.ts.map +1 -0
  77. package/dist/src/lib/walletInitializationBuilder.js +24 -0
  78. package/dist/src/register.d.ts +3 -0
  79. package/dist/src/register.d.ts.map +1 -0
  80. package/dist/src/register.js +13 -0
  81. package/dist/src/tada.d.ts +21 -0
  82. package/dist/src/tada.d.ts.map +1 -0
  83. package/dist/src/tada.js +26 -0
  84. package/package.json +61 -0
@@ -0,0 +1,59 @@
1
+ import BigNumber from 'bignumber.js';
2
+ import { BaseCoin as CoinConfig } from '@bitgo-beta/statics';
3
+ import { BaseAddress, BaseKey, BaseTransactionBuilder, PublicKey as BasePublicKey, Signature, TransactionType } from '@bitgo-beta/sdk-core';
4
+ import { Asset, Transaction, TransactionInput, TransactionOutput, Withdrawal } from './transaction';
5
+ import { KeyPair } from './keyPair';
6
+ import * as CardanoWasm from '@emurgo/cardano-serialization-lib-nodejs';
7
+ export declare abstract class TransactionBuilder extends BaseTransactionBuilder {
8
+ protected _transaction: Transaction;
9
+ protected _signers: KeyPair[];
10
+ protected _transactionInputs: TransactionInput[];
11
+ protected _transactionOutputs: TransactionOutput[];
12
+ protected _initSignatures: Signature[];
13
+ protected _signatures: Signature[];
14
+ protected _changeAddress: string;
15
+ protected _senderBalance: string;
16
+ protected _ttl: number;
17
+ protected _certs: CardanoWasm.Certificate[];
18
+ protected _withdrawals: Withdrawal[];
19
+ protected _type: TransactionType;
20
+ protected _multiAssets: Asset[];
21
+ private _fee;
22
+ constructor(_coinConfig: Readonly<CoinConfig>);
23
+ input(i: TransactionInput): this;
24
+ output(o: TransactionOutput): this;
25
+ assets(a: Asset): this;
26
+ ttl(t: number): this;
27
+ changeAddress(addr: string, totalInputBalance: string): this;
28
+ fee(fee: string): this;
29
+ /**
30
+ * Initialize the transaction builder fields using the decoded transaction data
31
+ *
32
+ * @param {Transaction} tx the transaction data
33
+ */
34
+ initBuilder(tx: Transaction): void;
35
+ /** @inheritdoc */
36
+ protected fromImplementation(rawTransaction: string): Transaction;
37
+ /** @inheritdoc */
38
+ protected buildImplementation(): Promise<Transaction>;
39
+ /** @inheritdoc */
40
+ protected signImplementation(key: BaseKey): Transaction;
41
+ /** @inheritdoc */
42
+ protected get transaction(): Transaction;
43
+ /** @inheritdoc */
44
+ protected set transaction(transaction: Transaction);
45
+ /** @inheritdoc */
46
+ validateAddress(address: BaseAddress, addressFormat?: string): void;
47
+ /** @inheritdoc */
48
+ validateKey(key: BaseKey): void;
49
+ /** @inheritdoc */
50
+ validateRawTransaction(rawTransaction: any): void;
51
+ /** @inheritdoc */
52
+ validateTransaction(transaction: Transaction): void;
53
+ /** @inheritdoc */
54
+ validateValue(value: BigNumber): void;
55
+ /** @inheritDoc */
56
+ addSignature(publicKey: BasePublicKey, signature: Buffer): void;
57
+ private getAllSignatures;
58
+ }
59
+ //# sourceMappingURL=transactionBuilder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transactionBuilder.d.ts","sourceRoot":"","sources":["../../../src/lib/transactionBuilder.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,cAAc,CAAC;AACrC,OAAO,EAAE,QAAQ,IAAI,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,EACL,WAAW,EACX,OAAO,EACP,sBAAsB,EAEtB,SAAS,IAAI,aAAa,EAC1B,SAAS,EACT,eAAe,EAEhB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AACpG,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,KAAK,WAAW,MAAM,0CAA0C,CAAC;AAGxE,8BAAsB,kBAAmB,SAAQ,sBAAsB;IACrE,SAAS,CAAC,YAAY,EAAG,WAAW,CAAC;IACrC,SAAS,CAAC,QAAQ,EAAE,OAAO,EAAE,CAAM;IACnC,SAAS,CAAC,kBAAkB,EAAE,gBAAgB,EAAE,CAAM;IACtD,SAAS,CAAC,mBAAmB,EAAE,iBAAiB,EAAE,CAAM;IACxD,SAAS,CAAC,eAAe,EAAE,SAAS,EAAE,CAAM;IAC5C,SAAS,CAAC,WAAW,EAAE,SAAS,EAAE,CAAM;IACxC,SAAS,CAAC,cAAc,EAAE,MAAM,CAAC;IACjC,SAAS,CAAC,cAAc,EAAE,MAAM,CAAC;IACjC,SAAS,CAAC,IAAI,SAAK;IACnB,SAAS,CAAC,MAAM,EAAE,WAAW,CAAC,WAAW,EAAE,CAAM;IACjD,SAAS,CAAC,YAAY,EAAE,UAAU,EAAE,CAAM;IAC1C,SAAS,CAAC,KAAK,EAAE,eAAe,CAAC;IACjC,SAAS,CAAC,YAAY,EAAE,KAAK,EAAE,CAAM;IACrC,OAAO,CAAC,IAAI,CAAS;gBAET,WAAW,EAAE,QAAQ,CAAC,UAAU,CAAC;IAM7C,KAAK,CAAC,CAAC,EAAE,gBAAgB,GAAG,IAAI;IAKhC,MAAM,CAAC,CAAC,EAAE,iBAAiB,GAAG,IAAI;IAKlC,MAAM,CAAC,CAAC,EAAE,KAAK,GAAG,IAAI;IAKtB,GAAG,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI;IAKpB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,GAAG,IAAI;IAM5D,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAKtB;;;;OAIG;IACH,WAAW,CAAC,EAAE,EAAE,WAAW,GAAG,IAAI;IAmDlC,kBAAkB;IAClB,SAAS,CAAC,kBAAkB,CAAC,cAAc,EAAE,MAAM,GAAG,WAAW;IAMjE,kBAAkB;cACF,mBAAmB,IAAI,OAAO,CAAC,WAAW,CAAC;IAiT3D,kBAAkB;IAClB,SAAS,CAAC,kBAAkB,CAAC,GAAG,EAAE,OAAO,GAAG,WAAW;IAKvD,kBAAkB;IAClB,SAAS,KAAK,WAAW,IAAI,WAAW,CAEvC;IAED,kBAAkB;IAClB,SAAS,KAAK,WAAW,CAAC,WAAW,EAAE,WAAW,EAEjD;IAED,kBAAkB;IAClB,eAAe,CAAC,OAAO,EAAE,WAAW,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI;IAMnE,kBAAkB;IAClB,WAAW,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI;IAQ/B,kBAAkB;IAClB,sBAAsB,CAAC,cAAc,EAAE,GAAG,GAAG,IAAI;IAQjD,kBAAkB;IAClB,mBAAmB,CAAC,WAAW,EAAE,WAAW,GAAG,IAAI;IAMnD,kBAAkB;IAClB,aAAa,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI;IAOrC,kBAAkB;IAClB,YAAY,CAAC,SAAS,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI;IAI/D,OAAO,CAAC,gBAAgB;CAGzB"}
@@ -0,0 +1,445 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.TransactionBuilder = void 0;
37
+ const sdk_core_1 = require("@bitgo-beta/sdk-core");
38
+ const transaction_1 = require("./transaction");
39
+ const keyPair_1 = require("./keyPair");
40
+ const utils_1 = __importStar(require("./utils"));
41
+ const CardanoWasm = __importStar(require("@emurgo/cardano-serialization-lib-nodejs"));
42
+ const cardano_serialization_lib_nodejs_1 = require("@emurgo/cardano-serialization-lib-nodejs");
43
+ class TransactionBuilder extends sdk_core_1.BaseTransactionBuilder {
44
+ constructor(_coinConfig) {
45
+ super(_coinConfig);
46
+ this._signers = [];
47
+ this._transactionInputs = [];
48
+ this._transactionOutputs = [];
49
+ this._initSignatures = [];
50
+ this._signatures = [];
51
+ this._ttl = 0;
52
+ this._certs = [];
53
+ this._withdrawals = [];
54
+ this._multiAssets = [];
55
+ this.transaction = new transaction_1.Transaction(_coinConfig);
56
+ this._fee = cardano_serialization_lib_nodejs_1.BigNum.zero();
57
+ }
58
+ input(i) {
59
+ this._transactionInputs.push(i);
60
+ return this;
61
+ }
62
+ output(o) {
63
+ this._transactionOutputs.push(o);
64
+ return this;
65
+ }
66
+ assets(a) {
67
+ this._multiAssets.push(a);
68
+ return this;
69
+ }
70
+ ttl(t) {
71
+ this._ttl = t;
72
+ return this;
73
+ }
74
+ changeAddress(addr, totalInputBalance) {
75
+ this._changeAddress = addr;
76
+ this._senderBalance = totalInputBalance;
77
+ return this;
78
+ }
79
+ fee(fee) {
80
+ this._fee = cardano_serialization_lib_nodejs_1.BigNum.from_str(fee);
81
+ return this;
82
+ }
83
+ /**
84
+ * Initialize the transaction builder fields using the decoded transaction data
85
+ *
86
+ * @param {Transaction} tx the transaction data
87
+ */
88
+ initBuilder(tx) {
89
+ this._transaction = tx;
90
+ const txnBody = tx.transaction.body();
91
+ for (let i = 0; i < txnBody.inputs().len(); i++) {
92
+ const input = txnBody.inputs().get(i);
93
+ this.input({
94
+ transaction_id: Buffer.from(input.transaction_id().to_bytes()).toString('hex'),
95
+ transaction_index: input.index(),
96
+ });
97
+ }
98
+ for (let i = 0; i < txnBody.outputs().len(); i++) {
99
+ const output = txnBody.outputs().get(i);
100
+ this.output({
101
+ address: output.address().to_bech32(),
102
+ amount: output.amount().coin().to_str(),
103
+ multiAssets: output.amount().multiasset() || undefined,
104
+ });
105
+ }
106
+ if (txnBody.certs() !== undefined) {
107
+ const certs = txnBody.certs();
108
+ for (let i = 0; i < certs.len(); i++) {
109
+ this._certs.push(certs.get(i));
110
+ }
111
+ }
112
+ if (txnBody.withdrawals() !== undefined) {
113
+ const withdrawals = txnBody.withdrawals();
114
+ const keys = withdrawals.keys();
115
+ for (let i = 0; i < keys.len(); i++) {
116
+ const rewardAddress = keys.get(i);
117
+ const reward = withdrawals.get(rewardAddress);
118
+ this._withdrawals.push({ stakeAddress: rewardAddress.to_address().to_bech32(), value: reward.to_str() });
119
+ }
120
+ }
121
+ this._ttl = tx.transaction.body().ttl();
122
+ this._fee = tx.transaction.body().fee();
123
+ if (tx.transaction.witness_set().vkeys()) {
124
+ const vkeys = tx.transaction.witness_set().vkeys();
125
+ for (let i = 0; i < vkeys.len(); i++) {
126
+ const vkey = vkeys.get(i);
127
+ this._initSignatures.push({
128
+ publicKey: { pub: vkey.vkey().public_key().to_hex() },
129
+ signature: Buffer.from(vkey.signature().to_hex(), 'hex'),
130
+ });
131
+ }
132
+ }
133
+ }
134
+ /** @inheritdoc */
135
+ fromImplementation(rawTransaction) {
136
+ this.validateRawTransaction(rawTransaction);
137
+ this.buildImplementation();
138
+ return this.transaction;
139
+ }
140
+ /** @inheritdoc */
141
+ async buildImplementation() {
142
+ const inputs = CardanoWasm.TransactionInputs.new();
143
+ this._transactionInputs.forEach((input) => {
144
+ inputs.add(CardanoWasm.TransactionInput.new(CardanoWasm.TransactionHash.from_bytes(Buffer.from(input.transaction_id, 'hex')), input.transaction_index));
145
+ });
146
+ let outputs = CardanoWasm.TransactionOutputs.new();
147
+ let totalAmountToSend = CardanoWasm.BigNum.zero();
148
+ this._transactionOutputs.forEach((output) => {
149
+ const amount = CardanoWasm.BigNum.from_str(output.amount);
150
+ outputs.add(CardanoWasm.TransactionOutput.new(utils_1.default.getWalletAddress(output.address), CardanoWasm.Value.new(amount)));
151
+ totalAmountToSend = totalAmountToSend.checked_add(amount);
152
+ });
153
+ if (this._fee.is_zero()) {
154
+ // estimate fee
155
+ // add extra output for the change
156
+ if (this._changeAddress && this._senderBalance) {
157
+ const changeAddress = utils_1.default.getWalletAddress(this._changeAddress);
158
+ const utxoBalance = CardanoWasm.BigNum.from_str(this._senderBalance);
159
+ const adjustment = cardano_serialization_lib_nodejs_1.BigNum.from_str('2000000');
160
+ let change = utxoBalance.checked_sub(this._fee).checked_sub(totalAmountToSend);
161
+ if (this._type === sdk_core_1.TransactionType.StakingActivate) {
162
+ change = change.checked_sub(adjustment);
163
+ }
164
+ else if (this._type === sdk_core_1.TransactionType.StakingDeactivate) {
165
+ change = change.checked_add(adjustment);
166
+ }
167
+ else if (this._type === sdk_core_1.TransactionType.StakingWithdraw || this._type === sdk_core_1.TransactionType.StakingClaim) {
168
+ this._withdrawals.forEach((withdrawal) => {
169
+ change = change.checked_add(CardanoWasm.BigNum.from_str(withdrawal.value));
170
+ });
171
+ }
172
+ // If totalAmountToSend is 0, its consolidation
173
+ if (totalAmountToSend.to_str() == '0') {
174
+ // support for multi-asset consolidation
175
+ if (this._multiAssets !== undefined) {
176
+ const totalNumberOfAssets = CardanoWasm.BigNum.from_str(this._multiAssets.length.toString());
177
+ const minAmountNeededForOneAssetOutput = CardanoWasm.BigNum.from_str(utils_1.MIN_ADA_FOR_ONE_ASSET);
178
+ const minAmountNeededForTotalAssetOutputs = minAmountNeededForOneAssetOutput.checked_mul(totalNumberOfAssets);
179
+ if (!change.less_than(minAmountNeededForTotalAssetOutputs)) {
180
+ this._multiAssets.forEach((asset) => {
181
+ let txOutputBuilder = CardanoWasm.TransactionOutputBuilder.new();
182
+ // changeAddress is the root address, which is where we want the tokens assets to be sent to
183
+ const toAddress = utils_1.default.getWalletAddress(this._changeAddress);
184
+ txOutputBuilder = txOutputBuilder.with_address(toAddress);
185
+ let txOutputAmountBuilder = txOutputBuilder.next();
186
+ const assetName = CardanoWasm.AssetName.new(Buffer.from(asset.asset_name, 'hex'));
187
+ const policyId = CardanoWasm.ScriptHash.from_bytes(Buffer.from(asset.policy_id, 'hex'));
188
+ const multiAsset = CardanoWasm.MultiAsset.new();
189
+ const assets = CardanoWasm.Assets.new();
190
+ assets.insert(assetName, CardanoWasm.BigNum.from_str(asset.quantity));
191
+ multiAsset.insert(policyId, assets);
192
+ txOutputAmountBuilder = txOutputAmountBuilder.with_coin_and_asset(minAmountNeededForOneAssetOutput, multiAsset);
193
+ const txOutput = txOutputAmountBuilder.build();
194
+ outputs.add(txOutput);
195
+ });
196
+ // finally send the remaining ADA in its own output
197
+ const remainingOutputAmount = change.checked_sub(minAmountNeededForTotalAssetOutputs);
198
+ const changeOutput = CardanoWasm.TransactionOutput.new(changeAddress, CardanoWasm.Value.new(remainingOutputAmount));
199
+ outputs.add(changeOutput);
200
+ }
201
+ }
202
+ else {
203
+ // If there are no tokens to consolidate, you only have 1 output which is ADA alone
204
+ const changeOutput = CardanoWasm.TransactionOutput.new(changeAddress, CardanoWasm.Value.new(change));
205
+ outputs.add(changeOutput);
206
+ }
207
+ }
208
+ else {
209
+ // If this isn't a consolidate request, whatever change that needs to be sent back to the rootaddress is added as a separate output here
210
+ const changeOutput = CardanoWasm.TransactionOutput.new(changeAddress, CardanoWasm.Value.new(change));
211
+ outputs.add(changeOutput);
212
+ }
213
+ }
214
+ const txBody = CardanoWasm.TransactionBody.new_tx_body(inputs, outputs, this._fee);
215
+ txBody.set_ttl(CardanoWasm.BigNum.from_str(this._ttl.toString()));
216
+ const txHash = CardanoWasm.hash_transaction(txBody);
217
+ // we add witnesses once so that we can get the appropriate amount of signers for calculating the fee
218
+ const witnessSet = CardanoWasm.TransactionWitnessSet.new();
219
+ const vkeyWitnesses = CardanoWasm.Vkeywitnesses.new();
220
+ this._signers.forEach((keyPair) => {
221
+ const prv = keyPair.getKeys().prv;
222
+ const vkeyWitness = CardanoWasm.make_vkey_witness(txHash, CardanoWasm.PrivateKey.from_normal_bytes(Buffer.from(prv, 'hex')));
223
+ vkeyWitnesses.add(vkeyWitness);
224
+ });
225
+ this.getAllSignatures().forEach((signature) => {
226
+ const vkey = CardanoWasm.Vkey.new(CardanoWasm.PublicKey.from_bytes(Buffer.from(signature.publicKey.pub, 'hex')));
227
+ const ed255Sig = CardanoWasm.Ed25519Signature.from_bytes(signature.signature);
228
+ vkeyWitnesses.add(CardanoWasm.Vkeywitness.new(vkey, ed255Sig));
229
+ });
230
+ if (vkeyWitnesses.len() === 0) {
231
+ const prv = CardanoWasm.PrivateKey.generate_ed25519();
232
+ const vkeyWitness = CardanoWasm.make_vkey_witness(txHash, prv);
233
+ vkeyWitnesses.add(vkeyWitness);
234
+ if (this._type !== sdk_core_1.TransactionType.Send) {
235
+ vkeyWitnesses.add(vkeyWitness);
236
+ }
237
+ }
238
+ witnessSet.set_vkeys(vkeyWitnesses);
239
+ // add in withdrawal if this is a withdrawal tx
240
+ if (this._withdrawals.length > 0) {
241
+ const withdrawals = CardanoWasm.Withdrawals.new();
242
+ this._withdrawals.forEach((withdrawal) => {
243
+ const rewardAddress = CardanoWasm.RewardAddress.from_address(CardanoWasm.Address.from_bech32(withdrawal.stakeAddress));
244
+ withdrawals.insert(rewardAddress, CardanoWasm.BigNum.from_str(withdrawal.value));
245
+ });
246
+ txBody.set_withdrawals(withdrawals);
247
+ }
248
+ // add in certificates to get mock size
249
+ const draftCerts = CardanoWasm.Certificates.new();
250
+ for (const cert of this._certs) {
251
+ draftCerts.add(cert);
252
+ }
253
+ txBody.set_certs(draftCerts);
254
+ const txDraft = CardanoWasm.Transaction.new(txBody, witnessSet);
255
+ const linearFee = CardanoWasm.LinearFee.new(CardanoWasm.BigNum.from_str('44'), CardanoWasm.BigNum.from_str('155381'));
256
+ // calculate the fee based off our dummy transaction
257
+ const fee = CardanoWasm.min_fee(txDraft, linearFee).checked_add(cardano_serialization_lib_nodejs_1.BigNum.from_str('440'));
258
+ this._fee = fee;
259
+ }
260
+ this._transaction.fee(this._fee.to_str());
261
+ // now calculate the change based off of <utxoBalance> - <fee> - <amountToSend>
262
+ // reset the outputs collection because now our last output has changed
263
+ outputs = CardanoWasm.TransactionOutputs.new();
264
+ this._transactionOutputs.forEach((output) => {
265
+ if (output.multiAssets) {
266
+ const policyId = output.multiAssets.keys().get(0);
267
+ const assets = output.multiAssets.get(policyId);
268
+ const assetName = assets.keys().get(0);
269
+ const quantity = assets.get(assetName);
270
+ let txOutputBuilder = CardanoWasm.TransactionOutputBuilder.new();
271
+ const outputAmount = CardanoWasm.BigNum.from_str(output.amount);
272
+ const toAddress = utils_1.default.getWalletAddress(output.address);
273
+ txOutputBuilder = txOutputBuilder.with_address(toAddress);
274
+ let txOutputAmountBuilder = txOutputBuilder.next();
275
+ const multiAsset = CardanoWasm.MultiAsset.new();
276
+ const asset = CardanoWasm.Assets.new();
277
+ asset.insert(assetName, quantity);
278
+ multiAsset.insert(policyId, asset);
279
+ txOutputAmountBuilder = txOutputAmountBuilder.with_coin_and_asset(outputAmount, multiAsset);
280
+ const txOutput = txOutputAmountBuilder.build();
281
+ outputs.add(txOutput);
282
+ }
283
+ else {
284
+ outputs.add(CardanoWasm.TransactionOutput.new(utils_1.default.getWalletAddress(output.address), CardanoWasm.Value.new(CardanoWasm.BigNum.from_str(output.amount))));
285
+ }
286
+ });
287
+ if (this._changeAddress && this._senderBalance) {
288
+ const changeAddress = utils_1.default.getWalletAddress(this._changeAddress);
289
+ const utxoBalance = CardanoWasm.BigNum.from_str(this._senderBalance);
290
+ const adjustment = cardano_serialization_lib_nodejs_1.BigNum.from_str('2000000');
291
+ let change = utxoBalance.checked_sub(this._fee).checked_sub(totalAmountToSend);
292
+ if (this._type === sdk_core_1.TransactionType.StakingActivate) {
293
+ change = change.checked_sub(adjustment);
294
+ }
295
+ else if (this._type === sdk_core_1.TransactionType.StakingDeactivate) {
296
+ change = change.checked_add(adjustment);
297
+ }
298
+ else if (this._type === sdk_core_1.TransactionType.StakingWithdraw || this._type === sdk_core_1.TransactionType.StakingClaim) {
299
+ this._withdrawals.forEach((withdrawal) => {
300
+ change = change.checked_add(CardanoWasm.BigNum.from_str(withdrawal.value));
301
+ });
302
+ }
303
+ // If totalAmountToSend is 0, its consolidation
304
+ if (totalAmountToSend.to_str() == '0') {
305
+ // support for multi-asset consolidation
306
+ if (this._multiAssets !== undefined) {
307
+ const totalNumberOfAssets = CardanoWasm.BigNum.from_str(this._multiAssets.length.toString());
308
+ const minAmountNeededForOneAssetOutput = CardanoWasm.BigNum.from_str('1500000');
309
+ const minAmountNeededForTotalAssetOutputs = minAmountNeededForOneAssetOutput.checked_mul(totalNumberOfAssets);
310
+ if (!change.less_than(minAmountNeededForTotalAssetOutputs)) {
311
+ this._multiAssets.forEach((asset) => {
312
+ let txOutputBuilder = CardanoWasm.TransactionOutputBuilder.new();
313
+ // changeAddress is the root address, which is where we want the tokens assets to be sent to
314
+ const toAddress = utils_1.default.getWalletAddress(this._changeAddress);
315
+ txOutputBuilder = txOutputBuilder.with_address(toAddress);
316
+ let txOutputAmountBuilder = txOutputBuilder.next();
317
+ const assetName = CardanoWasm.AssetName.new(Buffer.from(asset.asset_name, 'hex'));
318
+ const policyId = CardanoWasm.ScriptHash.from_bytes(Buffer.from(asset.policy_id, 'hex'));
319
+ const multiAsset = CardanoWasm.MultiAsset.new();
320
+ const assets = CardanoWasm.Assets.new();
321
+ assets.insert(assetName, CardanoWasm.BigNum.from_str(asset.quantity));
322
+ multiAsset.insert(policyId, assets);
323
+ txOutputAmountBuilder = txOutputAmountBuilder.with_coin_and_asset(minAmountNeededForOneAssetOutput, multiAsset);
324
+ const txOutput = txOutputAmountBuilder.build();
325
+ outputs.add(txOutput);
326
+ });
327
+ // finally send the remaining ADA in its own output
328
+ const remainingOutputAmount = change.checked_sub(minAmountNeededForTotalAssetOutputs);
329
+ const changeOutput = CardanoWasm.TransactionOutput.new(changeAddress, CardanoWasm.Value.new(remainingOutputAmount));
330
+ outputs.add(changeOutput);
331
+ }
332
+ else {
333
+ throw new sdk_core_1.BuildTransactionError('Insufficient funds: need a minimum of 1.5 ADA per output to construct token consolidation');
334
+ }
335
+ }
336
+ else {
337
+ // If there are no tokens to consolidate, you only have 1 output which is ADA alone
338
+ const changeOutput = CardanoWasm.TransactionOutput.new(changeAddress, CardanoWasm.Value.new(change));
339
+ outputs.add(changeOutput);
340
+ }
341
+ }
342
+ else {
343
+ // If this isn't a consolidate request, whatever change that needs to be sent back to the rootaddress is added as a separate output here
344
+ const changeOutput = CardanoWasm.TransactionOutput.new(changeAddress, CardanoWasm.Value.new(change));
345
+ outputs.add(changeOutput);
346
+ }
347
+ }
348
+ const txRaw = CardanoWasm.TransactionBody.new_tx_body(inputs, outputs, this._fee);
349
+ const certs = CardanoWasm.Certificates.new();
350
+ for (const cert of this._certs) {
351
+ certs.add(cert);
352
+ }
353
+ txRaw.set_certs(certs);
354
+ // add in withdrawal if this is a withdrawal tx
355
+ if (this._withdrawals.length > 0) {
356
+ const withdrawals = CardanoWasm.Withdrawals.new();
357
+ this._withdrawals.forEach((withdrawal) => {
358
+ const rewardAddress = CardanoWasm.RewardAddress.from_address(CardanoWasm.Address.from_bech32(withdrawal.stakeAddress));
359
+ withdrawals.insert(rewardAddress, CardanoWasm.BigNum.from_str(withdrawal.value));
360
+ });
361
+ txRaw.set_withdrawals(withdrawals);
362
+ }
363
+ txRaw.set_ttl(CardanoWasm.BigNum.from_str(this._ttl.toString()));
364
+ const txRawHash = CardanoWasm.hash_transaction(txRaw);
365
+ // now add the witnesses again this time for real. We need to do this again
366
+ // because now that we've added our real fee and change output, we have a difference transaction hash
367
+ const witnessSet = CardanoWasm.TransactionWitnessSet.new();
368
+ const vkeyWitnesses = CardanoWasm.Vkeywitnesses.new();
369
+ this._signers.forEach((keyPair) => {
370
+ const prv = keyPair.getKeys().prv;
371
+ const vkeyWitness = CardanoWasm.make_vkey_witness(txRawHash, CardanoWasm.PrivateKey.from_normal_bytes(Buffer.from(prv, 'hex')));
372
+ vkeyWitnesses.add(vkeyWitness);
373
+ });
374
+ // Clear the cosmetic signature array in native txn wrapper to prevent duplicate when builder is inited from a partially witnessed txn
375
+ this._transaction.signature.length = 0;
376
+ this.getAllSignatures().forEach((signature) => {
377
+ const vkey = CardanoWasm.Vkey.new(CardanoWasm.PublicKey.from_bytes(Buffer.from(signature.publicKey.pub, 'hex')));
378
+ const ed255Sig = CardanoWasm.Ed25519Signature.from_bytes(signature.signature);
379
+ vkeyWitnesses.add(CardanoWasm.Vkeywitness.new(vkey, ed255Sig));
380
+ this._transaction.signature.push(signature.signature.toString('hex'));
381
+ });
382
+ witnessSet.set_vkeys(vkeyWitnesses);
383
+ this._transaction.transaction = CardanoWasm.Transaction.new(txRaw, witnessSet);
384
+ return this.transaction;
385
+ }
386
+ /** @inheritdoc */
387
+ signImplementation(key) {
388
+ this._signers.push(new keyPair_1.KeyPair({ prv: key.key }));
389
+ return this._transaction;
390
+ }
391
+ /** @inheritdoc */
392
+ get transaction() {
393
+ return this._transaction;
394
+ }
395
+ /** @inheritdoc */
396
+ set transaction(transaction) {
397
+ this._transaction = transaction;
398
+ }
399
+ /** @inheritdoc */
400
+ validateAddress(address, addressFormat) {
401
+ if (!utils_1.default.isValidAddress(address.address)) {
402
+ throw new sdk_core_1.UtilsError('invalid address ' + address.address);
403
+ }
404
+ }
405
+ /** @inheritdoc */
406
+ validateKey(key) {
407
+ try {
408
+ new keyPair_1.KeyPair({ prv: key.key });
409
+ }
410
+ catch {
411
+ throw new sdk_core_1.BuildTransactionError(`Key validation failed`);
412
+ }
413
+ }
414
+ /** @inheritdoc */
415
+ validateRawTransaction(rawTransaction) {
416
+ try {
417
+ CardanoWasm.Transaction.from_bytes(rawTransaction);
418
+ }
419
+ catch {
420
+ throw new sdk_core_1.BuildTransactionError('invalid raw transaction');
421
+ }
422
+ }
423
+ /** @inheritdoc */
424
+ validateTransaction(transaction) {
425
+ if (!transaction.transaction) {
426
+ return;
427
+ }
428
+ }
429
+ /** @inheritdoc */
430
+ validateValue(value) {
431
+ if (value.isLessThan(0)) {
432
+ throw new sdk_core_1.BuildTransactionError('Value cannot be less than zero');
433
+ }
434
+ }
435
+ // endregion
436
+ /** @inheritDoc */
437
+ addSignature(publicKey, signature) {
438
+ this._signatures.push({ publicKey, signature });
439
+ }
440
+ getAllSignatures() {
441
+ return this._initSignatures.concat(this._signatures);
442
+ }
443
+ }
444
+ exports.TransactionBuilder = TransactionBuilder;
445
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhbnNhY3Rpb25CdWlsZGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2xpYi90cmFuc2FjdGlvbkJ1aWxkZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBRUEsbURBUzhCO0FBQzlCLCtDQUFvRztBQUNwRyx1Q0FBb0M7QUFDcEMsaURBQXNEO0FBQ3RELHNGQUF3RTtBQUN4RSwrRkFBa0U7QUFFbEUsTUFBc0Isa0JBQW1CLFNBQVEsaUNBQXNCO0lBZ0JyRSxZQUFZLFdBQWlDO1FBQzNDLEtBQUssQ0FBQyxXQUFXLENBQUMsQ0FBQztRQWZYLGFBQVEsR0FBYyxFQUFFLENBQUM7UUFDekIsdUJBQWtCLEdBQXVCLEVBQUUsQ0FBQztRQUM1Qyx3QkFBbUIsR0FBd0IsRUFBRSxDQUFDO1FBQzlDLG9CQUFlLEdBQWdCLEVBQUUsQ0FBQztRQUNsQyxnQkFBVyxHQUFnQixFQUFFLENBQUM7UUFHOUIsU0FBSSxHQUFHLENBQUMsQ0FBQztRQUNULFdBQU0sR0FBOEIsRUFBRSxDQUFDO1FBQ3ZDLGlCQUFZLEdBQWlCLEVBQUUsQ0FBQztRQUVoQyxpQkFBWSxHQUFZLEVBQUUsQ0FBQztRQUtuQyxJQUFJLENBQUMsV0FBVyxHQUFHLElBQUkseUJBQVcsQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUNoRCxJQUFJLENBQUMsSUFBSSxHQUFHLHlDQUFNLENBQUMsSUFBSSxFQUFFLENBQUM7SUFDNUIsQ0FBQztJQUVELEtBQUssQ0FBQyxDQUFtQjtRQUN2QixJQUFJLENBQUMsa0JBQWtCLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ2hDLE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQztJQUVELE1BQU0sQ0FBQyxDQUFvQjtRQUN6QixJQUFJLENBQUMsbUJBQW1CLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ2pDLE9BQU8sSUFBSSxDQUFDO0lBQ2Qs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LENBQUM7WUFDeEIsTUFBTSxJQUFJLGdDQUFxQixDQUFDLGdDQUFnQyxDQUFDLENBQUM7UUFDcEUsQ0FBQztJQUNILENBQUM7SUFDRCxZQUFZO0lBRVosa0JBQWtCO0lBQ2xCLFlBQVksQ0FBQyxTQUF3QixFQUFFLFNBQWlCO1FBQ3RELElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLEVBQUUsU0FBUyxFQUFFLFNBQVMsRUFBRSxDQUFDLENBQUM7SUFDbEQsQ0FBQztJQUVPLGdCQUFnQjtRQUN0QixPQUFPLElBQUksQ0FBQyxlQUFlLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQztJQUN2RCxDQUFDO0NBQ0Y7QUF0ZUQsZ0RBc2VDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IEJpZ051bWJlciBmcm9tICdiaWdudW1iZXIuanMnO1xuaW1wb3J0IHsgQmFzZUNvaW4gYXMgQ29pbkNvbmZpZyB9IGZyb20gJ0BiaXRnby1iZXRhL3N0YXRpY3MnO1xuaW1wb3J0IHtcbiAgQmFzZUFkZHJlc3MsXG4gIEJhc2VLZXksXG4gIEJhc2VUcmFuc2FjdGlvbkJ1aWxkZXIsXG4gIEJ1aWxkVHJhbnNhY3Rpb25FcnJvcixcbiAgUHVibGljS2V5IGFzIEJhc2VQdWJsaWNLZXksXG4gIFNpZ25hdHVyZSxcbiAgVHJhbnNhY3Rpb25UeXBlLFxuICBVdGlsc0Vycm9yLFxufSBmcm9tICdAYml0Z28tYmV0YS9zZGstY29yZSc7XG5pbXBvcnQgeyBBc3NldCwgVHJhbnNhY3Rpb24sIFRyYW5zYWN0aW9uSW5wdXQsIFRyYW5zYWN0aW9uT3V0cHV0LCBXaXRoZHJhd2FsIH0gZnJvbSAnLi90cmFuc2FjdGlvbic7XG5pbXBvcnQgeyBLZXlQYWlyIH0gZnJvbSAnLi9rZXlQYWlyJztcbmltcG9ydCB1dGlsLCB7IE1JTl9BREFfRk9SX09ORV9BU1NFVCB9IGZyb20gJy4vdXRpbHMnO1xuaW1wb3J0ICogYXMgQ2FyZGFub1dhc20gZnJvbSAnQGVtdXJnby9jYXJkYW5vLXNlcmlhbGl6YXRpb24tbGliLW5vZGVqcyc7XG5pbXBvcnQgeyBCaWdOdW0gfSBmcm9tICdAZW11cmdvL2NhcmRhbm8tc2VyaWFsaXphdGlvbi1saWItbm9kZWpzJztcblxuZXhwb3J0IGFic3RyYWN0IGNsYXNzIFRyYW5zYWN0aW9uQnVpbGRlciBleHRlbmRzIEJhc2VUcmFuc2FjdGlvbkJ1aWxkZXIge1xuICBwcm90ZWN0ZWQgX3RyYW5zYWN0aW9uITogVHJhbnNhY3Rpb247XG4gIHByb3RlY3RlZCBfc2lnbmVyczogS2V5UGFpcltdID0gW107XG4gIHByb3RlY3RlZCBfdHJhbnNhY3Rpb25JbnB1dHM6IFRyYW5zYWN0aW9uSW5wdXRbXSA9IFtdO1xuICBwcm90ZWN0ZWQgX3RyYW5zYWN0aW9uT3V0cHV0czogVHJhbnNhY3Rpb25PdXRwdXRbXSA9IFtdO1xuICBwcm90ZWN0ZWQgX2luaXRTaWduYXR1cmVzOiBTaWduYXR1cmVbXSA9IFtdO1xuICBwcm90ZWN0ZWQgX3NpZ25hdHVyZXM6IFNpZ25hdHVyZVtdID0gW107XG4gIHByb3RlY3RlZCBfY2hhbmdlQWRkcmVzczogc3RyaW5nO1xuICBwcm90ZWN0ZWQgX3NlbmRlckJhbGFuY2U6IHN0cmluZztcbiAgcHJvdGVjdGVkIF90dGwgPSAwO1xuICBwcm90ZWN0ZWQgX2NlcnRzOiBDYXJkYW5vV2FzbS5DZXJ0aWZpY2F0ZVtdID0gW107XG4gIHByb3RlY3RlZCBfd2l0aGRyYXdhbHM6IFdpdGhkcmF3YWxbXSA9IFtdO1xuICBwcm90ZWN0ZWQgX3R5cGU6IFRyYW5zYWN0aW9uVHlwZTtcbiAgcHJvdGVjdGVkIF9tdWx0aUFzc2V0czogQXNzZXRbXSA9IFtdO1xuICBwcml2YXRlIF9mZWU6IEJpZ051bTtcblxuICBjb25zdHJ1Y3RvcihfY29pbkNvbmZpZzogUmVhZG9ubHk8Q29pbkNvbmZpZz4pIHtcbiAgICBzdXBlcihfY29pbkNvbmZpZyk7XG4gICAgdGhpcy50cmFuc2FjdGlvbiA9IG5ldyBUcmFuc2FjdGlvbihfY29pbkNvbmZpZyk7XG4gICAgdGhpcy5fZmVlID0gQmlnTnVtLnplcm8oKTtcbiAgfVxuXG4gIGlucHV0KGk6IFRyYW5zYWN0aW9uSW5wdXQpOiB0aGlzIHtcbiAgICB0aGlzLl90cmFuc2FjdGlvbklucHV0cy5wdXNoKGkpO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgb3V0cHV0KG86IFRyYW5zYWN0aW9uT3V0cHV0KTogdGhpcyB7XG4gICAgdGhpcy5fdHJhbnNhY3Rpb25PdXRwdXRzLnB1c2gobyk7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICBhc3NldHMoYTogQXNzZXQpOiB0aGlzIHtcbiAgICB0aGlzLl9tdWx0aUFzc2V0cy5wdXNoKGEpO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgdHRsKHQ6IG51bWJlcik6IHRoaXMge1xuICAgIHRoaXMuX3R0bCA9IHQ7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICBjaGFuZ2VBZGRyZXNzKGFkZHI6IHN0cmluZywgdG90YWxJbnB1dEJhbGFuY2U6IHN0cmluZyk6IHRoaXMge1xuICAgIHRoaXMuX2NoYW5nZUFkZHJlc3MgPSBhZGRyO1xuICAgIHRoaXMuX3NlbmRlckJhbGFuY2UgPSB0b3RhbElucHV0QmFsYW5jZTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIGZlZShmZWU6IHN0cmluZyk6IHRoaXMge1xuICAgIHRoaXMuX2ZlZSA9IEJpZ051bS5mcm9tX3N0cihmZWUpO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIEluaXRpYWxpemUgdGhlIHRyYW5zYWN0aW9uIGJ1aWxkZXIgZmllbGRzIHVzaW5nIHRoZSBkZWNvZGVkIHRyYW5zYWN0aW9uIGRhdGFcbiAgICpcbiAgICogQHBhcmFtIHtUcmFuc2FjdGlvbn0gdHggdGhlIHRyYW5zYWN0aW9uIGRhdGFcbiAgICovXG4gIGluaXRCdWlsZGVyKHR4OiBUcmFuc2FjdGlvbik6IHZvaWQge1xuICAgIHRoaXMuX3RyYW5zYWN0aW9uID0gdHg7XG4gICAgY29uc3QgdHhuQm9keSA9IHR4LnRyYW5zYWN0aW9uLmJvZHkoKTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHR4bkJvZHkuaW5wdXRzKCkubGVuKCk7IGkrKykge1xuICAgICAgY29uc3QgaW5wdXQgPSB0eG5Cb2R5LmlucHV0cygpLmdldChpKTtcbiAgICAgIHRoaXMuaW5wdXQoe1xuICAgICAgICB0cmFuc2FjdGlvbl9pZDogQnVmZmVyLmZyb20oaW5wdXQudHJhbnNhY3Rpb25faWQoKS50b19ieXRlcygpKS50b1N0cmluZygnaGV4JyksXG4gICAgICAgIHRyYW5zYWN0aW9uX2luZGV4OiBpbnB1dC5pbmRleCgpLFxuICAgICAgfSk7XG4gICAgfVxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdHhuQm9keS5vdXRwdXRzKCkubGVuKCk7IGkrKykge1xuICAgICAgY29uc3Qgb3V0cHV0ID0gdHhuQm9keS5vdXRwdXRzKCkuZ2V0KGkpO1xuICAgICAgdGhpcy5vdXRwdXQoe1xuICAgICAgICBhZGRyZXNzOiBvdXRwdXQuYWRkcmVzcygpLnRvX2JlY2gzMigpLFxuICAgICAgICBhbW91bnQ6IG91dHB1dC5hbW91bnQoKS5jb2luKCkudG9fc3RyKCksXG4gICAgICAgIG11bHRpQXNzZXRzOiBvdXRwdXQuYW1vdW50KCkubXVsdGlhc3NldCgpIHx8IHVuZGVmaW5lZCxcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGlmICh0eG5Cb2R5LmNlcnRzKCkgIT09IHVuZGVmaW5lZCkge1xuICAgICAgY29uc3QgY2VydHMgPSB0eG5Cb2R5LmNlcnRzKCkgYXMgQ2FyZGFub1dhc20uQ2VydGlmaWNhdGVzO1xuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBjZXJ0cy5sZW4oKTsgaSsrKSB7XG4gICAgICAgIHRoaXMuX2NlcnRzLnB1c2goY2VydHMuZ2V0KGkpKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAodHhuQm9keS53aXRoZHJhd2FscygpICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIGNvbnN0IHdpdGhkcmF3YWxzID0gdHhuQm9keS53aXRoZHJhd2FscygpIGFzIENhcmRhbm9XYXNtLldpdGhkcmF3YWxzO1xuICAgICAgY29uc3Qga2V5cyA9IHdpdGhkcmF3YWxzLmtleXMoKTtcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwga2V5cy5sZW4oKTsgaSsrKSB7XG4gICAgICAgIGNvbnN0IHJld2FyZEFkZHJlc3MgPSBrZXlzLmdldChpKSBhcyBDYXJkYW5vV2FzbS5SZXdhcmRBZGRyZXNzO1xuICAgICAgICBjb25zdCByZXdhcmQgPSB3aXRoZHJhd2Fscy5nZXQocmV3YXJkQWRkcmVzcykgYXMgQ2FyZGFub1dhc20uQmlnTnVtO1xuICAgICAgICB0aGlzLl93aXRoZHJhd2Fscy5wdXNoKHsgc3Rha2VBZGRyZXNzOiByZXdhcmRBZGRyZXNzLnRvX2FkZHJlc3MoKS50b19iZWNoMzIoKSwgdmFsdWU6IHJld2FyZC50b19zdHIoKSB9KTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aGlzLl90dGwgPSB0eC50cmFuc2FjdGlvbi5ib2R5KCkudHRsKCkgYXMgbnVtYmVyO1xuICAgIHRoaXMuX2ZlZSA9IHR4LnRyYW5zYWN0aW9uLmJvZHkoKS5mZWUoKTtcblxuICAgIGlmICh0eC50cmFuc2FjdGlvbi53aXRuZXNzX3NldCgpLnZrZXlzKCkpIHtcbiAgICAgIGNvbnN0IHZrZXlzID0gdHgudHJhbnNhY3Rpb24ud2l0bmVzc19zZXQoKS52a2V5cygpISBhcyBDYXJkYW5vV2FzbS5Wa2V5d2l0bmVzc2VzO1xuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB2a2V5cy5sZW4oKTsgaSsrKSB7XG4gICAgICAgIGNvbnN0IHZrZXkgPSB2a2V5cy5nZXQoaSk7XG4gICAgICAgIHRoaXMuX2luaXRTaWduYXR1cmVzLnB1c2goe1xuICAgICAgICAgIHB1YmxpY0tleTogeyBwdWI6IHZrZXkudmtleSgpLnB1YmxpY19rZXkoKS50b19oZXgoKSB9LFxuICAgICAgICAgIHNpZ25hdHVyZTogQnVmZmVyLmZyb20odmtleS5zaWduYXR1cmUoKS50b19oZXgoKSwgJ2hleCcpLFxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKiogQGluaGVyaXRkb2MgKi9cbiAgcHJvdGVjdGVkIGZyb21JbXBsZW1lbnRhdGlvbihyYXdUcmFuc2FjdGlvbjogc3RyaW5nKTogVHJhbnNhY3Rpb24ge1xuICAgIHRoaXMudmFsaWRhdGVSYXdUcmFuc2FjdGlvbihyYXdUcmFuc2FjdGlvbik7XG4gICAgdGhpcy5idWlsZEltcGxlbWVudGF0aW9uKCk7XG4gICAgcmV0dXJuIHRoaXMudHJhbnNhY3Rpb247XG4gIH1cblxuICAvKiogQGluaGVyaXRkb2MgKi9cbiAgcHJvdGVjdGVkIGFzeW5jIGJ1aWxkSW1wbGVtZW50YXRpb24oKTogUHJvbWlzZTxUcmFuc2FjdGlvbj4ge1xuICAgIGNvbnN0IGlucHV0cyA9IENhcmRhbm9XYXNtLlRyYW5zYWN0aW9uSW5wdXRzLm5ldygpO1xuICAgIHRoaXMuX3RyYW5zYWN0aW9uSW5wdXRzLmZvckVhY2goKGlucHV0KSA9PiB7XG4gICAgICBpbnB1dHMuYWRkKFxuICAgICAgICBDYXJkYW5vV2FzbS5UcmFuc2FjdGlvbklucHV0Lm5ldyhcbiAgICAgICAgICBDYXJkYW5vV2FzbS5UcmFuc2FjdGlvbkhhc2guZnJvbV9ieXRlcyhCdWZmZXIuZnJvbShpbnB1dC50cmFuc2FjdGlvbl9pZCwgJ2hleCcpKSxcbiAgICAgICAgICBpbnB1dC50cmFuc2FjdGlvbl9pbmRleFxuICAgICAgICApXG4gICAgICApO1xuICAgIH0pO1xuICAgIGxldCBvdXRwdXRzID0gQ2FyZGFub1dhc20uVHJhbnNhY3Rpb25PdXRwdXRzLm5ldygpO1xuICAgIGxldCB0b3RhbEFtb3VudFRvU2VuZCA9IENhcmRhbm9XYXNtLkJpZ051bS56ZXJvKCk7XG4gICAgdGhpcy5fdHJhbnNhY3Rpb25PdXRwdXRzLmZvckVhY2goKG91dHB1dCkgPT4ge1xuICAgICAgY29uc3QgYW1vdW50ID0gQ2FyZGFub1dhc20uQmlnTnVtLmZyb21fc3RyKG91dHB1dC5hbW91bnQpO1xuICAgICAgb3V0cHV0cy5hZGQoXG4gICAgICAgIENhcmRhbm9XYXNtLlRyYW5zYWN0aW9uT3V0cHV0Lm5ldyh1dGlsLmdldFdhbGxldEFkZHJlc3Mob3V0cHV0LmFkZHJlc3MpLCBDYXJkYW5vV2FzbS5WYWx1ZS5uZXcoYW1vdW50KSlcbiAgICAgICk7XG4gICAgICB0b3RhbEFtb3VudFRvU2VuZCA9IHRvdGFsQW1vdW50VG9TZW5kLmNoZWNrZWRfYWRkKGFtb3VudCk7XG4gICAgfSk7XG5cbiAgICBpZiAodGhpcy5fZmVlLmlzX3plcm8oKSkge1xuICAgICAgLy8gZXN0aW1hdGUgZmVlXG4gICAgICAvLyBhZGQgZXh0cmEgb3V0cHV0IGZvciB0aGUgY2hhbmdlXG4gICAgICBpZiAodGhpcy5fY2hhbmdlQWRkcmVzcyAmJiB0aGlzLl9zZW5kZXJCYWxhbmNlKSB7XG4gICAgICAgIGNvbnN0IGNoYW5nZUFkZHJlc3MgPSB1dGlsLmdldFdhbGxldEFkZHJlc3ModGhpcy5fY2hhbmdlQWRkcmVzcyk7XG4gICAgICAgIGNvbnN0IHV0eG9CYWxhbmNlID0gQ2FyZGFub1dhc20uQmlnTnVtLmZyb21fc3RyKHRoaXMuX3NlbmRlckJhbGFuY2UpO1xuXG4gICAgICAgIGNvbnN0IGFkanVzdG1lbnQgPSBCaWdOdW0uZnJvbV9zdHIoJzIwMDAwMDAnKTtcbiAgICAgICAgbGV0IGNoYW5nZSA9IHV0eG9CYWxhbmNlLmNoZWNrZWRfc3ViKHRoaXMuX2ZlZSkuY2hlY2tlZF9zdWIodG90YWxBbW91bnRUb1NlbmQpO1xuICAgICAgICBpZiAodGhpcy5fdHlwZSA9PT0gVHJhbnNhY3Rpb25UeXBlLlN0YWtpbmdBY3RpdmF0ZSkge1xuICAgICAgICAgIGNoYW5nZSA9IGNoYW5nZS5jaGVja2VkX3N1YihhZGp1c3RtZW50KTtcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLl90eXBlID09PSBUcmFuc2FjdGlvblR5cGUuU3Rha2luZ0RlYWN0aXZhdGUpIHtcbiAgICAgICAgICBjaGFuZ2UgPSBjaGFuZ2UuY2hlY2tlZF9hZGQoYWRqdXN0bWVudCk7XG4gICAgICAgIH0gZWxzZSBpZiAodGhpcy5fdHlwZSA9PT0gVHJhbnNhY3Rpb25UeXBlLlN0YWtpbmdXaXRoZHJhdyB8fCB0aGlzLl90eXBlID09PSBUcmFuc2FjdGlvblR5cGUuU3Rha2luZ0NsYWltKSB7XG4gICAgICAgICAgdGhpcy5fd2l0aGRyYXdhbHMuZm9yRWFjaCgod2l0aGRyYXdhbDogV2l0aGRyYXdhbCkgPT4ge1xuICAgICAgICAgICAgY2hhbmdlID0gY2hhbmdlLmNoZWNrZWRfYWRkKENhcmRhbm9XYXNtLkJpZ051bS5mcm9tX3N0cih3aXRoZHJhd2FsLnZhbHVlKSk7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBJZiB0b3RhbEFtb3VudFRvU2VuZCBpcyAwLCBpdHMgY29uc29saWRhdGlvblxuICAgICAgICBpZiAodG90YWxBbW91bnRUb1NlbmQudG9fc3RyKCkgPT0gJzAnKSB7XG4gICAgICAgICAgLy8gc3VwcG9ydCBmb3IgbXVsdGktYXNzZXQgY29uc29saWRhdGlvblxuICAgICAgICAgIGlmICh0aGlzLl9tdWx0aUFzc2V0cyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICBjb25zdCB0b3RhbE51bWJlck9mQXNzZXRzID0gQ2FyZGFub1dhc20uQmlnTnVtLmZyb21fc3RyKHRoaXMuX211bHRpQXNzZXRzLmxlbmd0aC50b1N0cmluZygpKTtcbiAgICAgICAgICAgIGNvbnN0IG1pbkFtb3VudE5lZWRlZEZvck9uZUFzc2V0T3V0cHV0ID0gQ2FyZGFub1dhc20uQmlnTnVtLmZyb21fc3RyKE1JTl9BREFfRk9SX09ORV9BU1NFVCk7XG4gICAgICAgICAgICBjb25zdCBtaW5BbW91bnROZWVkZWRGb3JUb3RhbEFzc2V0T3V0cHV0cyA9XG4gICAgICAgICAgICAgIG1pbkFtb3VudE5lZWRlZEZvck9uZUFzc2V0T3V0cHV0LmNoZWNrZWRfbXVsKHRvdGFsTnVtYmVyT2ZBc3NldHMpO1xuXG4gICAgICAgICAgICBpZiAoIWNoYW5nZS5sZXNzX3RoYW4obWluQW1vdW50TmVlZGVkRm9yVG90YWxBc3NldE91dHB1dHMpKSB7XG4gICAgICAgICAgICAgIHRoaXMuX211bHRpQXNzZXRzLmZvckVhY2goKGFzc2V0KSA9PiB7XG4gICAgICAgICAgICAgICAgbGV0IHR4T3V0cHV0QnVpbGRlciA9IENhcmRhbm9XYXNtLlRyYW5zYWN0aW9uT3V0cHV0QnVpbGRlci5uZXcoKTtcbiAgICAgICAgICAgICAgICAvLyBjaGFuZ2VBZGRyZXNzIGlzIHRoZSByb290IGFkZHJlc3MsIHdoaWNoIGlzIHdoZXJlIHdlIHdhbnQgdGhlIHRva2VucyBhc3NldHMgdG8gYmUgc2VudCB0b1xuICAgICAgICAgICAgICAgIGNvbnN0IHRvQWRkcmVzcyA9IHV0aWwuZ2V0V2FsbGV0QWRkcmVzcyh0aGlzLl9jaGFuZ2VBZGRyZXNzKTtcbiAgICAgICAgICAgICAgICB0eE91dHB1dEJ1aWxkZXIgPSB0eE91dHB1dEJ1aWxkZXIud2l0aF9hZGRyZXNzKHRvQWRkcmVzcyk7XG4gICAgICAgICAgICAgICAgbGV0IHR4T3V0cHV0QW1vdW50QnVpbGRlciA9IHR4T3V0cHV0QnVpbGRlci5uZXh0KCk7XG4gICAgICAgICAgICAgICAgY29uc3QgYXNzZXROYW1lID0gQ2FyZGFub1dhc20uQXNzZXROYW1lLm5ldyhCdWZmZXIuZnJvbShhc3NldC5hc3NldF9uYW1lLCAnaGV4JykpO1xuICAgICAgICAgICAgICAgIGNvbnN0IHBvbGljeUlkID0gQ2FyZGFub1dhc20uU2NyaXB0SGFzaC5mcm9tX2J5dGVzKEJ1ZmZlci5mcm9tKGFzc2V0LnBvbGljeV9pZCwgJ2hleCcpKTtcbiAgICAgICAgICAgICAgICBjb25zdCBtdWx0aUFzc2V0ID0gQ2FyZGFub1dhc20uTXVsdGlBc3NldC5uZXcoKTtcbiAgICAgICAgICAgICAgICBjb25zdCBhc3NldHMgPSBDYXJkYW5vV2FzbS5Bc3NldHMubmV3KCk7XG4gICAgICAgICAgICAgICAgYXNzZXRzLmluc2VydChhc3NldE5hbWUsIENhcmRhbm9XYXNtLkJpZ051bS5mcm9tX3N0cihhc3NldC5xdWFudGl0eSkpO1xuICAgICAgICAgICAgICAgIG11bHRpQXNzZXQuaW5zZXJ0KHBvbGljeUlkLCBhc3NldHMpO1xuXG4gICAgICAgICAgICAgICAgdHhPdXRwdXRBbW91bnRCdWlsZGVyID0gdHhPdXRwdXRBbW91bnRCdWlsZGVyLndpdGhfY29pbl9hbmRfYXNzZXQoXG4gICAgICAgICAgICAgICAgICBtaW5BbW91bnROZWVkZWRGb3JPbmVBc3NldE91dHB1dCxcbiAgICAgICAgICAgICAgICAgIG11bHRpQXNzZXRcbiAgICAgICAgICAgICAgICApO1xuXG4gICAgICAgICAgICAgICAgY29uc3QgdHhPdXRwdXQgPSB0eE91dHB1dEFtb3VudEJ1aWxkZXIuYnVpbGQoKTtcbiAgICAgICAgICAgICAgICBvdXRwdXRzLmFkZCh0eE91dHB1dCk7XG4gICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgIC8vIGZpbmFsbHkgc2VuZCB0aGUgcmVtYWluaW5nIEFEQSBpbiBpdHMgb3duIG91dHB1dFxuICAgICAgICAgICAgICBjb25zdCByZW1haW5pbmdPdXRwdXRBbW91bnQgPSBjaGFuZ2UuY2hlY2tlZF9zdWIobWluQW1vdW50TmVlZGVkRm9yVG90YWxBc3NldE91dHB1dHMpO1xuICAgICAgICAgICAgICBjb25zdCBjaGFuZ2VPdXRwdXQgPSBDYXJkYW5vV2FzbS5UcmFuc2FjdGlvbk91dHB1dC5uZXcoXG4gICAgICAgICAgICAgICAgY2hhbmdlQWRkcmVzcyxcbiAgICAgICAgICAgICAgICBDYXJkYW5vV2FzbS5WYWx1ZS5uZXcocmVtYWluaW5nT3V0cHV0QW1vdW50KVxuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICBvdXRwdXRzLmFkZChjaGFuZ2VPdXRwdXQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBJZiB0aGVyZSBhcmUgbm8gdG9rZW5zIHRvIGNvbnNvbGlkYXRlLCB5b3Ugb25seSBoYXZlIDEgb3V0cHV0IHdoaWNoIGlzIEFEQSBhbG9uZVxuICAgICAgICAgICAgY29uc3QgY2hhbmdlT3V0cHV0ID0gQ2FyZGFub1dhc20uVHJhbnNhY3Rpb25PdXRwdXQubmV3KGNoYW5nZUFkZHJlc3MsIENhcmRhbm9XYXNtLlZhbHVlLm5ldyhjaGFuZ2UpKTtcbiAgICAgICAgICAgIG91dHB1dHMuYWRkKGNoYW5nZU91dHB1dCk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIC8vIElmIHRoaXMgaXNuJ3QgYSBjb25zb2xpZGF0ZSByZXF1ZXN0LCB3aGF0ZXZlciBjaGFuZ2UgdGhhdCBuZWVkcyB0byBiZSBzZW50IGJhY2sgdG8gdGhlIHJvb3RhZGRyZXNzIGlzIGFkZGVkIGFzIGEgc2VwYXJhdGUgb3V0cHV0IGhlcmVcbiAgICAgICAgICBjb25zdCBjaGFuZ2VPdXRwdXQgPSBDYXJkYW5vV2FzbS5UcmFuc2FjdGlvbk91dHB1dC5uZXcoY2hhbmdlQWRkcmVzcywgQ2FyZGFub1dhc20uVmFsdWUubmV3KGNoYW5nZSkpO1xuICAgICAgICAgIG91dHB1dHMuYWRkKGNoYW5nZU91dHB1dCk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgY29uc3QgdHhCb2R5ID0gQ2FyZGFub1dhc20uVHJhbnNhY3Rpb25Cb2R5Lm5ld190eF9ib2R5KGlucHV0cywgb3V0cHV0cywgdGhpcy5fZmVlKTtcbiAgICAgIHR4Qm9keS5zZXRfdHRsKENhcmRhbm9XYXNtLkJpZ051bS5mcm9tX3N0cih0aGlzLl90dGwudG9TdHJpbmcoKSkpO1xuICAgICAgY29uc3QgdHhIYXNoID0gQ2FyZGFub1dhc20uaGFzaF90cmFuc2FjdGlvbih0eEJvZHkpO1xuXG4gICAgICAvLyB3ZSBhZGQgd2l0bmVzc2VzIG9uY2Ugc28gdGhhdCB3ZSBjYW4gZ2V0IHRoZSBhcHByb3ByaWF0ZSBhbW91bnQgb2Ygc2lnbmVycyBmb3IgY2FsY3VsYXRpbmcgdGhlIGZlZVxuICAgICAgY29uc3Qgd2l0bmVzc1NldCA9IENhcmRhbm9XYXNtLlRyYW5zYWN0aW9uV2l0bmVzc1NldC5uZXcoKTtcbiAgICAgIGNvbnN0IHZrZXlXaXRuZXNzZXMgPSBDYXJkYW5vV2FzbS5Wa2V5d2l0bmVzc2VzLm5ldygpO1xuICAgICAgdGhpcy5fc2lnbmVycy5mb3JFYWNoKChrZXlQYWlyKSA9PiB7XG4gICAgICAgIGNvbnN0IHBydiA9IGtleVBhaXIuZ2V0S2V5cygpLnBydiBhcyBzdHJpbmc7XG4gICAgICAgIGNvbnN0IHZrZXlXaXRuZXNzID0gQ2FyZGFub1dhc20ubWFrZV92a2V5X3dpdG5lc3MoXG4gICAgICAgICAgdHhIYXNoLFxuICAgICAgICAgIENhcmRhbm9XYXNtLlByaXZhdGVLZXkuZnJvbV9ub3JtYWxfYnl0ZXMoQnVmZmVyLmZyb20ocHJ2LCAnaGV4JykpXG4gICAgICAgICk7XG4gICAgICAgIHZrZXlXaXRuZXNzZXMuYWRkKHZrZXlXaXRuZXNzKTtcbiAgICAgIH0pO1xuICAgICAgdGhpcy5nZXRBbGxTaWduYXR1cmVzKCkuZm9yRWFjaCgoc2lnbmF0dXJlKSA9PiB7XG4gICAgICAgIGNvbnN0IHZrZXkgPSBDYXJkYW5vV2FzbS5Wa2V5Lm5ldyhcbiAgICAgICAgICBDYXJkYW5vV2FzbS5QdWJsaWNLZXkuZnJvbV9ieXRlcyhCdWZmZXIuZnJvbShzaWduYXR1cmUucHVibGljS2V5LnB1YiwgJ2hleCcpKVxuICAgICAgICApO1xuICAgICAgICBjb25zdCBlZDI1NVNpZyA9IENhcmRhbm9XYXNtLkVkMjU1MTlTaWduYXR1cmUuZnJvbV9ieXRlcyhzaWduYXR1cmUuc2lnbmF0dXJlKTtcbiAgICAgICAgdmtleVdpdG5lc3Nlcy5hZGQoQ2FyZGFub1dhc20uVmtleXdpdG5lc3MubmV3KHZrZXksIGVkMjU1U2lnKSk7XG4gICAgICB9KTtcbiAgICAgIGlmICh2a2V5V2l0bmVzc2VzLmxlbigpID09PSAwKSB7XG4gICAgICAgIGNvbnN0IHBydiA9IENhcmRhbm9XYXNtLlByaXZhdGVLZXkuZ2VuZXJhdGVfZWQyNTUxOSgpO1xuICAgICAgICBjb25zdCB2a2V5V2l0bmVzcyA9IENhcmRhbm9XYXNtLm1ha2VfdmtleV93aXRuZXNzKHR4SGFzaCwgcHJ2KTtcbiAgICAgICAgdmtleVdpdG5lc3Nlcy5hZGQodmtleVdpdG5lc3MpO1xuICAgICAgICBpZiAodGhpcy5fdHlwZSAhPT0gVHJhbnNhY3Rpb25UeXBlLlNlbmQpIHtcbiAgICAgICAgICB2a2V5V2l0bmVzc2VzLmFkZCh2a2V5V2l0bmVzcyk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHdpdG5lc3NTZXQuc2V0X3ZrZXlzKHZrZXlXaXRuZXNzZXMpO1xuXG4gICAgICAvLyBhZGQgaW4gd2l0aGRyYXdhbCBpZiB0aGlzIGlzIGEgd2l0aGRyYXdhbCB0eFxuICAgICAgaWYgKHRoaXMuX3dpdGhkcmF3YWxzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgY29uc3Qgd2l0aGRyYXdhbHMgPSBDYXJkYW5vV2FzbS5XaXRoZHJhd2Fscy5uZXcoKTtcbiAgICAgICAgdGhpcy5fd2l0aGRyYXdhbHMuZm9yRWFjaCgod2l0aGRyYXdhbDogV2l0aGRyYXdhbCkgPT4ge1xuICAgICAgICAgIGNvbnN0IHJld2FyZEFkZHJlc3MgPSBDYXJkYW5vV2FzbS5SZXdhcmRBZGRyZXNzLmZyb21fYWRkcmVzcyhcbiAgICAgICAgICAgIENhcmRhbm9XYXNtLkFkZHJlc3MuZnJvbV9iZWNoMzIod2l0aGRyYXdhbC5zdGFrZUFkZHJlc3MpXG4gICAgICAgICAgKTtcbiAgICAgICAgICB3aXRoZHJhd2Fscy5pbnNlcnQocmV3YXJkQWRkcmVzcyEsIENhcmRhbm9XYXNtLkJpZ051bS5mcm9tX3N0cih3aXRoZHJhd2FsLnZhbHVlKSk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHR4Qm9keS5zZXRfd2l0aGRyYXdhbHMod2l0aGRyYXdhbHMpO1xuICAgICAgfVxuXG4gICAgICAvLyBhZGQgaW4gY2VydGlmaWNhdGVzIHRvIGdldCBtb2NrIHNpemVcbiAgICAgIGNvbnN0IGRyYWZ0Q2VydHMgPSBDYXJkYW5vV2FzbS5DZXJ0aWZpY2F0ZXMubmV3KCk7XG4gICAgICBmb3IgKGNvbnN0IGNlcnQgb2YgdGhpcy5fY2VydHMpIHtcbiAgICAgICAgZHJhZnRDZXJ0cy5hZGQoY2VydCk7XG4gICAgICB9XG4gICAgICB0eEJvZHkuc2V0X2NlcnRzKGRyYWZ0Q2VydHMpO1xuXG4gICAgICBjb25zdCB0eERyYWZ0ID0gQ2FyZGFub1dhc20uVHJhbnNhY3Rpb24ubmV3KHR4Qm9keSwgd2l0bmVzc1NldCk7XG4gICAgICBjb25zdCBsaW5lYXJGZWUgPSBDYXJkYW5vV2FzbS5MaW5lYXJGZWUubmV3KFxuICAgICAgICBDYXJkYW5vV2FzbS5CaWdOdW0uZnJvbV9zdHIoJzQ0JyksXG4gICAgICAgIENhcmRhbm9XYXNtLkJpZ051bS5mcm9tX3N0cignMTU1MzgxJylcbiAgICAgICk7XG5cbiAgICAgIC8vIGNhbGN1bGF0ZSB0aGUgZmVlIGJhc2VkIG9mZiBvdXIgZHVtbXkgdHJhbnNhY3Rpb25cbiAgICAgIGNvbnN0IGZlZSA9IENhcmRhbm9XYXNtLm1pbl9mZWUodHhEcmFmdCwgbGluZWFyRmVlKS5jaGVja2VkX2FkZChCaWdOdW0uZnJvbV9zdHIoJzQ0MCcpKTtcbiAgICAgIHRoaXMuX2ZlZSA9IGZlZTtcbiAgICB9XG4gICAgdGhpcy5fdHJhbnNhY3Rpb24uZmVlKHRoaXMuX2ZlZS50b19zdHIoKSk7XG4gICAgLy8gbm93IGNhbGN1bGF0ZSB0aGUgY2hhbmdlIGJhc2VkIG9mZiBvZiA8dXR4b0JhbGFuY2U+IC0gPGZlZT4gLSA8YW1vdW50VG9TZW5kPlxuICAgIC8vIHJlc2V0IHRoZSBvdXRwdXRzIGNvbGxlY3Rpb24gYmVjYXVzZSBub3cgb3VyIGxhc3Qgb3V0cHV0IGhhcyBjaGFuZ2VkXG4gICAgb3V0cHV0cyA9IENhcmRhbm9XYXNtLlRyYW5zYWN0aW9uT3V0cHV0cy5uZXcoKTtcbiAgICB0aGlzLl90cmFuc2FjdGlvbk91dHB1dHMuZm9yRWFjaCgob3V0cHV0KSA9PiB7XG4gICAgICBpZiAob3V0cHV0Lm11bHRpQXNzZXRzKSB7XG4gICAgICAgIGNvbnN0IHBvbGljeUlkID0gb3V0cHV0Lm11bHRpQXNzZXRzLmtleXMoKS5nZXQoMCk7XG4gICAgICAgIGNvbnN0IGFzc2V0cyA9IG91dHB1dC5tdWx0aUFzc2V0cy5nZXQocG9saWN5SWQpO1xuICAgICAgICBjb25zdCBhc3NldE5hbWUgPSBhc3NldHMhLmtleXMoKS5nZXQoMCk7XG4gICAgICAgIGNvbnN0IHF1YW50aXR5ID0gYXNzZXRzIS5nZXQoYXNzZXROYW1lKTtcbiAgICAgICAgbGV0IHR4T3V0cHV0QnVpbGRlciA9IENhcmRhbm9XYXNtLlRyYW5zYWN0aW9uT3V0cHV0QnVpbGRlci5uZXcoKTtcbiAgICAgICAgY29uc3Qgb3V0cHV0QW1vdW50ID0gQ2FyZGFub1dhc20uQmlnTnVtLmZyb21fc3RyKG91dHB1dC5hbW91bnQpO1xuICAgICAgICBjb25zdCB0b0FkZHJlc3MgPSB1dGlsLmdldFdhbGxldEFkZHJlc3Mob3V0cHV0LmFkZHJlc3MpO1xuICAgICAgICB0eE91dHB1dEJ1aWxkZXIgPSB0eE91dHB1dEJ1aWxkZXIud2l0aF9hZGRyZXNzKHRvQWRkcmVzcyk7XG4gICAgICAgIGxldCB0eE91dHB1dEFtb3VudEJ1aWxkZXIgPSB0eE91dHB1dEJ1aWxkZXIubmV4dCgpO1xuICAgICAgICBjb25zdCBtdWx0aUFzc2V0ID0gQ2FyZGFub1dhc20uTXVsdGlBc3NldC5uZXcoKTtcbiAgICAgICAgY29uc3QgYXNzZXQgPSBDYXJkYW5vV2FzbS5Bc3NldHMubmV3KCk7XG4gICAgICAgIGFzc2V0Lmluc2VydChhc3NldE5hbWUsIHF1YW50aXR5ISk7XG4gICAgICAgIG11bHRpQXNzZXQuaW5zZXJ0KHBvbGljeUlkLCBhc3NldCk7XG4gICAgICAgIHR4T3V0cHV0QW1vdW50QnVpbGRlciA9IHR4T3V0cHV0QW1vdW50QnVpbGRlci53aXRoX2NvaW5fYW5kX2Fzc2V0KG91dHB1dEFtb3VudCwgbXVsdGlBc3NldCk7XG4gICAgICAgIGNvbnN0IHR4T3V0cHV0ID0gdHhPdXRwdXRBbW91bnRCdWlsZGVyLmJ1aWxkKCk7XG4gICAgICAgIG91dHB1dHMuYWRkKHR4T3V0cHV0KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG91dHB1dHMuYWRkKFxuICAgICAgICAgIENhcmRhbm9XYXNtLlRyYW5zYWN0aW9uT3V0cHV0Lm5ldyhcbiAgICAgICAgICAgIHV0aWwuZ2V0V2FsbGV0QWRkcmVzcyhvdXRwdXQuYWRkcmVzcyksXG4gICAgICAgICAgICBDYXJkYW5vV2FzbS5WYWx1ZS5uZXcoQ2FyZGFub1dhc20uQmlnTnVtLmZyb21fc3RyKG91dHB1dC5hbW91bnQpKVxuICAgICAgICAgIClcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICBpZiAodGhpcy5fY2hhbmdlQWRkcmVzcyAmJiB0aGlzLl9zZW5kZXJCYWxhbmNlKSB7XG4gICAgICBjb25zdCBjaGFuZ2VBZGRyZXNzID0gdXRpbC5nZXRXYWxsZXRBZGRyZXNzKHRoaXMuX2NoYW5nZUFkZHJlc3MpO1xuICAgICAgY29uc3QgdXR4b0JhbGFuY2UgPSBDYXJkYW5vV2FzbS5CaWdOdW0uZnJvbV9zdHIodGhpcy5fc2VuZGVyQmFsYW5jZSk7XG5cbiAgICAgIGNvbnN0IGFkanVzdG1lbnQgPSBCaWdOdW0uZnJvbV9zdHIoJzIwMDAwMDAnKTtcbiAgICAgIGxldCBjaGFuZ2UgPSB1dHhvQmFsYW5jZS5jaGVja2VkX3N1Yih0aGlzLl9mZWUpLmNoZWNrZWRfc3ViKHRvdGFsQW1vdW50VG9TZW5kKTtcbiAgICAgIGlmICh0aGlzLl90eXBlID09PSBUcmFuc2FjdGlvblR5cGUuU3Rha2luZ0FjdGl2YXRlKSB7XG4gICAgICAgIGNoYW5nZSA9IGNoYW5nZS5jaGVja2VkX3N1YihhZGp1c3RtZW50KTtcbiAgICAgIH0gZWxzZSBpZiAodGhpcy5fdHlwZSA9PT0gVHJhbnNhY3Rpb25UeXBlLlN0YWtpbmdEZWFjdGl2YXRlKSB7XG4gICAgICAgIGNoYW5nZSA9IGNoYW5nZS5jaGVja2VkX2FkZChhZGp1c3RtZW50KTtcbiAgICAgIH0gZWxzZSBpZiAodGhpcy5fdHlwZSA9PT0gVHJhbnNhY3Rpb25UeXBlLlN0YWtpbmdXaXRoZHJhdyB8fCB0aGlzLl90eXBlID09PSBUcmFuc2FjdGlvblR5cGUuU3Rha2luZ0NsYWltKSB7XG4gICAgICAgIHRoaXMuX3dpdGhkcmF3YWxzLmZvckVhY2goKHdpdGhkcmF3YWw6IFdpdGhkcmF3YWwpID0+IHtcbiAgICAgICAgICBjaGFuZ2UgPSBjaGFuZ2UuY2hlY2tlZF9hZGQoQ2FyZGFub1dhc20uQmlnTnVtLmZyb21fc3RyKHdpdGhkcmF3YWwudmFsdWUpKTtcbiAgICAgICAgfSk7XG4gICAgICB9XG5cbiAgICAgIC8vIElmIHRvdGFsQW1vdW50VG9TZW5kIGlzIDAsIGl0cyBjb25zb2xpZGF0aW9uXG4gICAgICBpZiAodG90YWxBbW91bnRUb1NlbmQudG9fc3RyKCkgPT0gJzAnKSB7XG4gICAgICAgIC8vIHN1cHBvcnQgZm9yIG11bHRpLWFzc2V0IGNvbnNvbGlkYXRpb25cbiAgICAgICAgaWYgKHRoaXMuX211bHRpQXNzZXRzICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICBjb25zdCB0b3RhbE51bWJlck9mQXNzZXRzID0gQ2FyZGFub1dhc20uQmlnTnVtLmZyb21fc3RyKHRoaXMuX211bHRpQXNzZXRzLmxlbmd0aC50b1N0cmluZygpKTtcbiAgICAgICAgICBjb25zdCBtaW5BbW91bnROZWVkZWRGb3JPbmVBc3NldE91dHB1dCA9IENhcmRhbm9XYXNtLkJpZ051bS5mcm9tX3N0cignMTUwMDAwMCcpO1xuICAgICAgICAgIGNvbnN0IG1pbkFtb3VudE5lZWRlZEZvclRvdGFsQXNzZXRPdXRwdXRzID0gbWluQW1vdW50TmVlZGVkRm9yT25lQXNzZXRPdXRwdXQuY2hlY2tlZF9tdWwodG90YWxOdW1iZXJPZkFzc2V0cyk7XG5cbiAgICAgICAgICBpZiAoIWNoYW5nZS5sZXNzX3RoYW4obWluQW1vdW50TmVlZGVkRm9yVG90YWxBc3NldE91dHB1dHMpKSB7XG4gICAgICAgICAgICB0aGlzLl9tdWx0aUFzc2V0cy5mb3JFYWNoKChhc3NldCkgPT4ge1xuICAgICAgICAgICAgICBsZXQgdHhPdXRwdXRCdWlsZGVyID0gQ2FyZGFub1dhc20uVHJhbnNhY3Rpb25PdXRwdXRCdWlsZGVyLm5ldygpO1xuICAgICAgICAgICAgICAvLyBjaGFuZ2VBZGRyZXNzIGlzIHRoZSByb290IGFkZHJlc3MsIHdoaWNoIGlzIHdoZXJlIHdlIHdhbnQgdGhlIHRva2VucyBhc3NldHMgdG8gYmUgc2VudCB0b1xuICAgICAgICAgICAgICBjb25zdCB0b0FkZHJlc3MgPSB1dGlsLmdldFdhbGxldEFkZHJlc3ModGhpcy5fY2hhbmdlQWRkcmVzcyk7XG4gICAgICAgICAgICAgIHR4T3V0cHV0QnVpbGRlciA9IHR4T3V0cHV0QnVpbGRlci53aXRoX2FkZHJlc3ModG9BZGRyZXNzKTtcbiAgICAgICAgICAgICAgbGV0IHR4T3V0cHV0QW1vdW50QnVpbGRlciA9IHR4T3V0cHV0QnVpbGRlci5uZXh0KCk7XG4gICAgICAgICAgICAgIGNvbnN0IGFzc2V0TmFtZSA9IENhcmRhbm9XYXNtLkFzc2V0TmFtZS5uZXcoQnVmZmVyLmZyb20oYXNzZXQuYXNzZXRfbmFtZSwgJ2hleCcpKTtcbiAgICAgICAgICAgICAgY29uc3QgcG9saWN5SWQgPSBDYXJkYW5vV2FzbS5TY3JpcHRIYXNoLmZyb21fYnl0ZXMoQnVmZmVyLmZyb20oYXNzZXQucG9saWN5X2lkLCAnaGV4JykpO1xuICAgICAgICAgICAgICBjb25zdCBtdWx0aUFzc2V0ID0gQ2FyZGFub1dhc20uTXVsdGlBc3NldC5uZXcoKTtcbiAgICAgICAgICAgICAgY29uc3QgYXNzZXRzID0gQ2FyZGFub1dhc20uQXNzZXRzLm5ldygpO1xuICAgICAgICAgICAgICBhc3NldHMuaW5zZXJ0KGFzc2V0TmFtZSwgQ2FyZGFub1dhc20uQmlnTnVtLmZyb21fc3RyKGFzc2V0LnF1YW50aXR5KSk7XG4gICAgICAgICAgICAgIG11bHRpQXNzZXQuaW5zZXJ0KHBvbGljeUlkLCBhc3NldHMpO1xuXG4gICAgICAgICAgICAgIHR4T3V0cHV0QW1vdW50QnVpbGRlciA9IHR4T3V0cHV0QW1vdW50QnVpbGRlci53aXRoX2NvaW5fYW5kX2Fzc2V0KFxuICAgICAgICAgICAgICAgIG1pbkFtb3VudE5lZWRlZEZvck9uZUFzc2V0T3V0cHV0LFxuICAgICAgICAgICAgICAgIG11bHRpQXNzZXRcbiAgICAgICAgICAgICAgKTtcblxuICAgICAgICAgICAgICBjb25zdCB0eE91dHB1dCA9IHR4T3V0cHV0QW1vdW50QnVpbGRlci5idWlsZCgpO1xuICAgICAgICAgICAgICBvdXRwdXRzLmFkZCh0eE91dHB1dCk7XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgLy8gZmluYWxseSBzZW5kIHRoZSByZW1haW5pbmcgQURBIGluIGl0cyBvd24gb3V0cHV0XG4gICAgICAgICAgICBjb25zdCByZW1haW5pbmdPdXRwdXRBbW91bnQgPSBjaGFuZ2UuY2hlY2tlZF9zdWIobWluQW1vdW50TmVlZGVkRm9yVG90YWxBc3NldE91dHB1dHMpO1xuICAgICAgICAgICAgY29uc3QgY2hhbmdlT3V0cHV0ID0gQ2FyZGFub1dhc20uVHJhbnNhY3Rpb25PdXRwdXQubmV3KFxuICAgICAgICAgICAgICBjaGFuZ2VBZGRyZXNzLFxuICAgICAgICAgICAgICBDYXJkYW5vV2FzbS5WYWx1ZS5uZXcocmVtYWluaW5nT3V0cHV0QW1vdW50KVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIG91dHB1dHMuYWRkKGNoYW5nZU91dHB1dCk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBCdWlsZFRyYW5zYWN0aW9uRXJyb3IoXG4gICAgICAgICAgICAgICdJbnN1ZmZpY2llbnQgZnVuZHM6IG5lZWQgYSBtaW5pbXVtIG9mIDEuNSBBREEgcGVyIG91dHB1dCB0byBjb25zdHJ1Y3QgdG9rZW4gY29uc29saWRhdGlvbidcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIC8vIElmIHRoZXJlIGFyZSBubyB0b2tlbnMgdG8gY29uc29saWRhdGUsIHlvdSBvbmx5IGhhdmUgMSBvdXRwdXQgd2hpY2ggaXMgQURBIGFsb25lXG4gICAgICAgICAgY29uc3QgY2hhbmdlT3V0cHV0ID0gQ2FyZGFub1dhc20uVHJhbnNhY3Rpb25PdXRwdXQubmV3KGNoYW5nZUFkZHJlc3MsIENhcmRhbm9XYXNtLlZhbHVlLm5ldyhjaGFuZ2UpKTtcbiAgICAgICAgICBvdXRwdXRzLmFkZChjaGFuZ2VPdXRwdXQpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBJZiB0aGlzIGlzbid0IGEgY29uc29saWRhdGUgcmVxdWVzdCwgd2hhdGV2ZXIgY2hhbmdlIHRoYXQgbmVlZHMgdG8gYmUgc2VudCBiYWNrIHRvIHRoZSByb290YWRkcmVzcyBpcyBhZGRlZCBhcyBhIHNlcGFyYXRlIG91dHB1dCBoZXJlXG4gICAgICAgIGNvbnN0IGNoYW5nZU91dHB1dCA9IENhcmRhbm9XYXNtLlRyYW5zYWN0aW9uT3V0cHV0Lm5ldyhjaGFuZ2VBZGRyZXNzLCBDYXJkYW5vV2FzbS5WYWx1ZS5uZXcoY2hhbmdlKSk7XG4gICAgICAgIG91dHB1dHMuYWRkKGNoYW5nZU91dHB1dCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3QgdHhSYXcgPSBDYXJkYW5vV2FzbS5UcmFuc2FjdGlvbkJvZHkubmV3X3R4X2JvZHkoaW5wdXRzLCBvdXRwdXRzLCB0aGlzLl9mZWUpO1xuXG4gICAgY29uc3QgY2VydHMgPSBDYXJkYW5vV2FzbS5DZXJ0aWZpY2F0ZXMubmV3KCk7XG4gICAgZm9yIChjb25zdCBjZXJ0IG9mIHRoaXMuX2NlcnRzKSB7XG4gICAgICBjZXJ0cy5hZGQoY2VydCk7XG4gICAgfVxuICAgIHR4UmF3LnNldF9jZXJ0cyhjZXJ0cyk7XG5cbiAgICAvLyBhZGQgaW4gd2l0aGRyYXdhbCBpZiB0aGlzIGlzIGEgd2l0aGRyYXdhbCB0eFxuICAgIGlmICh0aGlzLl93aXRoZHJhd2Fscy5sZW5ndGggPiAwKSB7XG4gICAgICBjb25zdCB3aXRoZHJhd2FscyA9IENhcmRhbm9XYXNtLldpdGhkcmF3YWxzLm5ldygpO1xuICAgICAgdGhpcy5fd2l0aGRyYXdhbHMuZm9yRWFjaCgod2l0aGRyYXdhbDogV2l0aGRyYXdhbCkgPT4ge1xuICAgICAgICBjb25zdCByZXdhcmRBZGRyZXNzID0gQ2FyZGFub1dhc20uUmV3YXJkQWRkcmVzcy5mcm9tX2FkZHJlc3MoXG4gICAgICAgICAgQ2FyZGFub1dhc20uQWRkcmVzcy5mcm9tX2JlY2gzMih3aXRoZHJhd2FsLnN0YWtlQWRkcmVzcylcbiAgICAgICAgKTtcbiAgICAgICAgd2l0aGRyYXdhbHMuaW5zZXJ0KHJld2FyZEFkZHJlc3MhLCBDYXJkYW5vV2FzbS5CaWdOdW0uZnJvbV9zdHIod2l0aGRyYXdhbC52YWx1ZSkpO1xuICAgICAgfSk7XG5cbiAgICAgIHR4UmF3LnNldF93aXRoZHJhd2Fscyh3aXRoZHJhd2Fscyk7XG4gICAgfVxuXG4gICAgdHhSYXcuc2V0X3R0bChDYXJkYW5vV2FzbS5CaWdOdW0uZnJvbV9zdHIodGhpcy5fdHRsLnRvU3RyaW5nKCkpKTtcbiAgICBjb25zdCB0eFJhd0hhc2ggPSBDYXJkYW5vV2FzbS5oYXNoX3RyYW5zYWN0aW9uKHR4UmF3KTtcblxuICAgIC8vIG5vdyBhZGQgdGhlIHdpdG5lc3NlcyBhZ2FpbiB0aGlzIHRpbWUgZm9yIHJlYWwuIFdlIG5lZWQgdG8gZG8gdGhpcyBhZ2FpblxuICAgIC8vIGJlY2F1c2Ugbm93IHRoYXQgd2UndmUgYWRkZWQgb3VyIHJlYWwgZmVlIGFuZCBjaGFuZ2Ugb3V0cHV0LCB3ZSBoYXZlIGEgZGlmZmVyZW5jZSB0cmFuc2FjdGlvbiBoYXNoXG4gICAgY29uc3Qgd2l0bmVzc1NldCA9IENhcmRhbm9XYXNtLlRyYW5zYWN0aW9uV2l0bmVzc1NldC5uZXcoKTtcbiAgICBjb25zdCB2a2V5V2l0bmVzc2VzID0gQ2FyZGFub1dhc20uVmtleXdpdG5lc3Nlcy5uZXcoKTtcbiAgICB0aGlzLl9zaWduZXJzLmZvckVhY2goKGtleVBhaXIpID0+IHtcbiAgICAgIGNvbnN0IHBydiA9IGtleVBhaXIuZ2V0S2V5cygpLnBydiBhcyBzdHJpbmc7XG4gICAgICBjb25zdCB2a2V5V2l0bmVzcyA9IENhcmRhbm9XYXNtLm1ha2VfdmtleV93aXRuZXNzKFxuICAgICAgICB0eFJhd0hhc2gsXG4gICAgICAgIENhcmRhbm9XYXNtLlByaXZhdGVLZXkuZnJvbV9ub3JtYWxfYnl0ZXMoQnVmZmVyLmZyb20ocHJ2LCAnaGV4JykpXG4gICAgICApO1xuICAgICAgdmtleVdpdG5lc3Nlcy5hZGQodmtleVdpdG5lc3MpO1xuICAgIH0pO1xuXG4gICAgLy8gQ2xlYXIgdGhlIGNvc21ldGljIHNpZ25hdHVyZSBhcnJheSBpbiBuYXRpdmUgdHhuIHdyYXBwZXIgdG8gcHJldmVudCBkdXBsaWNhdGUgd2hlbiBidWlsZGVyIGlzIGluaXRlZCBmcm9tIGEgcGFydGlhbGx5IHdpdG5lc3NlZCB0eG5cbiAgICB0aGlzLl90cmFuc2FjdGlvbi5zaWduYXR1cmUubGVuZ3RoID0gMDtcbiAgICB0aGlzLmdldEFsbFNpZ25hdHVyZXMoKS5mb3JFYWNoKChzaWduYXR1cmUpID0+IHtcbiAgICAgIGNvbnN0IHZrZXkgPSBDYXJkYW5vV2FzbS5Wa2V5Lm5ldyhDYXJkYW5vV2FzbS5QdWJsaWNLZXkuZnJvbV9ieXRlcyhCdWZmZXIuZnJvbShzaWduYXR1cmUucHVibGljS2V5LnB1YiwgJ2hleCcpKSk7XG4gICAgICBjb25zdCBlZDI1NVNpZyA9IENhcmRhbm9XYXNtLkVkMjU1MTlTaWduYXR1cmUuZnJvbV9ieXRlcyhzaWduYXR1cmUuc2lnbmF0dXJlKTtcbiAgICAgIHZrZXlXaXRuZXNzZXMuYWRkKENhcmRhbm9XYXNtLlZrZXl3aXRuZXNzLm5ldyh2a2V5LCBlZDI1NVNpZykpO1xuICAgICAgdGhpcy5fdHJhbnNhY3Rpb24uc2lnbmF0dXJlLnB1c2goc2lnbmF0dXJlLnNpZ25hdHVyZS50b1N0cmluZygnaGV4JykpO1xuICAgIH0pO1xuICAgIHdpdG5lc3NTZXQuc2V0X3ZrZXlzKHZrZXlXaXRuZXNzZXMpO1xuICAgIHRoaXMuX3RyYW5zYWN0aW9uLnRyYW5zYWN0aW9uID0gQ2FyZGFub1dhc20uVHJhbnNhY3Rpb24ubmV3KHR4UmF3LCB3aXRuZXNzU2V0KTtcbiAgICByZXR1cm4gdGhpcy50cmFuc2FjdGlvbjtcbiAgfVxuXG4gIC8qKiBAaW5oZXJpdGRvYyAqL1xuICBwcm90ZWN0ZWQgc2lnbkltcGxlbWVudGF0aW9uKGtleTogQmFzZUtleSk6IFRyYW5zYWN0aW9uIHtcbiAgICB0aGlzLl9zaWduZXJzLnB1c2gobmV3IEtleVBhaXIoeyBwcnY6IGtleS5rZXkgfSkpO1xuICAgIHJldHVybiB0aGlzLl90cmFuc2FjdGlvbjtcbiAgfVxuXG4gIC8qKiBAaW5oZXJpdGRvYyAqL1xuICBwcm90ZWN0ZWQgZ2V0IHRyYW5zYWN0aW9uKCk6IFRyYW5zYWN0aW9uIHtcbiAgICByZXR1cm4gdGhpcy5fdHJhbnNhY3Rpb247XG4gIH1cblxuICAvKiogQGluaGVyaXRkb2MgKi9cbiAgcHJvdGVjdGVkIHNldCB0cmFuc2FjdGlvbih0cmFuc2FjdGlvbjogVHJhbnNhY3Rpb24pIHtcbiAgICB0aGlzLl90cmFuc2FjdGlvbiA9IHRyYW5zYWN0aW9uO1xuICB9XG5cbiAgLyoqIEBpbmhlcml0ZG9jICovXG4gIHZhbGlkYXRlQWRkcmVzcyhhZGRyZXNzOiBCYXNlQWRkcmVzcywgYWRkcmVzc0Zvcm1hdD86IHN0cmluZyk6IHZvaWQge1xuICAgIGlmICghdXRpbC5pc1ZhbGlkQWRkcmVzcyhhZGRyZXNzLmFkZHJlc3MpKSB7XG4gICAgICB0aHJvdyBuZXcgVXRpbHNFcnJvcignaW52YWxpZCBhZGRyZXNzICcgKyBhZGRyZXNzLmFkZHJlc3MpO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBAaW5oZXJpdGRvYyAqL1xuICB2YWxpZGF0ZUtleShrZXk6IEJhc2VLZXkpOiB2b2lkIHtcbiAgICB0cnkge1xuICAgICAgbmV3IEtleVBhaXIoeyBwcnY6IGtleS5rZXkgfSk7XG4gICAgfSBjYXRjaCB7XG4gICAgICB0aHJvdyBuZXcgQnVpbGRUcmFuc2FjdGlvbkVycm9yKGBLZXkgdmFsaWRhdGlvbiBmYWlsZWRgKTtcbiAgICB9XG4gIH1cblxuICAvKiogQGluaGVyaXRkb2MgKi9cbiAgdmFsaWRhdGVSYXdUcmFuc2FjdGlvbihyYXdUcmFuc2FjdGlvbjogYW55KTogdm9pZCB7XG4gICAgdHJ5IHtcbiAgICAgIENhcmRhbm9XYXNtLlRyYW5zYWN0aW9uLmZyb21fYnl0ZXMocmF3VHJhbnNhY3Rpb24pO1xuICAgIH0gY2F0Y2gge1xuICAgICAgdGhyb3cgbmV3IEJ1aWxkVHJhbnNhY3Rpb25FcnJvcignaW52YWxpZCByYXcgdHJhbnNhY3Rpb24nKTtcbiAgICB9XG4gIH1cblxuICAvKiogQGluaGVyaXRkb2MgKi9cbiAgdmFsaWRhdGVUcmFuc2FjdGlvbih0cmFuc2FjdGlvbjogVHJhbnNhY3Rpb24pOiB2b2lkIHtcbiAgICBpZiAoIXRyYW5zYWN0aW9uLnRyYW5zYWN0aW9uKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICB9XG5cbiAgLyoqIEBpbmhlcml0ZG9jICovXG4gIHZhbGlkYXRlVmFsdWUodmFsdWU6IEJpZ051bWJlcik6IHZvaWQge1xuICAgIGlmICh2YWx1ZS5pc0xlc3NUaGFuKDApKSB7XG4gICAgICB0aHJvdyBuZXcgQnVpbGRUcmFuc2FjdGlvbkVycm9yKCdWYWx1ZSBjYW5ub3QgYmUgbGVzcyB0aGFuIHplcm8nKTtcbiAgICB9XG4gIH1cbiAgLy8gZW5kcmVnaW9uXG5cbiAgLyoqIEBpbmhlcml0RG9jICovXG4gIGFkZFNpZ25hdHVyZShwdWJsaWNLZXk6IEJhc2VQdWJsaWNLZXksIHNpZ25hdHVyZTogQnVmZmVyKTogdm9pZCB7XG4gICAgdGhpcy5fc2lnbmF0dXJlcy5wdXNoKHsgcHVibGljS2V5LCBzaWduYXR1cmUgfSk7XG4gIH1cblxuICBwcml2YXRlIGdldEFsbFNpZ25hdHVyZXMoKTogU2lnbmF0dXJlW10ge1xuICAgIHJldHVybiB0aGlzLl9pbml0U2lnbmF0dXJlcy5jb25jYXQodGhpcy5fc2lnbmF0dXJlcyk7XG4gIH1cbn1cbiJdfQ==