@bitgo/abstract-eth 24.10.1 → 24.11.0
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/CHANGELOG.md +6 -0
- package/LICENSE +191 -0
- package/dist/src/abstractEthLikeCoin.d.ts +95 -0
- package/dist/src/abstractEthLikeCoin.d.ts.map +1 -0
- package/dist/src/abstractEthLikeCoin.js +160 -0
- package/dist/src/abstractEthLikeNewCoins.d.ts +749 -0
- package/dist/src/abstractEthLikeNewCoins.d.ts.map +1 -0
- package/dist/src/abstractEthLikeNewCoins.js +2229 -0
- package/dist/src/ethLikeToken.d.ts +70 -0
- package/dist/src/ethLikeToken.d.ts.map +1 -0
- package/dist/src/ethLikeToken.js +360 -0
- package/dist/src/index.d.ts +5 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +21 -0
- package/dist/src/lib/contractCall.d.ts +8 -0
- package/dist/src/lib/contractCall.d.ts.map +1 -0
- package/dist/src/lib/contractCall.js +17 -0
- package/dist/src/lib/iface.d.ts +133 -0
- package/dist/src/lib/iface.d.ts.map +1 -0
- package/dist/src/lib/iface.js +8 -0
- package/dist/src/lib/index.d.ts +16 -0
- package/dist/src/lib/index.d.ts.map +1 -0
- package/dist/src/lib/index.js +57 -0
- package/dist/src/lib/keyPair.d.ts +26 -0
- package/dist/src/lib/keyPair.d.ts.map +1 -0
- package/dist/src/lib/keyPair.js +65 -0
- package/dist/src/lib/messages/eip191/eip191Message.d.ts +12 -0
- package/dist/src/lib/messages/eip191/eip191Message.d.ts.map +1 -0
- package/dist/src/lib/messages/eip191/eip191Message.js +25 -0
- package/dist/src/lib/messages/eip191/eip191MessageBuilder.d.ts +19 -0
- package/dist/src/lib/messages/eip191/eip191MessageBuilder.d.ts.map +1 -0
- package/dist/src/lib/messages/eip191/eip191MessageBuilder.js +27 -0
- package/dist/src/lib/messages/eip191/index.d.ts +3 -0
- package/dist/src/lib/messages/eip191/index.d.ts.map +1 -0
- package/dist/src/lib/messages/eip191/index.js +19 -0
- package/dist/src/lib/messages/index.d.ts +3 -0
- package/dist/src/lib/messages/index.d.ts.map +1 -0
- package/dist/src/lib/messages/index.js +19 -0
- package/dist/src/lib/messages/messageBuilderFactory.d.ts +7 -0
- package/dist/src/lib/messages/messageBuilderFactory.d.ts.map +1 -0
- package/dist/src/lib/messages/messageBuilderFactory.js +20 -0
- package/dist/src/lib/transaction.d.ts +67 -0
- package/dist/src/lib/transaction.d.ts.map +1 -0
- package/dist/src/lib/transaction.js +142 -0
- package/dist/src/lib/transactionBuilder.d.ts +251 -0
- package/dist/src/lib/transactionBuilder.d.ts.map +1 -0
- package/dist/src/lib/transactionBuilder.js +742 -0
- package/dist/src/lib/transferBuilder.d.ts +76 -0
- package/dist/src/lib/transferBuilder.d.ts.map +1 -0
- package/dist/src/lib/transferBuilder.js +307 -0
- package/dist/src/lib/transferBuilders/baseNFTTransferBuilder.d.ts +54 -0
- package/dist/src/lib/transferBuilders/baseNFTTransferBuilder.d.ts.map +1 -0
- package/dist/src/lib/transferBuilders/baseNFTTransferBuilder.js +120 -0
- package/dist/src/lib/transferBuilders/index.d.ts +4 -0
- package/dist/src/lib/transferBuilders/index.d.ts.map +1 -0
- package/dist/src/lib/transferBuilders/index.js +20 -0
- package/dist/src/lib/transferBuilders/transferBuilderERC1155.d.ts +17 -0
- package/dist/src/lib/transferBuilders/transferBuilderERC1155.d.ts.map +1 -0
- package/dist/src/lib/transferBuilders/transferBuilderERC1155.js +96 -0
- package/dist/src/lib/transferBuilders/transferBuilderERC721.d.ts +16 -0
- package/dist/src/lib/transferBuilders/transferBuilderERC721.d.ts.map +1 -0
- package/dist/src/lib/transferBuilders/transferBuilderERC721.js +81 -0
- package/dist/src/lib/types.d.ts +39 -0
- package/dist/src/lib/types.d.ts.map +1 -0
- package/dist/src/lib/types.js +137 -0
- package/dist/src/lib/utils.d.ts +270 -0
- package/dist/src/lib/utils.d.ts.map +1 -0
- package/dist/src/lib/utils.js +717 -0
- package/dist/src/lib/walletUtil.d.ts +32 -0
- package/dist/src/lib/walletUtil.d.ts.map +1 -0
- package/dist/src/lib/walletUtil.js +35 -0
- package/dist/src/types.d.ts +9 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/src/types.js +3 -0
- package/dist/test/index.d.ts +2 -0
- package/dist/test/index.d.ts.map +1 -0
- package/dist/test/index.js +18 -0
- package/dist/test/unit/coin.d.ts +8 -0
- package/dist/test/unit/coin.d.ts.map +1 -0
- package/dist/test/unit/coin.js +577 -0
- package/dist/test/unit/index.d.ts +6 -0
- package/dist/test/unit/index.d.ts.map +1 -0
- package/dist/test/unit/index.js +22 -0
- package/dist/test/unit/messages/eip191/eip191Message.d.ts +2 -0
- package/dist/test/unit/messages/eip191/eip191Message.d.ts.map +1 -0
- package/dist/test/unit/messages/eip191/eip191Message.js +137 -0
- package/dist/test/unit/messages/eip191/eip191MessageBuilder.d.ts +2 -0
- package/dist/test/unit/messages/eip191/eip191MessageBuilder.d.ts.map +1 -0
- package/dist/test/unit/messages/eip191/eip191MessageBuilder.js +116 -0
- package/dist/test/unit/messages/fixtures.d.ts +24 -0
- package/dist/test/unit/messages/fixtures.d.ts.map +1 -0
- package/dist/test/unit/messages/fixtures.js +28 -0
- package/dist/test/unit/messages/index.d.ts +4 -0
- package/dist/test/unit/messages/index.d.ts.map +1 -0
- package/dist/test/unit/messages/index.js +20 -0
- package/dist/test/unit/messages/messageBuilderFactory.d.ts +2 -0
- package/dist/test/unit/messages/messageBuilderFactory.d.ts.map +1 -0
- package/dist/test/unit/messages/messageBuilderFactory.js +44 -0
- package/dist/test/unit/token.d.ts +2 -0
- package/dist/test/unit/token.d.ts.map +1 -0
- package/dist/test/unit/token.js +37 -0
- package/dist/test/unit/transaction.d.ts +3 -0
- package/dist/test/unit/transaction.d.ts.map +1 -0
- package/dist/test/unit/transaction.js +60 -0
- package/dist/test/unit/transactionBuilder/addressInitialization.d.ts +8 -0
- package/dist/test/unit/transactionBuilder/addressInitialization.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/addressInitialization.js +95 -0
- package/dist/test/unit/transactionBuilder/index.d.ts +4 -0
- package/dist/test/unit/transactionBuilder/index.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/index.js +20 -0
- package/dist/test/unit/transactionBuilder/send.d.ts +3 -0
- package/dist/test/unit/transactionBuilder/send.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/send.js +197 -0
- package/dist/test/unit/transactionBuilder/walletInitialization.d.ts +10 -0
- package/dist/test/unit/transactionBuilder/walletInitialization.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/walletInitialization.js +124 -0
- package/dist/test/unit/transferBuilder.d.ts +2 -0
- package/dist/test/unit/transferBuilder.d.ts.map +1 -0
- package/dist/test/unit/transferBuilder.js +76 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +8 -8
|
@@ -0,0 +1,742 @@
|
|
|
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
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.TransactionBuilder = void 0;
|
|
40
|
+
const statics_1 = require("@bitgo/statics");
|
|
41
|
+
const ethereumjs_abi_1 = __importDefault(require("ethereumjs-abi"));
|
|
42
|
+
const bignumber_js_1 = __importDefault(require("bignumber.js"));
|
|
43
|
+
const ethUtil = __importStar(require("ethereumjs-util"));
|
|
44
|
+
const tx_1 = require("@ethereumjs/tx");
|
|
45
|
+
const sdk_core_1 = require("@bitgo/sdk-core");
|
|
46
|
+
const keyPair_1 = require("./keyPair");
|
|
47
|
+
const iface_1 = require("./iface");
|
|
48
|
+
const utils_1 = require("./utils");
|
|
49
|
+
const walletUtil_1 = require("./walletUtil");
|
|
50
|
+
const transaction_1 = require("./transaction");
|
|
51
|
+
const DEFAULT_M = 3;
|
|
52
|
+
/**
|
|
53
|
+
* EthereumLike transaction builder.
|
|
54
|
+
*/
|
|
55
|
+
class TransactionBuilder extends sdk_core_1.BaseTransactionBuilder {
|
|
56
|
+
/**
|
|
57
|
+
* Public constructor.
|
|
58
|
+
*
|
|
59
|
+
* @param _coinConfig
|
|
60
|
+
*/
|
|
61
|
+
constructor(_coinConfig) {
|
|
62
|
+
super(_coinConfig);
|
|
63
|
+
this._common = (0, utils_1.getCommon)(this._coinConfig.network);
|
|
64
|
+
this._type = sdk_core_1.TransactionType.Send;
|
|
65
|
+
this._counter = 0;
|
|
66
|
+
this._value = '0';
|
|
67
|
+
this._walletOwnerAddresses = [];
|
|
68
|
+
this._forwarderVersion = 0;
|
|
69
|
+
this._walletVersion = 0;
|
|
70
|
+
this.transaction = new transaction_1.Transaction(this._coinConfig, this._common);
|
|
71
|
+
this._walletSimpleByteCode = '';
|
|
72
|
+
}
|
|
73
|
+
/** @inheritdoc */
|
|
74
|
+
async buildImplementation() {
|
|
75
|
+
const transactionData = this.getTransactionData();
|
|
76
|
+
if (this._txSignature) {
|
|
77
|
+
Object.assign(transactionData, this._txSignature);
|
|
78
|
+
}
|
|
79
|
+
this.transaction.setTransactionType(this._type);
|
|
80
|
+
transactionData.from = this._sourceKeyPair ? this._sourceKeyPair.getAddress() : undefined;
|
|
81
|
+
this.transaction.setTransactionData(transactionData, this._transfer ? this._transfer.getIsFirstSigner() : undefined);
|
|
82
|
+
// Build and sign a new transaction based on the latest changes
|
|
83
|
+
if (this._sourceKeyPair && this._sourceKeyPair.getKeys().prv) {
|
|
84
|
+
await this.transaction.sign(this._sourceKeyPair);
|
|
85
|
+
}
|
|
86
|
+
return this.transaction;
|
|
87
|
+
}
|
|
88
|
+
getTransactionData() {
|
|
89
|
+
switch (this._type) {
|
|
90
|
+
case sdk_core_1.TransactionType.WalletInitialization:
|
|
91
|
+
return this.buildWalletInitializationTransaction(this._walletVersion);
|
|
92
|
+
case sdk_core_1.TransactionType.RecoveryWalletDeployment:
|
|
93
|
+
return this.buildBase(this._data);
|
|
94
|
+
case sdk_core_1.TransactionType.Send:
|
|
95
|
+
case sdk_core_1.TransactionType.SendERC721:
|
|
96
|
+
case sdk_core_1.TransactionType.SendERC1155:
|
|
97
|
+
return this.buildSendTransaction();
|
|
98
|
+
case sdk_core_1.TransactionType.AddressInitialization:
|
|
99
|
+
return this.buildAddressInitializationTransaction();
|
|
100
|
+
case sdk_core_1.TransactionType.FlushTokens:
|
|
101
|
+
return this.buildFlushTokensTransaction();
|
|
102
|
+
case sdk_core_1.TransactionType.FlushCoins:
|
|
103
|
+
return this.buildFlushCoinsTransaction();
|
|
104
|
+
case sdk_core_1.TransactionType.SingleSigSend:
|
|
105
|
+
return this.buildBase('0x');
|
|
106
|
+
case sdk_core_1.TransactionType.ContractCall:
|
|
107
|
+
return this.buildGenericContractCallTransaction();
|
|
108
|
+
default:
|
|
109
|
+
throw new sdk_core_1.BuildTransactionError('Unsupported transaction type');
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
/** @inheritdoc */
|
|
113
|
+
fromImplementation(rawTransaction, isFirstSigner) {
|
|
114
|
+
let tx;
|
|
115
|
+
if (/^0x?[0-9a-f]{1,}$/.test(rawTransaction.toLowerCase())) {
|
|
116
|
+
tx = transaction_1.Transaction.fromSerialized(this._coinConfig, this._common, rawTransaction, isFirstSigner);
|
|
117
|
+
this.loadBuilderInput(tx.toJson(), isFirstSigner);
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
const txData = JSON.parse(rawTransaction);
|
|
121
|
+
tx = new transaction_1.Transaction(this._coinConfig, txData);
|
|
122
|
+
}
|
|
123
|
+
return tx;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Load the builder data using the deserialized transaction
|
|
127
|
+
*
|
|
128
|
+
* @param {TxData} transactionJson the deserialized transaction json
|
|
129
|
+
* @param {boolean} isFirstSigner if the transaction is being signed by the first signer
|
|
130
|
+
*/
|
|
131
|
+
loadBuilderInput(transactionJson, isFirstSigner) {
|
|
132
|
+
const decodedType = (0, utils_1.classifyTransaction)(transactionJson.data);
|
|
133
|
+
this.type(decodedType);
|
|
134
|
+
this.counter(transactionJson.nonce);
|
|
135
|
+
this.value(transactionJson.value);
|
|
136
|
+
if (transactionJson._type === iface_1.ETHTransactionType.LEGACY) {
|
|
137
|
+
this.fee({
|
|
138
|
+
fee: transactionJson.gasPrice,
|
|
139
|
+
gasPrice: transactionJson.gasPrice,
|
|
140
|
+
gasLimit: transactionJson.gasLimit,
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
this.fee({
|
|
145
|
+
gasLimit: transactionJson.gasLimit,
|
|
146
|
+
fee: transactionJson.maxFeePerGas,
|
|
147
|
+
eip1559: {
|
|
148
|
+
maxFeePerGas: transactionJson.maxFeePerGas,
|
|
149
|
+
maxPriorityFeePerGas: transactionJson.maxPriorityFeePerGas,
|
|
150
|
+
},
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
if ((0, utils_1.hasSignature)(transactionJson)) {
|
|
154
|
+
this._txSignature = { v: transactionJson.v, r: transactionJson.r, s: transactionJson.s };
|
|
155
|
+
}
|
|
156
|
+
this.setTransactionTypeFields(decodedType, transactionJson, isFirstSigner);
|
|
157
|
+
}
|
|
158
|
+
setTransactionTypeFields(decodedType, transactionJson, isFirstSigner) {
|
|
159
|
+
switch (decodedType) {
|
|
160
|
+
case sdk_core_1.TransactionType.WalletInitialization:
|
|
161
|
+
const { owners, salt } = (0, utils_1.decodeWalletCreationData)(transactionJson.data);
|
|
162
|
+
owners.forEach((element) => {
|
|
163
|
+
this.owner(element);
|
|
164
|
+
});
|
|
165
|
+
if (salt) {
|
|
166
|
+
this.salt(salt);
|
|
167
|
+
this.walletVersion(1);
|
|
168
|
+
this.setContract(transactionJson.to);
|
|
169
|
+
}
|
|
170
|
+
break;
|
|
171
|
+
case sdk_core_1.TransactionType.RecoveryWalletDeployment:
|
|
172
|
+
this.data(transactionJson.data);
|
|
173
|
+
break;
|
|
174
|
+
case sdk_core_1.TransactionType.FlushTokens:
|
|
175
|
+
this.setContract(transactionJson.to);
|
|
176
|
+
const { forwarderAddress, tokenAddress, forwarderVersion } = (0, utils_1.decodeFlushTokensData)(transactionJson.data, transactionJson.to);
|
|
177
|
+
if (forwarderVersion === 4) {
|
|
178
|
+
this.forwarderVersion(4);
|
|
179
|
+
}
|
|
180
|
+
this.forwarderAddress(forwarderAddress);
|
|
181
|
+
this.tokenAddress(tokenAddress);
|
|
182
|
+
break;
|
|
183
|
+
case sdk_core_1.TransactionType.FlushCoins:
|
|
184
|
+
this.setContract(transactionJson.to);
|
|
185
|
+
break;
|
|
186
|
+
case sdk_core_1.TransactionType.Send:
|
|
187
|
+
case sdk_core_1.TransactionType.SendERC1155:
|
|
188
|
+
case sdk_core_1.TransactionType.SendERC721:
|
|
189
|
+
this.setContract(transactionJson.to);
|
|
190
|
+
this._transfer = this.transfer(transactionJson.data, isFirstSigner);
|
|
191
|
+
break;
|
|
192
|
+
case sdk_core_1.TransactionType.AddressInitialization:
|
|
193
|
+
this.setContract(transactionJson.to);
|
|
194
|
+
const { baseAddress, addressCreationSalt, feeAddress } = (0, utils_1.decodeForwarderCreationData)(transactionJson.data);
|
|
195
|
+
if (baseAddress && addressCreationSalt) {
|
|
196
|
+
this.baseAddress(baseAddress);
|
|
197
|
+
this.salt(addressCreationSalt);
|
|
198
|
+
if (feeAddress) {
|
|
199
|
+
this.feeAddress(feeAddress);
|
|
200
|
+
this.forwarderVersion(4);
|
|
201
|
+
}
|
|
202
|
+
else {
|
|
203
|
+
this.forwarderVersion(1);
|
|
204
|
+
}
|
|
205
|
+
const forwarderImplementationAddress = this._coinConfig.network
|
|
206
|
+
.forwarderImplementationAddress;
|
|
207
|
+
if (forwarderImplementationAddress) {
|
|
208
|
+
this.initCode(forwarderImplementationAddress);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
break;
|
|
212
|
+
case sdk_core_1.TransactionType.SingleSigSend:
|
|
213
|
+
this.setContract(transactionJson.to);
|
|
214
|
+
break;
|
|
215
|
+
case sdk_core_1.TransactionType.ContractCall:
|
|
216
|
+
this.setContract(transactionJson.to);
|
|
217
|
+
this.data(transactionJson.data);
|
|
218
|
+
break;
|
|
219
|
+
default:
|
|
220
|
+
throw new sdk_core_1.BuildTransactionError('Unsupported transaction type');
|
|
221
|
+
// TODO: Add other cases of deserialization
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
/** @inheritdoc */
|
|
225
|
+
signImplementation(key) {
|
|
226
|
+
const signer = new keyPair_1.KeyPair({ prv: key.key });
|
|
227
|
+
if (this._type === sdk_core_1.TransactionType.WalletInitialization && this._walletOwnerAddresses.length === 0) {
|
|
228
|
+
throw new sdk_core_1.SigningError('Cannot sign an wallet initialization transaction without owners');
|
|
229
|
+
}
|
|
230
|
+
if (this._sourceKeyPair) {
|
|
231
|
+
throw new sdk_core_1.SigningError('Cannot sign multiple times a non send-type transaction');
|
|
232
|
+
}
|
|
233
|
+
// Signing the transaction is an async operation, so save the source and leave the actual
|
|
234
|
+
// signing for the build step
|
|
235
|
+
this._sourceKeyPair = signer;
|
|
236
|
+
return this.transaction;
|
|
237
|
+
}
|
|
238
|
+
/** @inheritdoc */
|
|
239
|
+
validateAddress(address) {
|
|
240
|
+
if (!(0, utils_1.isValidEthAddress)(address.address)) {
|
|
241
|
+
throw new sdk_core_1.BuildTransactionError('Invalid address ' + address.address);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
/** @inheritdoc */
|
|
245
|
+
validateKey(key) {
|
|
246
|
+
if (!((0, sdk_core_1.isValidXprv)(key.key) || (0, sdk_core_1.isValidPrv)(key.key))) {
|
|
247
|
+
throw new sdk_core_1.BuildTransactionError('Invalid key');
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Validate the raw transaction is either a JSON or
|
|
252
|
+
* a hex encoded transaction
|
|
253
|
+
*
|
|
254
|
+
* @param {any} rawTransaction The raw transaction to be validated
|
|
255
|
+
*/
|
|
256
|
+
validateRawTransaction(rawTransaction) {
|
|
257
|
+
if (!rawTransaction) {
|
|
258
|
+
throw new sdk_core_1.InvalidTransactionError('Raw transaction is empty');
|
|
259
|
+
}
|
|
260
|
+
if (typeof rawTransaction === 'string') {
|
|
261
|
+
if (/^0x?[0-9a-f]{1,}$/.test(rawTransaction.toLowerCase())) {
|
|
262
|
+
const txBytes = ethUtil.toBuffer(ethUtil.addHexPrefix(rawTransaction.toLowerCase()));
|
|
263
|
+
if (!this.isEip1559Txn(txBytes) && !this.isRLPDecodable(txBytes)) {
|
|
264
|
+
throw new sdk_core_1.ParseTransactionError('There was error in decoding the hex string');
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
else {
|
|
268
|
+
try {
|
|
269
|
+
JSON.parse(rawTransaction);
|
|
270
|
+
}
|
|
271
|
+
catch (e) {
|
|
272
|
+
throw new sdk_core_1.ParseTransactionError('There was error in parsing the JSON string');
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
else {
|
|
277
|
+
throw new sdk_core_1.InvalidTransactionError('Transaction is not a hex string or stringified json');
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
isEip1559Txn(txn) {
|
|
281
|
+
try {
|
|
282
|
+
tx_1.FeeMarketEIP1559Transaction.fromSerializedTx(txn);
|
|
283
|
+
return true;
|
|
284
|
+
}
|
|
285
|
+
catch (_) {
|
|
286
|
+
return false;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
isRLPDecodable(bytes) {
|
|
290
|
+
try {
|
|
291
|
+
ethUtil.rlp.decode(bytes);
|
|
292
|
+
return true;
|
|
293
|
+
}
|
|
294
|
+
catch (_) {
|
|
295
|
+
return false;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
validateBaseTransactionFields() {
|
|
299
|
+
if (this._fee === undefined || (!this._fee.fee && !this._fee.gasPrice && !this._fee.eip1559)) {
|
|
300
|
+
throw new sdk_core_1.BuildTransactionError('Invalid transaction: missing fee');
|
|
301
|
+
}
|
|
302
|
+
if (this._common === undefined) {
|
|
303
|
+
throw new sdk_core_1.BuildTransactionError('Invalid transaction: network common');
|
|
304
|
+
}
|
|
305
|
+
if (this._counter === undefined) {
|
|
306
|
+
throw new sdk_core_1.BuildTransactionError('Invalid transaction: missing address counter');
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
/** @inheritdoc */
|
|
310
|
+
validateTransaction(transaction) {
|
|
311
|
+
this.validateBaseTransactionFields();
|
|
312
|
+
switch (this._type) {
|
|
313
|
+
case sdk_core_1.TransactionType.WalletInitialization:
|
|
314
|
+
this.validateWalletInitializationFields();
|
|
315
|
+
break;
|
|
316
|
+
case sdk_core_1.TransactionType.RecoveryWalletDeployment:
|
|
317
|
+
this.validateDataField();
|
|
318
|
+
break;
|
|
319
|
+
case sdk_core_1.TransactionType.Send:
|
|
320
|
+
case sdk_core_1.TransactionType.SendERC721:
|
|
321
|
+
case sdk_core_1.TransactionType.SendERC1155:
|
|
322
|
+
this.validateContractAddress();
|
|
323
|
+
break;
|
|
324
|
+
case sdk_core_1.TransactionType.AddressInitialization:
|
|
325
|
+
this.validateContractAddress();
|
|
326
|
+
break;
|
|
327
|
+
case sdk_core_1.TransactionType.FlushCoins:
|
|
328
|
+
this.validateContractAddress();
|
|
329
|
+
break;
|
|
330
|
+
case sdk_core_1.TransactionType.FlushTokens:
|
|
331
|
+
this.validateContractAddress();
|
|
332
|
+
this.validateForwarderAddress();
|
|
333
|
+
this.validateTokenAddress();
|
|
334
|
+
break;
|
|
335
|
+
case sdk_core_1.TransactionType.SingleSigSend:
|
|
336
|
+
// for single sig sends, the contract address is actually the recipient
|
|
337
|
+
this.validateContractAddress();
|
|
338
|
+
break;
|
|
339
|
+
case sdk_core_1.TransactionType.StakingLock:
|
|
340
|
+
case sdk_core_1.TransactionType.StakingUnlock:
|
|
341
|
+
case sdk_core_1.TransactionType.StakingVote:
|
|
342
|
+
case sdk_core_1.TransactionType.StakingUnvote:
|
|
343
|
+
case sdk_core_1.TransactionType.StakingActivate:
|
|
344
|
+
case sdk_core_1.TransactionType.StakingWithdraw:
|
|
345
|
+
break;
|
|
346
|
+
case sdk_core_1.TransactionType.ContractCall:
|
|
347
|
+
this.validateContractAddress();
|
|
348
|
+
this.validateDataField();
|
|
349
|
+
break;
|
|
350
|
+
default:
|
|
351
|
+
throw new sdk_core_1.BuildTransactionError('Unsupported transaction type');
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
/**
|
|
355
|
+
* Check wallet owner addresses for wallet initialization transactions are valid or throw.
|
|
356
|
+
*/
|
|
357
|
+
validateWalletInitializationFields() {
|
|
358
|
+
if (this._walletOwnerAddresses === undefined) {
|
|
359
|
+
throw new sdk_core_1.BuildTransactionError('Invalid transaction: missing wallet owners');
|
|
360
|
+
}
|
|
361
|
+
if (this._walletOwnerAddresses.length !== 3) {
|
|
362
|
+
throw new sdk_core_1.BuildTransactionError(`Invalid transaction: wrong number of owners -- required: 3, found: ${this._walletOwnerAddresses.length}`);
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
/**
|
|
366
|
+
* Check if a token address for the tx was defined or throw.
|
|
367
|
+
*/
|
|
368
|
+
validateTokenAddress() {
|
|
369
|
+
if (this._tokenAddress === undefined) {
|
|
370
|
+
throw new sdk_core_1.BuildTransactionError('Invalid transaction: missing token address');
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
/**
|
|
374
|
+
* Check if a forwarder address for the tx was defined or throw.
|
|
375
|
+
*/
|
|
376
|
+
validateForwarderAddress() {
|
|
377
|
+
if (this._forwarderAddress === undefined) {
|
|
378
|
+
throw new sdk_core_1.BuildTransactionError('Invalid transaction: missing forwarder address');
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
/**
|
|
382
|
+
* Check if a contract address for the wallet was defined or throw.
|
|
383
|
+
*/
|
|
384
|
+
validateContractAddress() {
|
|
385
|
+
if (this._contractAddress === undefined) {
|
|
386
|
+
throw new sdk_core_1.BuildTransactionError('Invalid transaction: missing contract address');
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
/**
|
|
390
|
+
* Checks if a contract call data field was defined or throws otherwise
|
|
391
|
+
*/
|
|
392
|
+
validateDataField() {
|
|
393
|
+
if (!this._data) {
|
|
394
|
+
throw new sdk_core_1.BuildTransactionError('Invalid transaction: missing contract call data field');
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
setContract(address) {
|
|
398
|
+
if (address === undefined) {
|
|
399
|
+
throw new sdk_core_1.BuildTransactionError('Undefined recipient address');
|
|
400
|
+
}
|
|
401
|
+
this.contract(address);
|
|
402
|
+
}
|
|
403
|
+
validateValue(value) {
|
|
404
|
+
if (value.isLessThan(0)) {
|
|
405
|
+
throw new sdk_core_1.BuildTransactionError('Value cannot be below less than zero');
|
|
406
|
+
}
|
|
407
|
+
// TODO: validate the amount is not bigger than the max amount in each Eth family coin
|
|
408
|
+
}
|
|
409
|
+
// region Common builder methods
|
|
410
|
+
/**
|
|
411
|
+
* The type of transaction being built.
|
|
412
|
+
*
|
|
413
|
+
* @param {TransactionType} type
|
|
414
|
+
*/
|
|
415
|
+
type(type) {
|
|
416
|
+
this._type = type;
|
|
417
|
+
}
|
|
418
|
+
/**
|
|
419
|
+
* Set the transaction fees. Low fees may get a transaction rejected or never picked up by bakers.
|
|
420
|
+
*
|
|
421
|
+
* @param {Fee} fee Baker fees. May also include the maximum gas to pay
|
|
422
|
+
*/
|
|
423
|
+
fee(fee) {
|
|
424
|
+
this.validateValue(new bignumber_js_1.default(fee.fee));
|
|
425
|
+
if (fee.gasLimit) {
|
|
426
|
+
this.validateValue(new bignumber_js_1.default(fee.gasLimit));
|
|
427
|
+
}
|
|
428
|
+
if (fee.eip1559) {
|
|
429
|
+
this.validateValue(new bignumber_js_1.default(fee.eip1559.maxFeePerGas));
|
|
430
|
+
this.validateValue(new bignumber_js_1.default(fee.eip1559.maxPriorityFeePerGas));
|
|
431
|
+
}
|
|
432
|
+
if (fee.gasPrice) {
|
|
433
|
+
this.validateValue(new bignumber_js_1.default(fee.gasPrice));
|
|
434
|
+
}
|
|
435
|
+
this._fee = fee;
|
|
436
|
+
}
|
|
437
|
+
/**
|
|
438
|
+
* Set the transaction counter to prevent submitting repeated transactions.
|
|
439
|
+
*
|
|
440
|
+
* @param {number} counter The counter to use
|
|
441
|
+
*/
|
|
442
|
+
counter(counter) {
|
|
443
|
+
if (counter < 0) {
|
|
444
|
+
throw new sdk_core_1.BuildTransactionError(`Invalid counter: ${counter}`);
|
|
445
|
+
}
|
|
446
|
+
this._counter = counter;
|
|
447
|
+
}
|
|
448
|
+
/**
|
|
449
|
+
* The value to send along with this transaction. 0 by default
|
|
450
|
+
*
|
|
451
|
+
* @param {string} value The value to send along with this transaction
|
|
452
|
+
*/
|
|
453
|
+
value(value) {
|
|
454
|
+
this._value = value;
|
|
455
|
+
}
|
|
456
|
+
// set args that are required for all types of eth transactions
|
|
457
|
+
buildBase(data) {
|
|
458
|
+
const baseParams = {
|
|
459
|
+
gasLimit: this._fee.gasLimit,
|
|
460
|
+
nonce: this._counter,
|
|
461
|
+
data: data,
|
|
462
|
+
chainId: this._common.chainIdBN().toString(),
|
|
463
|
+
value: this._value,
|
|
464
|
+
to: this._contractAddress,
|
|
465
|
+
};
|
|
466
|
+
if (this._fee.eip1559) {
|
|
467
|
+
return {
|
|
468
|
+
...baseParams,
|
|
469
|
+
_type: iface_1.ETHTransactionType.EIP1559,
|
|
470
|
+
maxFeePerGas: this._fee.eip1559.maxFeePerGas,
|
|
471
|
+
maxPriorityFeePerGas: this._fee.eip1559.maxPriorityFeePerGas,
|
|
472
|
+
};
|
|
473
|
+
}
|
|
474
|
+
else {
|
|
475
|
+
return {
|
|
476
|
+
...baseParams,
|
|
477
|
+
_type: iface_1.ETHTransactionType.LEGACY,
|
|
478
|
+
gasPrice: this._fee?.gasPrice ?? this._fee.fee,
|
|
479
|
+
v: this.getFinalV(),
|
|
480
|
+
};
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
// endregion
|
|
484
|
+
// region WalletInitialization builder methods
|
|
485
|
+
/**
|
|
486
|
+
* Set one of the owners of the multisig wallet.
|
|
487
|
+
*
|
|
488
|
+
* @param {string} address An Ethereum address
|
|
489
|
+
*/
|
|
490
|
+
owner(address) {
|
|
491
|
+
if (this._type !== sdk_core_1.TransactionType.WalletInitialization) {
|
|
492
|
+
throw new sdk_core_1.BuildTransactionError('Multisig wallet owner can only be set for initialization transactions');
|
|
493
|
+
}
|
|
494
|
+
if (this._walletOwnerAddresses.length >= DEFAULT_M) {
|
|
495
|
+
throw new sdk_core_1.BuildTransactionError('A maximum of ' + DEFAULT_M + ' owners can be set for a multisig wallet');
|
|
496
|
+
}
|
|
497
|
+
if (!(0, utils_1.isValidEthAddress)(address)) {
|
|
498
|
+
throw new sdk_core_1.BuildTransactionError('Invalid address: ' + address);
|
|
499
|
+
}
|
|
500
|
+
if (this._walletOwnerAddresses.includes(address)) {
|
|
501
|
+
throw new sdk_core_1.BuildTransactionError('Repeated owner address: ' + address);
|
|
502
|
+
}
|
|
503
|
+
this._walletOwnerAddresses.push(address);
|
|
504
|
+
}
|
|
505
|
+
/**
|
|
506
|
+
* Build a transaction for a generic multisig contract.
|
|
507
|
+
*
|
|
508
|
+
* @returns {TxData} The Ethereum transaction data
|
|
509
|
+
*/
|
|
510
|
+
buildWalletInitializationTransaction(walletVersion) {
|
|
511
|
+
const walletInitData = walletVersion === walletUtil_1.defaultWalletVersion
|
|
512
|
+
? this.getContractData(this._walletOwnerAddresses)
|
|
513
|
+
: (0, utils_1.getV1WalletInitializationData)(this._walletOwnerAddresses, this._salt);
|
|
514
|
+
return this.buildBase(walletInitData);
|
|
515
|
+
}
|
|
516
|
+
/**
|
|
517
|
+
* Returns the smart contract encoded data
|
|
518
|
+
*
|
|
519
|
+
* @param {string[]} addresses - the contract signers
|
|
520
|
+
* @returns {string} - the smart contract encoded data
|
|
521
|
+
*/
|
|
522
|
+
getContractData(addresses) {
|
|
523
|
+
const params = [addresses];
|
|
524
|
+
const resultEncodedParameters = ethereumjs_abi_1.default.rawEncode(walletUtil_1.walletSimpleConstructor, params)
|
|
525
|
+
.toString('hex')
|
|
526
|
+
.replace('0x', '');
|
|
527
|
+
return this._walletSimpleByteCode + resultEncodedParameters;
|
|
528
|
+
}
|
|
529
|
+
// endregion
|
|
530
|
+
// region Send builder methods
|
|
531
|
+
contract(address) {
|
|
532
|
+
if (!(0, utils_1.isValidEthAddress)(address)) {
|
|
533
|
+
throw new sdk_core_1.BuildTransactionError('Invalid address: ' + address);
|
|
534
|
+
}
|
|
535
|
+
this._contractAddress = address;
|
|
536
|
+
}
|
|
537
|
+
/**
|
|
538
|
+
* Returns the serialized sendMultiSig contract method data
|
|
539
|
+
*
|
|
540
|
+
* @returns {string} serialized sendMultiSig data
|
|
541
|
+
*/
|
|
542
|
+
getSendData() {
|
|
543
|
+
if (!this._transfer) {
|
|
544
|
+
throw new sdk_core_1.BuildTransactionError('Missing transfer information');
|
|
545
|
+
}
|
|
546
|
+
const chainId = this._common.chainIdBN().toString();
|
|
547
|
+
this._transfer.walletVersion(this._walletVersion);
|
|
548
|
+
// This change is made to support new contracts with different encoding type
|
|
549
|
+
return this._transfer.signAndBuild(chainId, this.coinUsesNonPackedEncodingForTxData());
|
|
550
|
+
}
|
|
551
|
+
/**
|
|
552
|
+
* Decide if the coin uses non-packed encoding for tx data
|
|
553
|
+
*
|
|
554
|
+
* @returns {boolean} true if the coin uses non-packed encoding for tx data
|
|
555
|
+
*/
|
|
556
|
+
coinUsesNonPackedEncodingForTxData() {
|
|
557
|
+
return (this._walletVersion === 4 || this._coinConfig.features.includes(statics_1.CoinFeature.USES_NON_PACKED_ENCODING_FOR_TXDATA));
|
|
558
|
+
}
|
|
559
|
+
buildSendTransaction() {
|
|
560
|
+
const sendData = this.getSendData();
|
|
561
|
+
const tx = this.buildBase(sendData);
|
|
562
|
+
tx.to = this._contractAddress;
|
|
563
|
+
return tx;
|
|
564
|
+
}
|
|
565
|
+
// endregion
|
|
566
|
+
// region AddressInitialization builder methods
|
|
567
|
+
/**
|
|
568
|
+
* Set the contract transaction nonce to calculate the forwarder address.
|
|
569
|
+
*
|
|
570
|
+
* @param {number} contractCounter The counter to use
|
|
571
|
+
*/
|
|
572
|
+
contractCounter(contractCounter) {
|
|
573
|
+
if (contractCounter < 0) {
|
|
574
|
+
throw new sdk_core_1.BuildTransactionError(`Invalid contract counter: ${contractCounter}`);
|
|
575
|
+
}
|
|
576
|
+
this._contractCounter = contractCounter;
|
|
577
|
+
}
|
|
578
|
+
/**
|
|
579
|
+
* Build a transaction to create a forwarder.
|
|
580
|
+
*
|
|
581
|
+
* @returns {TxData} The Ethereum transaction data
|
|
582
|
+
*/
|
|
583
|
+
buildAddressInitializationTransaction() {
|
|
584
|
+
const addressInitData = (0, utils_1.getAddressInitDataAllForwarderVersions)(this._forwarderVersion, this._baseAddress, this._salt, this._feeAddress);
|
|
585
|
+
const tx = this.buildBase(addressInitData);
|
|
586
|
+
tx.to = this._contractAddress;
|
|
587
|
+
if (this._contractCounter) {
|
|
588
|
+
tx.deployedAddress = (0, utils_1.calculateForwarderAddress)(this._contractAddress, this._contractCounter);
|
|
589
|
+
}
|
|
590
|
+
if (this._salt && this._initCode) {
|
|
591
|
+
const saltBuffer = ethUtil.setLengthLeft(ethUtil.toBuffer(this._salt), 32);
|
|
592
|
+
const { createForwarderParams, createForwarderTypes } = (0, utils_1.getCreateForwarderParamsAndTypes)(this._baseAddress, saltBuffer, this._feeAddress);
|
|
593
|
+
// Hash the wallet base address and fee address if present with the given salt, so the address directly relies on the base address and fee address
|
|
594
|
+
const calculationSalt = ethUtil.bufferToHex(ethereumjs_abi_1.default.soliditySHA3(createForwarderTypes, createForwarderParams));
|
|
595
|
+
tx.deployedAddress = (0, utils_1.calculateForwarderV1Address)(this._contractAddress, calculationSalt, this._initCode);
|
|
596
|
+
}
|
|
597
|
+
return tx;
|
|
598
|
+
}
|
|
599
|
+
// endregion
|
|
600
|
+
// region flush methods
|
|
601
|
+
/**
|
|
602
|
+
* Set the forwarder address to flush
|
|
603
|
+
*
|
|
604
|
+
* @param {string} address The address to flush
|
|
605
|
+
*/
|
|
606
|
+
forwarderAddress(address) {
|
|
607
|
+
if (!(0, utils_1.isValidEthAddress)(address)) {
|
|
608
|
+
throw new sdk_core_1.BuildTransactionError('Invalid address: ' + address);
|
|
609
|
+
}
|
|
610
|
+
this._forwarderAddress = address;
|
|
611
|
+
}
|
|
612
|
+
/**
|
|
613
|
+
* Set the address of the ERC20 token contract that we are flushing tokens for
|
|
614
|
+
*
|
|
615
|
+
* @param {string} address the contract address of the token to flush
|
|
616
|
+
*/
|
|
617
|
+
tokenAddress(address) {
|
|
618
|
+
if (!(0, utils_1.isValidEthAddress)(address)) {
|
|
619
|
+
throw new sdk_core_1.BuildTransactionError('Invalid address: ' + address);
|
|
620
|
+
}
|
|
621
|
+
this._tokenAddress = address;
|
|
622
|
+
}
|
|
623
|
+
/**
|
|
624
|
+
* Build a transaction to flush tokens from a forwarder.
|
|
625
|
+
*
|
|
626
|
+
* @returns {TxData} The Ethereum transaction data
|
|
627
|
+
*/
|
|
628
|
+
buildFlushTokensTransaction() {
|
|
629
|
+
if (this._forwarderVersion >= 4 && this._contractAddress !== this._forwarderAddress) {
|
|
630
|
+
throw new sdk_core_1.BuildTransactionError('Invalid contract address: ' + this._contractAddress);
|
|
631
|
+
}
|
|
632
|
+
return this.buildBase((0, utils_1.flushTokensData)(this._forwarderAddress, this._tokenAddress, this._forwarderVersion));
|
|
633
|
+
}
|
|
634
|
+
/**
|
|
635
|
+
* Build a transaction to flush tokens from a forwarder.
|
|
636
|
+
*
|
|
637
|
+
* @returns {TxData} The Ethereum transaction data
|
|
638
|
+
*/
|
|
639
|
+
buildFlushCoinsTransaction() {
|
|
640
|
+
return this.buildBase((0, utils_1.flushCoinsData)());
|
|
641
|
+
}
|
|
642
|
+
// endregion
|
|
643
|
+
// region generic contract call
|
|
644
|
+
data(encodedCall) {
|
|
645
|
+
const supportedTransactionTypes = [sdk_core_1.TransactionType.ContractCall, sdk_core_1.TransactionType.RecoveryWalletDeployment];
|
|
646
|
+
if (!supportedTransactionTypes.includes(this._type)) {
|
|
647
|
+
throw new sdk_core_1.BuildTransactionError('data can only be set for contract call transaction types');
|
|
648
|
+
}
|
|
649
|
+
this._data = encodedCall;
|
|
650
|
+
}
|
|
651
|
+
buildGenericContractCallTransaction() {
|
|
652
|
+
return this.buildBase(this._data);
|
|
653
|
+
}
|
|
654
|
+
// endregion
|
|
655
|
+
/** @inheritdoc */
|
|
656
|
+
get transaction() {
|
|
657
|
+
return this._transaction;
|
|
658
|
+
}
|
|
659
|
+
/** @inheritdoc */
|
|
660
|
+
set transaction(transaction) {
|
|
661
|
+
this._transaction = transaction;
|
|
662
|
+
}
|
|
663
|
+
/**
|
|
664
|
+
* Get the final v value. Final v is described in EIP-155.
|
|
665
|
+
*
|
|
666
|
+
* @protected for internal use when the enableFinalVField flag is true.
|
|
667
|
+
*/
|
|
668
|
+
getFinalV() {
|
|
669
|
+
return ethUtil.addHexPrefix(this._common.chainIdBN().muln(2).addn(35).toString(16));
|
|
670
|
+
}
|
|
671
|
+
/**
|
|
672
|
+
* Set the forwarder version for address to be initialized
|
|
673
|
+
*
|
|
674
|
+
* @param {number} version forwarder version
|
|
675
|
+
*/
|
|
676
|
+
forwarderVersion(version) {
|
|
677
|
+
if (version < 0 || version > 4 || version === 3) {
|
|
678
|
+
throw new sdk_core_1.BuildTransactionError(`Invalid forwarder version: ${version}`);
|
|
679
|
+
}
|
|
680
|
+
this._forwarderVersion = version;
|
|
681
|
+
}
|
|
682
|
+
/**
|
|
683
|
+
* Set the salt to create the address using create2
|
|
684
|
+
*
|
|
685
|
+
* @param {string} salt The salt to create the address using create2, hex string
|
|
686
|
+
*/
|
|
687
|
+
salt(salt) {
|
|
688
|
+
this._salt = salt;
|
|
689
|
+
}
|
|
690
|
+
/**
|
|
691
|
+
* Take the implementation address for the proxy contract, and get the binary initcode for the associated proxy
|
|
692
|
+
*
|
|
693
|
+
* @param {string} implementationAddress The address of the implementation contract
|
|
694
|
+
*/
|
|
695
|
+
initCode(implementationAddress) {
|
|
696
|
+
if (!(0, utils_1.isValidEthAddress)(implementationAddress)) {
|
|
697
|
+
throw new sdk_core_1.BuildTransactionError('Invalid address: ' + implementationAddress);
|
|
698
|
+
}
|
|
699
|
+
this._initCode = (0, utils_1.getProxyInitcode)(implementationAddress);
|
|
700
|
+
}
|
|
701
|
+
/**
|
|
702
|
+
* Set the wallet version for wallet to be initialized
|
|
703
|
+
*
|
|
704
|
+
* @param {number} version wallet version
|
|
705
|
+
*/
|
|
706
|
+
walletVersion(version) {
|
|
707
|
+
if (version < 0 || version > 4 || version === 3) {
|
|
708
|
+
throw new sdk_core_1.BuildTransactionError(`Invalid wallet version: ${version}`);
|
|
709
|
+
}
|
|
710
|
+
this._walletVersion = version;
|
|
711
|
+
}
|
|
712
|
+
/**
|
|
713
|
+
* Set the base address of the wallet
|
|
714
|
+
*
|
|
715
|
+
* @param {string} address The wallet contract address
|
|
716
|
+
*/
|
|
717
|
+
baseAddress(address) {
|
|
718
|
+
if (!(0, utils_1.isValidEthAddress)(address)) {
|
|
719
|
+
throw new sdk_core_1.BuildTransactionError('Invalid address: ' + address);
|
|
720
|
+
}
|
|
721
|
+
this._baseAddress = address;
|
|
722
|
+
}
|
|
723
|
+
/**
|
|
724
|
+
* Set the fee address of the wallet
|
|
725
|
+
*
|
|
726
|
+
* @param {string} address The fee address of the wallet
|
|
727
|
+
*/
|
|
728
|
+
feeAddress(address) {
|
|
729
|
+
if (!(0, utils_1.isValidEthAddress)(address)) {
|
|
730
|
+
throw new sdk_core_1.BuildTransactionError('Invalid address: ' + address);
|
|
731
|
+
}
|
|
732
|
+
this._feeAddress = address;
|
|
733
|
+
}
|
|
734
|
+
/**
|
|
735
|
+
* Get the wallet version for wallet
|
|
736
|
+
*/
|
|
737
|
+
getWalletVersion() {
|
|
738
|
+
return this._walletVersion;
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
exports.TransactionBuilder = TransactionBuilder;
|
|
742
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhbnNhY3Rpb25CdWlsZGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2xpYi90cmFuc2FjdGlvbkJ1aWxkZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsNENBQXNGO0FBRXRGLG9FQUF5QztBQUN6QyxnRUFBcUM7QUFDckMseURBQTJDO0FBQzNDLHVDQUE2RDtBQUU3RCw4Q0FZeUI7QUFFekIsdUNBQW9DO0FBQ3BDLG1DQUEwRTtBQUMxRSxtQ0FnQmlCO0FBQ2pCLDZDQUE2RTtBQUc3RSwrQ0FBNEM7QUFHNUMsTUFBTSxTQUFTLEdBQUcsQ0FBQyxDQUFDO0FBRXBCOztHQUVHO0FBQ0gsTUFBc0Isa0JBQW1CLFNBQVEsaUNBQXNCO0lBd0NyRTs7OztPQUlHO0lBQ0gsWUFBWSxXQUFpQztRQUMzQyxLQUFLLENBQUMsV0FBVyxDQUFDLENBQUM7UUFDbkIsSUFBSSxDQUFDLE9BQU8sR0FBRyxJQUFBLGlCQUFTLEVBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxPQUEwQixDQUFDLENBQUM7UUFDdEUsSUFBSSxDQUFDLEtBQUssR0FBRywwQkFBZSxDQUFDLElBQUksQ0FBQztRQUNsQyxJQUFJLENBQUMsUUFBUSxHQUFHLENBQUMsQ0FBQztRQUNsQixJQUFJLENBQUMsTUFBTSxHQUFHLEdBQUcsQ0FBQztRQUNsQixJQUFJLENBQUMscUJBQXFCLEdBQUcsRUFBRSxDQUFDO1FBQ2hDLElBQUksQ0FBQyxpQkFBaUIsR0FBRyxDQUFDLENBQUM7UUFDM0IsSUFBSSxDQUFDLGNBQWMsR0FBRyxDQUFDLENBQUM7UUFDeEIsSUFBSSxDQUFDLFdBQVcsR0FBRyxJQUFJLHlCQUFXLENBQUMsSUFBSSxDQUFDLFdBQVcsRUFBRSxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDbkUsSUFBSSxDQUFDLHFCQUFxQixHQUFHLEVBQUUsQ0FBQztJQUNsQyxDQUFDO0lB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QUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztZQUNoQyxNQUFNLElBQUksZ0NBQXFCLENBQUMsbUJBQW1CLEdBQUcsT0FBTyxDQUFDLENBQUM7UUFDakUsQ0FBQztRQUNELElBQUksQ0FBQyxZQUFZLEdBQUcsT0FBTyxDQUFDO0lBQzlCLENBQUM7SUFFRDs7OztPQUlHO0lBQ0gsVUFBVSxDQUFDLE9BQWU7UUFDeEIsSUFBSSxDQUFDLElBQUEseUJBQWlCLEVBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztZQUNoQyxNQUFNLElBQUksZ0NBQXFCLENBQUMsbUJBQW1CLEdBQUcsT0FBTyxDQUFDLENBQUM7UUFDakUsQ0FBQztRQUNELElBQUksQ0FBQyxXQUFXLEdBQUcsT0FBTyxDQUFDO0lBQzdCLENBQUM7SUFFRDs7T0FFRztJQUNJLGdCQUFnQjtRQUNyQixPQUFPLElBQUksQ0FBQyxjQUFjLENBQUM7SUFDN0IsQ0FBQztDQUNGO0FBdnpCRCxnREF1ekJDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQmFzZUNvaW4gYXMgQ29pbkNvbmZpZywgRXRoZXJldW1OZXR3b3JrLCBDb2luRmVhdHVyZSB9IGZyb20gJ0BiaXRnby9zdGF0aWNzJztcbmltcG9ydCBFdGhlcmV1bUNvbW1vbiBmcm9tICdAZXRoZXJldW1qcy9jb21tb24nO1xuaW1wb3J0IEV0aGVyZXVtQWJpIGZyb20gJ2V0aGVyZXVtanMtYWJpJztcbmltcG9ydCBCaWdOdW1iZXIgZnJvbSAnYmlnbnVtYmVyLmpzJztcbmltcG9ydCAqIGFzIGV0aFV0aWwgZnJvbSAnZXRoZXJldW1qcy11dGlsJztcbmltcG9ydCB7IEZlZU1hcmtldEVJUDE1NTlUcmFuc2FjdGlvbiB9IGZyb20gJ0BldGhlcmV1bWpzL3R4JztcblxuaW1wb3J0IHtcbiAgQmFzZUFkZHJlc3MsXG4gIEJhc2VLZXksXG4gIEJhc2VUcmFuc2FjdGlvbixcbiAgQmFzZVRyYW5zYWN0aW9uQnVpbGRlcixcbiAgQnVpbGRUcmFuc2FjdGlvbkVycm9yLFxuICBJbnZhbGlkVHJhbnNhY3Rpb25FcnJvcixcbiAgaXNWYWxpZFBydixcbiAgaXNWYWxpZFhwcnYsXG4gIFBhcnNlVHJhbnNhY3Rpb25FcnJvcixcbiAgU2lnbmluZ0Vycm9yLFxuICBUcmFuc2FjdGlvblR5cGUsXG59IGZyb20gJ0BiaXRnby9zZGstY29yZSc7XG5cbmltcG9ydCB7IEtleVBhaXIgfSBmcm9tICcuL2tleVBhaXInO1xuaW1wb3J0IHsgRVRIVHJhbnNhY3Rpb25UeXBlLCBGZWUsIFNpZ25hdHVyZVBhcnRzLCBUeERhdGEgfSBmcm9tICcuL2lmYWNlJztcbmltcG9ydCB7XG4gIGNhbGN1bGF0ZUZvcndhcmRlckFkZHJlc3MsXG4gIGNhbGN1bGF0ZUZvcndhcmRlclYxQWRkcmVzcyxcbiAgY2xhc3NpZnlUcmFuc2FjdGlvbixcbiAgZGVjb2RlRm9yd2FyZGVyQ3JlYXRpb25EYXRhLFxuICBkZWNvZGVGbHVzaFRva2Vuc0RhdGEsXG4gIGRlY29kZVdhbGxldENyZWF0aW9uRGF0YSxcbiAgZmx1c2hDb2luc0RhdGEsXG4gIGZsdXNoVG9rZW5zRGF0YSxcbiAgZ2V0QWRkcmVzc0luaXREYXRhQWxsRm9yd2FyZGVyVmVyc2lvbnMsXG4gIGdldENvbW1vbixcbiAgZ2V0UHJveHlJbml0Y29kZSxcbiAgaGFzU2lnbmF0dXJlLFxuICBpc1ZhbGlkRXRoQWRkcmVzcyxcbiAgZ2V0VjFXYWxsZXRJbml0aWFsaXphdGlvbkRhdGEsXG4gIGdldENyZWF0ZUZvcndhcmRlclBhcmFtc0FuZFR5cGVzLFxufSBmcm9tICcuL3V0aWxzJztcbmltcG9ydCB7IGRlZmF1bHRXYWxsZXRWZXJzaW9uLCB3YWxsZXRTaW1wbGVDb25zdHJ1Y3RvciB9IGZyb20gJy4vd2FsbGV0VXRpbCc7XG5pbXBvcnQgeyBFUkMxMTU1VHJhbnNmZXJCdWlsZGVyIH0gZnJvbSAnLi90cmFuc2ZlckJ1aWxkZXJzL3RyYW5zZmVyQnVpbGRlckVSQzExNTUnO1xuaW1wb3J0IHsgRVJDNzIxVHJhbnNmZXJCdWlsZGVyIH0gZnJvbSAnLi90cmFuc2ZlckJ1aWxkZXJzL3RyYW5zZmVyQnVpbGRlckVSQzcyMSc7XG5pbXBvcnQgeyBUcmFuc2FjdGlvbiB9IGZyb20gJy4vdHJhbnNhY3Rpb24nO1xuaW1wb3J0IHsgVHJhbnNmZXJCdWlsZGVyIH0gZnJvbSAnLi90cmFuc2ZlckJ1aWxkZXInO1xuXG5jb25zdCBERUZBVUxUX00gPSAzO1xuXG4vKipcbiAqIEV0aGVyZXVtTGlrZSB0cmFuc2FjdGlvbiBidWlsZGVyLlxuICovXG5leHBvcnQgYWJzdHJhY3QgY2xhc3MgVHJhbnNhY3Rpb25CdWlsZGVyIGV4dGVuZHMgQmFzZVRyYW5zYWN0aW9uQnVpbGRlciB7XG4gIHByb3RlY3RlZCBfdHlwZTogVHJhbnNhY3Rpb25UeXBlO1xuICAvLyBTcGVjaWZpZXMgY29tbW9uIGNoYWluIGFuZCBoYXJkZm9yayBwYXJhbWV0ZXJzLlxuICBwcm90ZWN0ZWQgX2NvbW1vbjogRXRoZXJldW1Db21tb247XG4gIHByb3RlY3RlZCBfc291cmNlS2V5UGFpcjogS2V5UGFpcjtcbiAgcHJpdmF0ZSBfdHJhbnNhY3Rpb246IFRyYW5zYWN0aW9uO1xuICBwcml2YXRlIF9jb3VudGVyOiBudW1iZXI7XG4gIHByaXZhdGUgX2ZlZTogRmVlO1xuICBwcm90ZWN0ZWQgX3ZhbHVlOiBzdHJpbmc7XG5cbiAgLy8gdGhlIHNpZ25hdHVyZSBvbiB0aGUgZXh0ZXJuYWwgRVRIIHRyYW5zYWN0aW9uXG4gIHByaXZhdGUgX3R4U2lnbmF0dXJlOiBTaWduYXR1cmVQYXJ0cztcblxuICAvLyBXYWxsZXQgaW5pdGlhbGl6YXRpb24gdHJhbnNhY3Rpb24gcGFyYW1ldGVyc1xuICBwcml2YXRlIF93YWxsZXRPd25lckFkZHJlc3Nlczogc3RyaW5nW107XG4gIHByb3RlY3RlZCBfd2FsbGV0VmVyc2lvbjogbnVtYmVyO1xuXG4gIC8vIGZsdXNoIHRva2VucyBwYXJhbWV0ZXJzXG4gIHByaXZhdGUgX2ZvcndhcmRlckFkZHJlc3M6IHN0cmluZztcbiAgcHJpdmF0ZSBfdG9rZW5BZGRyZXNzOiBzdHJpbmc7XG5cbiAgLy8gU2VuZCBhbmQgQWRkcmVzc0luaXRpYWxpemF0aW9uIHRyYW5zYWN0aW9uIHNwZWNpZmljIHBhcmFtZXRlcnNcbiAgcHJvdGVjdGVkIF90cmFuc2ZlcjogVHJhbnNmZXJCdWlsZGVyIHwgRVJDNzIxVHJhbnNmZXJCdWlsZGVyIHwgRVJDMTE1NVRyYW5zZmVyQnVpbGRlcjtcbiAgcHJpdmF0ZSBfY29udHJhY3RBZGRyZXNzOiBzdHJpbmc7XG4gIHByaXZhdGUgX2NvbnRyYWN0Q291bnRlcjogbnVtYmVyO1xuICBwcml2YXRlIF9mb3J3YXJkZXJWZXJzaW9uOiBudW1iZXI7XG4gIHByaXZhdGUgX2luaXRDb2RlOiBzdHJpbmc7XG4gIHByaXZhdGUgX2Jhc2VBZGRyZXNzOiBzdHJpbmc7XG4gIHByaXZhdGUgX2ZlZUFkZHJlc3M6IHN0cmluZztcblxuICAvLyBnZW5lcmljIGNvbnRyYWN0IGNhbGwgYnVpbGRlclxuICAvLyBlbmNvZGVkIGNvbnRyYWN0IGNhbGwgaGV4XG4gIHByaXZhdGUgX2RhdGE6IHN0cmluZztcblxuICAvLyBDb21tb24gcGFyYW1ldGVyIGZvciB3YWxsZXQgaW5pdGlhbGl6YXRpb24gYW5kIGFkZHJlc3MgaW5pdGlhbGl6YXRpb24gdHJhbnNhY3Rpb25cbiAgcHJpdmF0ZSBfc2FsdDogc3RyaW5nO1xuXG4gIC8vIHdhbGxldHNpbXBsZWJ5dGVjb2RlXG4gIHByb3RlY3RlZCBfd2FsbGV0U2ltcGxlQnl0ZUNvZGU6IHN0cmluZztcblxuICAvKipcbiAgICogUHVibGljIGNvbnN0cnVjdG9yLlxuICAgKlxuICAgKiBAcGFyYW0gX2NvaW5Db25maWdcbiAgICovXG4gIGNvbnN0cnVjdG9yKF9jb2luQ29uZmlnOiBSZWFkb25seTxDb2luQ29uZmlnPikge1xuICAgIHN1cGVyKF9jb2luQ29uZmlnKTtcbiAgICB0aGlzLl9jb21tb24gPSBnZXRDb21tb24odGhpcy5fY29pbkNvbmZpZy5uZXR3b3JrIGFzIEV0aGVyZXVtTmV0d29yayk7XG4gICAgdGhpcy5fdHlwZSA9IFRyYW5zYWN0aW9uVHlwZS5TZW5kO1xuICAgIHRoaXMuX2NvdW50ZXIgPSAwO1xuICAgIHRoaXMuX3ZhbHVlID0gJzAnO1xuICAgIHRoaXMuX3dhbGxldE93bmVyQWRkcmVzc2VzID0gW107XG4gICAgdGhpcy5fZm9yd2FyZGVyVmVyc2lvbiA9IDA7XG4gICAgdGhpcy5fd2FsbGV0VmVyc2lvbiA9IDA7XG4gICAgdGhpcy50cmFuc2FjdGlvbiA9IG5ldyBUcmFuc2FjdGlvbih0aGlzLl9jb2luQ29uZmlnLCB0aGlzLl9jb21tb24pO1xuICAgIHRoaXMuX3dhbGxldFNpbXBsZUJ5dGVDb2RlID0gJyc7XG4gIH1cblxuICAvKiogQGluaGVyaXRkb2MgKi9cbiAgcHJvdGVjdGVkIGFzeW5jIGJ1aWxkSW1wbGVtZW50YXRpb24oKTogUHJvbWlzZTxCYXNlVHJhbnNhY3Rpb24+IHtcbiAgICBjb25zdCB0cmFuc2FjdGlvbkRhdGEgPSB0aGlzLmdldFRyYW5zYWN0aW9uRGF0YSgpO1xuXG4gICAgaWYgKHRoaXMuX3R4U2lnbmF0dXJlKSB7XG4gICAgICBPYmplY3QuYXNzaWduKHRyYW5zYWN0aW9uRGF0YSwgdGhpcy5fdHhTaWduYXR1cmUpO1xuICAgIH1cblxuICAgIHRoaXMudHJhbnNhY3Rpb24uc2V0VHJhbnNhY3Rpb25UeXBlKHRoaXMuX3R5cGUpO1xuICAgIHRyYW5zYWN0aW9uRGF0YS5mcm9tID0gdGhpcy5fc291cmNlS2V5UGFpciA/IHRoaXMuX3NvdXJjZUtleVBhaXIuZ2V0QWRkcmVzcygpIDogdW5kZWZpbmVkO1xuICAgIHRoaXMudHJhbnNhY3Rpb24uc2V0VHJhbnNhY3Rpb25EYXRhKFxuICAgICAgdHJhbnNhY3Rpb25EYXRhLFxuICAgICAgdGhpcy5fdHJhbnNmZXIgPyB0aGlzLl90cmFuc2Zlci5nZXRJc0ZpcnN0U2lnbmVyKCkgOiB1bmRlZmluZWRcbiAgICApO1xuICAgIC8vIEJ1aWxkIGFuZCBzaWduIGEgbmV3IHRyYW5zYWN0aW9uIGJhc2VkIG9uIHRoZSBsYXRlc3QgY2hhbmdlc1xuICAgIGlmICh0aGlzLl9zb3VyY2VLZXlQYWlyICYmIHRoaXMuX3NvdXJjZUtleVBhaXIuZ2V0S2V5cygpLnBydikge1xuICAgICAgYXdhaXQgdGhpcy50cmFuc2FjdGlvbi5zaWduKHRoaXMuX3NvdXJjZUtleVBhaXIpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy50cmFuc2FjdGlvbjtcbiAgfVxuXG4gIHByb3RlY3RlZCBnZXRUcmFuc2FjdGlvbkRhdGEoKTogVHhEYXRhIHtcbiAgICBzd2l0Y2ggKHRoaXMuX3R5cGUpIHtcbiAgICAgIGNhc2UgVHJhbnNhY3Rpb25UeXBlLldhbGxldEluaXRpYWxpemF0aW9uOlxuICAgICAgICByZXR1cm4gdGhpcy5idWlsZFdhbGxldEluaXRpYWxpemF0aW9uVHJhbnNhY3Rpb24odGhpcy5fd2FsbGV0VmVyc2lvbik7XG4gICAgICBjYXNlIFRyYW5zYWN0aW9uVHlwZS5SZWNvdmVyeVdhbGxldERlcGxveW1lbnQ6XG4gICAgICAgIHJldHVybiB0aGlzLmJ1aWxkQmFzZSh0aGlzLl9kYXRhKTtcbiAgICAgIGNhc2UgVHJhbnNhY3Rpb25UeXBlLlNlbmQ6XG4gICAgICBjYXNlIFRyYW5zYWN0aW9uVHlwZS5TZW5kRVJDNzIxOlxuICAgICAgY2FzZSBUcmFuc2FjdGlvblR5cGUuU2VuZEVSQzExNTU6XG4gICAgICAgIHJldHVybiB0aGlzLmJ1aWxkU2VuZFRyYW5zYWN0aW9uKCk7XG4gICAgICBjYXNlIFRyYW5zYWN0aW9uVHlwZS5BZGRyZXNzSW5pdGlhbGl6YXRpb246XG4gICAgICAgIHJldHVybiB0aGlzLmJ1aWxkQWRkcmVzc0luaXRpYWxpemF0aW9uVHJhbnNhY3Rpb24oKTtcbiAgICAgIGNhc2UgVHJhbnNhY3Rpb25UeXBlLkZsdXNoVG9rZW5zOlxuICAgICAgICByZXR1cm4gdGhpcy5idWlsZEZsdXNoVG9rZW5zVHJhbnNhY3Rpb24oKTtcbiAgICAgIGNhc2UgVHJhbnNhY3Rpb25UeXBlLkZsdXNoQ29pbnM6XG4gICAgICAgIHJldHVybiB0aGlzLmJ1aWxkRmx1c2hDb2luc1RyYW5zYWN0aW9uKCk7XG4gICAgICBjYXNlIFRyYW5zYWN0aW9uVHlwZS5TaW5nbGVTaWdTZW5kOlxuICAgICAgICByZXR1cm4gdGhpcy5idWlsZEJhc2UoJzB4Jyk7XG4gICAgICBjYXNlIFRyYW5zYWN0aW9uVHlwZS5Db250cmFjdENhbGw6XG4gICAgICAgIHJldHVybiB0aGlzLmJ1aWxkR2VuZXJpY0NvbnRyYWN0Q2FsbFRyYW5zYWN0aW9uKCk7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyBuZXcgQnVpbGRUcmFuc2FjdGlvbkVycm9yKCdVbnN1cHBvcnRlZCB0cmFuc2FjdGlvbiB0eXBlJyk7XG4gICAgfVxuICB9XG5cbiAgLyoqIEBpbmhlcml0ZG9jICovXG4gIHByb3RlY3RlZCBmcm9tSW1wbGVtZW50YXRpb24ocmF3VHJhbnNhY3Rpb246IHN0cmluZywgaXNGaXJzdFNpZ25lcj86IGJvb2xlYW4pOiBUcmFuc2FjdGlvbiB7XG4gICAgbGV0IHR4OiBUcmFuc2FjdGlvbjtcbiAgICBpZiAoL14weD9bMC05YS1mXXsxLH0kLy50ZXN0KHJhd1RyYW5zYWN0aW9uLnRvTG93ZXJDYXNlKCkpKSB7XG4gICAgICB0eCA9IFRyYW5zYWN0aW9uLmZyb21TZXJpYWxpemVkKHRoaXMuX2NvaW5Db25maWcsIHRoaXMuX2NvbW1vbiwgcmF3VHJhbnNhY3Rpb24sIGlzRmlyc3RTaWduZXIpO1xuICAgICAgdGhpcy5sb2FkQnVpbGRlcklucHV0KHR4LnRvSnNvbigpLCBpc0ZpcnN0U2lnbmVyKTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc3QgdHhEYXRhID0gSlNPTi5wYXJzZShyYXdUcmFuc2FjdGlvbik7XG4gICAgICB0eCA9IG5ldyBUcmFuc2FjdGlvbih0aGlzLl9jb2luQ29uZmlnLCB0eERhdGEpO1xuICAgIH1cbiAgICByZXR1cm4gdHg7XG4gIH1cblxuICAvKipcbiAgICogTG9hZCB0aGUgYnVpbGRlciBkYXRhIHVzaW5nIHRoZSBkZXNlcmlhbGl6ZWQgdHJhbnNhY3Rpb25cbiAgICpcbiAgICogQHBhcmFtIHtUeERhdGF9IHRyYW5zYWN0aW9uSnNvbiB0aGUgZGVzZXJpYWxpemVkIHRyYW5zYWN0aW9uIGpzb25cbiAgICogQHBhcmFtIHtib29sZWFufSBpc0ZpcnN0U2lnbmVyIGlmIHRoZSB0cmFuc2FjdGlvbiBpcyBiZWluZyBzaWduZWQgYnkgdGhlIGZpcnN0IHNpZ25lclxuICAgKi9cbiAgcHJvdGVjdGVkIGxvYWRCdWlsZGVySW5wdXQodHJhbnNhY3Rpb25Kc29uOiBUeERhdGEsIGlzRmlyc3RTaWduZXI/OiBib29sZWFuKTogdm9pZCB7XG4gICAgY29uc3QgZGVjb2RlZFR5cGUgPSBjbGFzc2lmeVRyYW5zYWN0aW9uKHRyYW5zYWN0aW9uSnNvbi5kYXRhKTtcbiAgICB0aGlzLnR5cGUoZGVjb2RlZFR5cGUpO1xuICAgIHRoaXMuY291bnRlcih0cmFuc2FjdGlvbkpzb24ubm9uY2UpO1xuICAgIHRoaXMudmFsdWUodHJhbnNhY3Rpb25Kc29uLnZhbHVlKTtcblxuICAgIGlmICh0cmFuc2FjdGlvbkpzb24uX3R5cGUgPT09IEVUSFRyYW5zYWN0aW9uVHlwZS5MRUdBQ1kpIHtcbiAgICAgIHRoaXMuZmVlKHtcbiAgICAgICAgZmVlOiB0cmFuc2FjdGlvbkpzb24uZ2FzUHJpY2UsXG4gICAgICAgIGdhc1ByaWNlOiB0cmFuc2FjdGlvbkpzb24uZ2FzUHJpY2UsXG4gICAgICAgIGdhc0xpbWl0OiB0cmFuc2FjdGlvbkpzb24uZ2FzTGltaXQsXG4gICAgICB9KTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5mZWUoe1xuICAgICAgICBnYXNMaW1pdDogdHJhbnNhY3Rpb25Kc29uLmdhc0xpbWl0LFxuICAgICAgICBmZWU6IHRyYW5zYWN0aW9uSnNvbi5tYXhGZWVQZXJHYXMsXG4gICAgICAgIGVpcDE1NTk6IHtcbiAgICAgICAgICBtYXhGZWVQZXJHYXM6IHRyYW5zYWN0aW9uSnNvbi5tYXhGZWVQZXJHYXMsXG4gICAgICAgICAgbWF4UHJpb3JpdHlGZWVQZXJHYXM6IHRyYW5zYWN0aW9uSnNvbi5tYXhQcmlvcml0eUZlZVBlckdhcyxcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGlmIChoYXNTaWduYXR1cmUodHJhbnNhY3Rpb25Kc29uKSkge1xuICAgICAgdGhpcy5fdHhTaWduYXR1cmUgPSB7IHY6IHRyYW5zYWN0aW9uSnNvbi52ISwgcjogdHJhbnNhY3Rpb25Kc29uLnIhLCBzOiB0cmFuc2FjdGlvbkpzb24ucyEgfTtcbiAgICB9XG4gICAgdGhpcy5zZXRUcmFuc2FjdGlvblR5cGVGaWVsZHMoZGVjb2RlZFR5cGUsIHRyYW5zYWN0aW9uSnNvbiwgaXNGaXJzdFNpZ25lcik7XG4gIH1cblxuICBwcm90ZWN0ZWQgc2V0VHJhbnNhY3Rpb25UeXBlRmllbGRzKFxuICAgIGRlY29kZWRUeXBlOiBUcmFuc2FjdGlvblR5cGUsXG4gICAgdHJhbnNhY3Rpb25Kc29uOiBUeERhdGEsXG4gICAgaXNGaXJzdFNpZ25lcj86IGJvb2xlYW5cbiAgKTogdm9pZCB7XG4gICAgc3dpdGNoIChkZWNvZGVkVHlwZSkge1xuICAgICAgY2FzZSBUcmFuc2FjdGlvblR5cGUuV2FsbGV0SW5pdGlhbGl6YXRpb246XG4gICAgICAgIGNvbnN0IHsgb3duZXJzLCBzYWx0IH0gPSBkZWNvZGVXYWxsZXRDcmVhdGlvbkRhdGEodHJhbnNhY3Rpb25Kc29uLmRhdGEpO1xuICAgICAgICBvd25lcnMuZm9yRWFjaCgoZWxlbWVudCkgPT4ge1xuICAgICAgICAgIHRoaXMub3duZXIoZWxlbWVudCk7XG4gICAgICAgIH0pO1xuICAgICAgICBpZiAoc2FsdCkge1xuICAgICAgICAgIHRoaXMuc2FsdChzYWx0IGFzIHN0cmluZyk7XG4gICAgICAgICAgdGhpcy53YWxsZXRWZXJzaW9uKDEpO1xuICAgICAgICAgIHRoaXMuc2V0Q29udHJhY3QodHJhbnNhY3Rpb25Kc29uLnRvKTtcbiAgICAgICAgfVxuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgVHJhbnNhY3Rpb25UeXBlLlJlY292ZXJ5V2FsbGV0RGVwbG95bWVudDpcbiAgICAgICAgdGhpcy5kYXRhKHRyYW5zYWN0aW9uSnNvbi5kYXRhKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIFRyYW5zYWN0aW9uVHlwZS5GbHVzaFRva2VuczpcbiAgICAgICAgdGhpcy5zZXRDb250cmFjdCh0cmFuc2FjdGlvbkpzb24udG8pO1xuICAgICAgICBjb25zdCB7IGZvcndhcmRlckFkZHJlc3MsIHRva2VuQWRkcmVzcywgZm9yd2FyZGVyVmVyc2lvbiB9ID0gZGVjb2RlRmx1c2hUb2tlbnNEYXRhKFxuICAgICAgICAgIHRyYW5zYWN0aW9uSnNvbi5kYXRhLFxuICAgICAgICAgIHRyYW5zYWN0aW9uSnNvbi50b1xuICAgICAgICApO1xuICAgICAgICBpZiAoZm9yd2FyZGVyVmVyc2lvbiA9PT0gNCkge1xuICAgICAgICAgIHRoaXMuZm9yd2FyZGVyVmVyc2lvbig0KTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmZvcndhcmRlckFkZHJlc3MoZm9yd2FyZGVyQWRkcmVzcyk7XG4gICAgICAgIHRoaXMudG9rZW5BZGRyZXNzKHRva2VuQWRkcmVzcyk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBUcmFuc2FjdGlvblR5cGUuRmx1c2hDb2luczpcbiAgICAgICAgdGhpcy5zZXRDb250cmFjdCh0cmFuc2FjdGlvbkpzb24udG8pO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgVHJhbnNhY3Rpb25UeXBlLlNlbmQ6XG4gICAgICBjYXNlIFRyYW5zYWN0aW9uVHlwZS5TZW5kRVJDMTE1NTpcbiAgICAgIGNhc2UgVHJhbnNhY3Rpb25UeXBlLlNlbmRFUkM3MjE6XG4gICAgICAgIHRoaXMuc2V0Q29udHJhY3QodHJhbnNhY3Rpb25Kc29uLnRvKTtcbiAgICAgICAgdGhpcy5fdHJhbnNmZXIgPSB0aGlzLnRyYW5zZmVyKHRyYW5zYWN0aW9uSnNvbi5kYXRhLCBpc0ZpcnN0U2lnbmVyKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIFRyYW5zYWN0aW9uVHlwZS5BZGRyZXNzSW5pdGlhbGl6YXRpb246XG4gICAgICAgIHRoaXMuc2V0Q29udHJhY3QodHJhbnNhY3Rpb25Kc29uLnRvKTtcbiAgICAgICAgY29uc3QgeyBiYXNlQWRkcmVzcywgYWRkcmVzc0NyZWF0aW9uU2FsdCwgZmVlQWRkcmVzcyB9ID0gZGVjb2RlRm9yd2FyZGVyQ3JlYXRpb25EYXRhKHRyYW5zYWN0aW9uSnNvbi5kYXRhKTtcbiAgICAgICAgaWYgKGJhc2VBZGRyZXNzICYmIGFkZHJlc3NDcmVhdGlvblNhbHQpIHtcbiAgICAgICAgICB0aGlzLmJhc2VBZGRyZXNzKGJhc2VBZGRyZXNzKTtcbiAgICAgICAgICB0aGlzLnNhbHQoYWRkcmVzc0NyZWF0aW9uU2FsdCk7XG4gICAgICAgICAgaWYgKGZlZUFkZHJlc3MpIHtcbiAgICAgICAgICAgIHRoaXMuZmVlQWRkcmVzcyhmZWVBZGRyZXNzKTtcbiAgICAgICAgICAgIHRoaXMuZm9yd2FyZGVyVmVyc2lvbig0KTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5mb3J3YXJkZXJWZXJzaW9uKDEpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBjb25zdCBmb3J3YXJkZXJJbXBsZW1lbnRhdGlvbkFkZHJlc3MgPSAodGhpcy5fY29pbkNvbmZpZy5uZXR3b3JrIGFzIEV0aGVyZXVtTmV0d29yaylcbiAgICAgICAgICAgIC5mb3J3YXJkZXJJbXBsZW1lbnRhdGlvbkFkZHJlc3MgYXMgc3RyaW5nO1xuICAgICAgICAgIGlmIChmb3J3YXJkZXJJbXBsZW1lbnRhdGlvbkFkZHJlc3MpIHtcbiAgICAgICAgICAgIHRoaXMuaW5pdENvZGUoZm9yd2FyZGVySW1wbGVtZW50YXRpb25BZGRyZXNzKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIFRyYW5zYWN0aW9uVHlwZS5TaW5nbGVTaWdTZW5kOlxuICAgICAgICB0aGlzLnNldENvbnRyYWN0KHRyYW5zYWN0aW9uSnNvbi50byk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBUcmFuc2FjdGlvblR5cGUuQ29udHJhY3RDYWxsOlxuICAgICAgICB0aGlzLnNldENvbnRyYWN0KHRyYW5zYWN0aW9uSnNvbi50byk7XG4gICAgICAgIHRoaXMuZGF0YSh0cmFuc2FjdGlvbkpzb24uZGF0YSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IEJ1aWxkVHJhbnNhY3Rpb25FcnJvcignVW5zdXBwb3J0ZWQgdHJhbnNhY3Rpb24gdHlwZScpO1xuICAgICAgLy8gVE9ETzogQWRkIG90aGVyIGNhc2VzIG9mIGRlc2VyaWFsaXphdGlvblxuICAgIH1cbiAgfVxuXG4gIC8qKiBAaW5oZXJpdGRvYyAqL1xuICBwcm90ZWN0ZWQgc2lnbkltcGxlbWVudGF0aW9uKGtleTogQmFzZUtleSk6IEJhc2VUcmFuc2FjdGlvbiB7XG4gICAgY29uc3Qgc2lnbmVyID0gbmV3IEtleVBhaXIoeyBwcnY6IGtleS5rZXkgfSk7XG4gICAgaWYgKHRoaXMuX3R5cGUgPT09IFRyYW5zYWN0aW9uVHlwZS5XYWxsZXRJbml0aWFsaXphdGlvbiAmJiB0aGlzLl93YWxsZXRPd25lckFkZHJlc3Nlcy5sZW5ndGggPT09IDApIHtcbiAgICAgIHRocm93IG5ldyBTaWduaW5nRXJyb3IoJ0Nhbm5vdCBzaWduIGFuIHdhbGxldCBpbml0aWFsaXphdGlvbiB0cmFuc2FjdGlvbiB3aXRob3V0IG93bmVycycpO1xuICAgIH1cbiAgICBpZiAodGhpcy5fc291cmNlS2V5UGFpcikge1xuICAgICAgdGhyb3cgbmV3IFNpZ25pbmdFcnJvcignQ2Fubm90IHNpZ24gbXVsdGlwbGUgdGltZXMgYSBub24gc2VuZC10eXBlIHRyYW5zYWN0aW9uJyk7XG4gICAgfVxuICAgIC8vIFNpZ25pbmcgdGhlIHRyYW5zYWN0aW9uIGlzIGFuIGFzeW5jIG9wZXJhdGlvbiwgc28gc2F2ZSB0aGUgc291cmNlIGFuZCBsZWF2ZSB0aGUgYWN0dWFsXG4gICAgLy8gc2lnbmluZyBmb3IgdGhlIGJ1aWxkIHN0ZXBcbiAgICB0aGlzLl9zb3VyY2VLZXlQYWlyID0gc2lnbmVyO1xuICAgIHJldHVybiB0aGlzLnRyYW5zYWN0aW9uO1xuICB9XG5cbiAgLyoqIEBpbmhlcml0ZG9jICovXG4gIHZhbGlkYXRlQWRkcmVzcyhhZGRyZXNzOiBCYXNlQWRkcmVzcyk6IHZvaWQge1xuICAgIGlmICghaXNWYWxpZEV0aEFkZHJlc3MoYWRkcmVzcy5hZGRyZXNzKSkge1xuICAgICAgdGhyb3cgbmV3IEJ1aWxkVHJhbnNhY3Rpb25FcnJvcignSW52YWxpZCBhZGRyZXNzICcgKyBhZGRyZXNzLmFkZHJlc3MpO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBAaW5oZXJpdGRvYyAqL1xuICB2YWxpZGF0ZUtleShrZXk6IEJhc2VLZXkpOiB2b2lkIHtcbiAgICBpZiAoIShpc1ZhbGlkWHBydihrZXkua2V5KSB8fCBpc1ZhbGlkUHJ2KGtleS5rZXkpKSkge1xuICAgICAgdGhyb3cgbmV3IEJ1aWxkVHJhbnNhY3Rpb25FcnJvcignSW52YWxpZCBrZXknKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogVmFsaWRhdGUgdGhlIHJhdyB0cmFuc2FjdGlvbiBpcyBlaXRoZXIgYSBKU09OIG9yXG4gICAqIGEgaGV4IGVuY29kZWQgdHJhbnNhY3Rpb25cbiAgICpcbiAgICogQHBhcmFtIHthbnl9IHJhd1RyYW5zYWN0aW9uIFRoZSByYXcgdHJhbnNhY3Rpb24gdG8gYmUgdmFsaWRhdGVkXG4gICAqL1xuICB2YWxpZGF0ZVJhd1RyYW5zYWN0aW9uKHJhd1RyYW5zYWN0aW9uOiBhbnkpOiB2b2lkIHtcbiAgICBpZiAoIXJhd1RyYW5zYWN0aW9uKSB7XG4gICAgICB0aHJvdyBuZXcgSW52YWxpZFRyYW5zYWN0aW9uRXJyb3IoJ1JhdyB0cmFuc2FjdGlvbiBpcyBlbXB0eScpO1xuICAgIH1cbiAgICBpZiAodHlwZW9mIHJhd1RyYW5zYWN0aW9uID09PSAnc3RyaW5nJykge1xuICAgICAgaWYgKC9eMHg/WzAtOWEtZl17MSx9JC8udGVzdChyYXdUcmFuc2FjdGlvbi50b0xvd2VyQ2FzZSgpKSkge1xuICAgICAgICBjb25zdCB0eEJ5dGVzID0gZXRoVXRpbC50b0J1ZmZlcihldGhVdGlsLmFkZEhleFByZWZpeChyYXdUcmFuc2FjdGlvbi50b0xvd2VyQ2FzZSgpKSk7XG4gICAgICAgIGlmICghdGhpcy5pc0VpcDE1NTlUeG4odHhCeXRlcykgJiYgIXRoaXMuaXNSTFBEZWNvZGFibGUodHhCeXRlcykpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgUGFyc2VUcmFuc2FjdGlvbkVycm9yKCdUaGVyZSB3YXMgZXJyb3IgaW4gZGVjb2RpbmcgdGhlIGhleCBzdHJpbmcnKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBKU09OLnBhcnNlKHJhd1RyYW5zYWN0aW9uKTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgIHRocm93IG5ldyBQYXJzZVRyYW5zYWN0aW9uRXJyb3IoJ1RoZXJlIHdhcyBlcnJvciBpbiBwYXJzaW5nIHRoZSBKU09OIHN0cmluZycpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBJbnZhbGlkVHJhbnNhY3Rpb25FcnJvcignVHJhbnNhY3Rpb24gaXMgbm90IGEgaGV4IHN0cmluZyBvciBzdHJpbmdpZmllZCBqc29uJyk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBpc0VpcDE1NTlUeG4odHhuOiBCdWZmZXIpOiBib29sZWFuIHtcbiAgICB0cnkge1xuICAgICAgRmVlTWFya2V0RUlQMTU1OVRyYW5zYWN0aW9uLmZyb21TZXJpYWxpemVkVHgodHhuKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH0gY2F0Y2ggKF8pIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGlzUkxQRGVjb2RhYmxlKGJ5dGVzOiBCdWZmZXIpOiBib29sZWFuIHtcbiAgICB0cnkge1xuICAgICAgZXRoVXRpbC5ybHAuZGVjb2RlKGJ5dGVzKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH0gY2F0Y2ggKF8pIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH1cblxuICBwcm90ZWN0ZWQgdmFsaWRhdGVCYXNlVHJhbnNhY3Rpb25GaWVsZHMoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuX2ZlZSA9PT0gdW5kZWZpbmVkIHx8ICghdGhpcy5fZmVlLmZlZSAmJiAhdGhpcy5fZmVlLmdhc1ByaWNlICYmICF0aGlzLl9mZWUuZWlwMTU1OSkpIHtcbiAgICAgIHRocm93IG5ldyBCdWlsZFRyYW5zYWN0aW9uRXJyb3IoJ0ludmFsaWQgdHJhbnNhY3Rpb246IG1pc3NpbmcgZmVlJyk7XG4gICAgfVxuICAgIGlmICh0aGlzLl9jb21tb24gPT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhyb3cgbmV3IEJ1aWxkVHJhbnNhY3Rpb25FcnJvcignSW52YWxpZCB0cmFuc2FjdGlvbjogbmV0d29yayBjb21tb24nKTtcbiAgICB9XG4gICAgaWYgKHRoaXMuX2NvdW50ZXIgPT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhyb3cgbmV3IEJ1aWxkVHJhbnNhY3Rpb25FcnJvcignSW52YWxpZCB0cmFuc2FjdGlvbjogbWlzc2luZyBhZGRyZXNzIGNvdW50ZXInKTtcbiAgICB9XG4gIH1cblxuICAvKiogQGluaGVyaXRkb2MgKi9cbiAgdmFsaWRhdGVUcmFuc2FjdGlvbih0cmFuc2FjdGlvbjogQmFzZVRyYW5zYWN0aW9uKTogdm9pZCB7XG4gICAgdGhpcy52YWxpZGF0ZUJhc2VUcmFuc2FjdGlvbkZpZWxkcygpO1xuICAgIHN3aXRjaCAodGhpcy5fdHlwZSkge1xuICAgICAgY2FzZSBUcmFuc2FjdGlvblR5cGUuV2FsbGV0SW5pdGlhbGl6YXRpb246XG4gICAgICAgIHRoaXMudmFsaWRhdGVXYWxsZXRJbml0aWFsaXphdGlvbkZpZWxkcygpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgVHJhbnNhY3Rpb25UeXBlLlJlY292ZXJ5V2FsbGV0RGVwbG95bWVudDpcbiAgICAgICAgdGhpcy52YWxpZGF0ZURhdGFGaWVsZCgpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgVHJhbnNhY3Rpb25UeXBlLlNlbmQ6XG4gICAgICBjYXNlIFRyYW5zYWN0aW9uVHlwZS5TZW5kRVJDNzIxOlxuICAgICAgY2FzZSBUcmFuc2FjdGlvblR5cGUuU2VuZEVSQzExNTU6XG4gICAgICAgIHRoaXMudmFsaWRhdGVDb250cmFjdEFkZHJlc3MoKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIFRyYW5zYWN0aW9uVHlwZS5BZGRyZXNzSW5pdGlhbGl6YXRpb246XG4gICAgICAgIHRoaXMudmFsaWRhdGVDb250cmFjdEFkZHJlc3MoKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIFRyYW5zYWN0aW9uVHlwZS5GbHVzaENvaW5zOlxuICAgICAgICB0aGlzLnZhbGlkYXRlQ29udHJhY3RBZGRyZXNzKCk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBUcmFuc2FjdGlvblR5cGUuRmx1c2hUb2tlbnM6XG4gICAgICAgIHRoaXMudmFsaWRhdGVDb250cmFjdEFkZHJlc3MoKTtcbiAgICAgICAgdGhpcy52YWxpZGF0ZUZvcndhcmRlckFkZHJlc3MoKTtcbiAgICAgICAgdGhpcy52YWxpZGF0ZVRva2VuQWRkcmVzcygpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgVHJhbnNhY3Rpb25UeXBlLlNpbmdsZVNpZ1NlbmQ6XG4gICAgICAgIC8vIGZvciBzaW5nbGUgc2lnIHNlbmRzLCB0aGUgY29udHJhY3QgYWRkcmVzcyBpcyBhY3R1YWxseSB0aGUgcmVjaXBpZW50XG4gICAgICAgIHRoaXMudmFsaWRhdGVDb250cmFjdEFkZHJlc3MoKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIFRyYW5zYWN0aW9uVHlwZS5TdGFraW5nTG9jazpcbiAgICAgIGNhc2UgVHJhbnNhY3Rpb25UeXBlLlN0YWtpbmdVbmxvY2s6XG4gICAgICBjYXNlIFRyYW5zYWN0aW9uVHlwZS5TdGFraW5nVm90ZTpcbiAgICAgIGNhc2UgVHJhbnNhY3Rpb25UeXBlLlN0YWtpbmdVbnZvdGU6XG4gICAgICBjYXNlIFRyYW5zYWN0aW9uVHlwZS5TdGFraW5nQWN0aXZhdGU6XG4gICAgICBjYXNlIFRyYW5zYWN0aW9uVHlwZS5TdGFraW5nV2l0aGRyYXc6XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBUcmFuc2FjdGlvblR5cGUuQ29udHJhY3RDYWxsOlxuICAgICAgICB0aGlzLnZhbGlkYXRlQ29udHJhY3RBZGRyZXNzKCk7XG4gICAgICAgIHRoaXMudmFsaWRhdGVEYXRhRmllbGQoKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyBuZXcgQnVpbGRUcmFuc2FjdGlvbkVycm9yKCdVbnN1cHBvcnRlZCB0cmFuc2FjdGlvbiB0eXBlJyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrIHdhbGxldCBvd25lciBhZGRyZXNzZXMgZm9yIHdhbGxldCBpbml0aWFsaXphdGlvbiB0cmFuc2FjdGlvbnMgYXJlIHZhbGlkIG9yIHRocm93LlxuICAgKi9cbiAgcHJpdmF0ZSB2YWxpZGF0ZVdhbGxldEluaXRpYWxpemF0aW9uRmllbGRzKCk6IHZvaWQge1xuICAgIGlmICh0aGlzLl93YWxsZXRPd25lckFkZHJlc3NlcyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aHJvdyBuZXcgQnVpbGRUcmFuc2FjdGlvbkVycm9yKCdJbnZhbGlkIHRyYW5zYWN0aW9uOiBtaXNzaW5nIHdhbGxldCBvd25lcnMnKTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5fd2FsbGV0T3duZXJBZGRyZXNzZXMubGVuZ3RoICE9PSAzKSB7XG4gICAgICB0aHJvdyBuZXcgQnVpbGRUcmFuc2FjdGlvbkVycm9yKFxuICAgICAgICBgSW52YWxpZCB0cmFuc2FjdGlvbjogd3JvbmcgbnVtYmVyIG9mIG93bmVycyAtLSByZXF1aXJlZDogMywgZm91bmQ6ICR7dGhpcy5fd2FsbGV0T3duZXJBZGRyZXNzZXMubGVuZ3RofWBcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrIGlmIGEgdG9rZW4gYWRkcmVzcyBmb3IgdGhlIHR4IHdhcyBkZWZpbmVkIG9yIHRocm93LlxuICAgKi9cbiAgcHJpdmF0ZSB2YWxpZGF0ZVRva2VuQWRkcmVzcygpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5fdG9rZW5BZGRyZXNzID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHRocm93IG5ldyBCdWlsZFRyYW5zYWN0aW9uRXJyb3IoJ0ludmFsaWQgdHJhbnNhY3Rpb246IG1pc3NpbmcgdG9rZW4gYWRkcmVzcycpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVjayBpZiBhIGZvcndhcmRlciBhZGRyZXNzIGZvciB0aGUgdHggd2FzIGRlZmluZWQgb3IgdGhyb3cuXG4gICAqL1xuICBwcml2YXRlIHZhbGlkYXRlRm9yd2FyZGVyQWRkcmVzcygpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5fZm9yd2FyZGVyQWRkcmVzcyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aHJvdyBuZXcgQnVpbGRUcmFuc2FjdGlvbkVycm9yKCdJbnZhbGlkIHRyYW5zYWN0aW9uOiBtaXNzaW5nIGZvcndhcmRlciBhZGRyZXNzJyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrIGlmIGEgY29udHJhY3QgYWRkcmVzcyBmb3IgdGhlIHdhbGxldCB3YXMgZGVmaW5lZCBvciB0aHJvdy5cbiAgICovXG4gIHByaXZhdGUgdmFsaWRhdGVDb250cmFjdEFkZHJlc3MoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuX2NvbnRyYWN0QWRkcmVzcyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aHJvdyBuZXcgQnVpbGRUcmFuc2FjdGlvbkVycm9yKCdJbnZhbGlkIHRyYW5zYWN0aW9uOiBtaXNzaW5nIGNvbnRyYWN0IGFkZHJlc3MnKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2tzIGlmIGEgY29udHJhY3QgY2FsbCBkYXRhIGZpZWxkIHdhcyBkZWZpbmVkIG9yIHRocm93cyBvdGhlcndpc2VcbiAgICovXG4gIHByaXZhdGUgdmFsaWRhdGVEYXRhRmllbGQoKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLl9kYXRhKSB7XG4gICAgICB0aHJvdyBuZXcgQnVpbGRUcmFuc2FjdGlvbkVycm9yKCdJbnZhbGlkIHRyYW5zYWN0aW9uOiBtaXNzaW5nIGNvbnRyYWN0IGNhbGwgZGF0YSBmaWVsZCcpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgc2V0Q29udHJhY3QoYWRkcmVzczogc3RyaW5nIHwgdW5kZWZpbmVkKTogdm9pZCB7XG4gICAgaWYgKGFkZHJlc3MgPT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhyb3cgbmV3IEJ1aWxkVHJhbnNhY3Rpb25FcnJvcignVW5kZWZpbmVkIHJlY2lwaWVudCBhZGRyZXNzJyk7XG4gICAgfVxuICAgIHRoaXMuY29udHJhY3QoYWRkcmVzcyk7XG4gIH1cblxuICB2YWxpZGF0ZVZhbHVlKHZhbHVlOiBCaWdOdW1iZXIpOiB2b2lkIHtcbiAgICBpZiAodmFsdWUuaXNMZXNzVGhhbigwKSkge1xuICAgICAgdGhyb3cgbmV3IEJ1aWxkVHJhbnNhY3Rpb25FcnJvcignVmFsdWUgY2Fubm90IGJlIGJlbG93IGxlc3MgdGhhbiB6ZXJvJyk7XG4gICAgfVxuICAgIC8vIFRPRE86IHZhbGlkYXRlIHRoZSBhbW91bnQgaXMgbm90IGJpZ2dlciB0aGFuIHRoZSBtYXggYW1vdW50IGluIGVhY2ggRXRoIGZhbWlseSBjb2luXG4gIH1cblxuICAvLyByZWdpb24gQ29tbW9uIGJ1aWxkZXIgbWV0aG9kc1xuXG4gIC8qKlxuICAgKiBUaGUgdHlwZSBvZiB0cmFuc2FjdGlvbiBiZWluZyBidWlsdC5cbiAgICpcbiAgICogQHBhcmFtIHtUcmFuc2FjdGlvblR5cGV9IHR5cGVcbiAgICovXG4gIHR5cGUodHlwZTogVHJhbnNhY3Rpb25UeXBlKTogdm9pZCB7XG4gICAgdGhpcy5fdHlwZSA9IHR5cGU7XG4gIH1cblxuICAvKipcbiAgICogU2V0IHRoZSB0cmFuc2FjdGlvbiBmZWVzLiBMb3cgZmVlcyBtYXkgZ2V0IGEgdHJhbnNhY3Rpb24gcmVqZWN0ZWQgb3IgbmV2ZXIgcGlja2VkIHVwIGJ5IGJha2Vycy5cbiAgICpcbiAgICogQHBhcmFtIHtGZWV9IGZlZSBCYWtlciBmZWVzLiBNYXkgYWxzbyBpbmNsdWRlIHRoZSBtYXhpbXVtIGdhcyB0byBwYXlcbiAgICovXG4gIGZlZShmZWU6IEZlZSk6IHZvaWQge1xuICAgIHRoaXMudmFsaWRhdGVWYWx1ZShuZXcgQmlnTnVtYmVyKGZlZS5mZWUpKTtcbiAgICBpZiAoZmVlLmdhc0xpbWl0KSB7XG4gICAgICB0aGlzLnZhbGlkYXRlVmFsdWUobmV3IEJpZ051bWJlcihmZWUuZ2FzTGltaXQpKTtcbiAgICB9XG4gICAgaWYgKGZlZS5laXAxNTU5KSB7XG4gICAgICB0aGlzLnZhbGlkYXRlVmFsdWUobmV3IEJpZ051bWJlcihmZWUuZWlwMTU1OS5tYXhGZWVQZXJHYXMpKTtcbiAgICAgIHRoaXMudmFsaWRhdGVWYWx1ZShuZXcgQmlnTnVtYmVyKGZlZS5laXAxNTU5Lm1heFByaW9yaXR5RmVlUGVyR2FzKSk7XG4gICAgfVxuICAgIGlmIChmZWUuZ2FzUHJpY2UpIHtcbiAgICAgIHRoaXMudmFsaWRhdGVWYWx1ZShuZXcgQmlnTnVtYmVyKGZlZS5nYXNQcmljZSkpO1xuICAgIH1cbiAgICB0aGlzLl9mZWUgPSBmZWU7XG4gIH1cblxuICAvKipcbiAgICogU2V0IHRoZSB0cmFuc2FjdGlvbiBjb3VudGVyIHRvIHByZXZlbnQgc3VibWl0dGluZyByZXBlYXRlZCB0cmFuc2FjdGlvbnMuXG4gICAqXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBjb3VudGVyIFRoZSBjb3VudGVyIHRvIHVzZVxuICAgKi9cbiAgY291bnRlcihjb3VudGVyOiBudW1iZXIpOiB2b2lkIHtcbiAgICBpZiAoY291bnRlciA8IDApIHtcbiAgICAgIHRocm93IG5ldyBCdWlsZFRyYW5zYWN0aW9uRXJyb3IoYEludmFsaWQgY291bnRlcjogJHtjb3VudGVyfWApO1xuICAgIH1cblxuICAgIHRoaXMuX2NvdW50ZXIgPSBjb3VudGVyO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSB2YWx1ZSB0byBzZW5kIGFsb25nIHdpdGggdGhpcyB0cmFuc2FjdGlvbi4gMCBieSBkZWZhdWx0XG4gICAqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSB2YWx1ZSBUaGUgdmFsdWUgdG8gc2VuZCBhbG9uZyB3aXRoIHRoaXMgdHJhbnNhY3Rpb25cbiAgICovXG4gIHZhbHVlKHZhbHVlOiBzdHJpbmcpOiB2b2lkIHtcbiAgICB0aGlzLl92YWx1ZSA9IHZhbHVlO1xuICB9XG5cbiAgLy8gc2V0IGFyZ3MgdGhhdCBhcmUgcmVxdWlyZWQgZm9yIGFsbCB0eXBlcyBvZiBldGggdHJhbnNhY3Rpb25zXG4gIHByb3RlY3RlZCBidWlsZEJhc2UoZGF0YTogc3RyaW5nKTogVHhEYXRhIHtcbiAgICBjb25zdCBiYXNlUGFyYW1zID0ge1xuICAgICAgZ2FzTGltaXQ6IHRoaXMuX2ZlZS5nYXNMaW1pdCxcbiAgICAgIG5vbmNlOiB0aGlzLl9jb3VudGVyLFxuICAgICAgZGF0YTogZGF0YSxcbiAgICAgIGNoYWluSWQ6IHRoaXMuX2NvbW1vbi5jaGFpbklkQk4oKS50b1N0cmluZygpLFxuICAgICAgdmFsdWU6IHRoaXMuX3ZhbHVlLFxuICAgICAgdG86IHRoaXMuX2NvbnRyYWN0QWRkcmVzcyxcbiAgICB9O1xuXG4gICAgaWYgKHRoaXMuX2ZlZS5laXAxNTU5KSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICAuLi5iYXNlUGFyYW1zLFxuICAgICAgICBfdHlwZTogRVRIVHJhbnNhY3Rpb25UeXBlLkVJUDE1NTksXG4gICAgICAgIG1heEZlZVBlckdhczogdGhpcy5fZmVlLmVpcDE1NTkubWF4RmVlUGVyR2FzLFxuICAgICAgICBtYXhQcmlvcml0eUZlZVBlckdhczogdGhpcy5fZmVlLmVpcDE1NTkubWF4UHJpb3JpdHlGZWVQZXJHYXMsXG4gICAgICB9O1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICAuLi5iYXNlUGFyYW1zLFxuICAgICAgICBfdHlwZTogRVRIVHJhbnNhY3Rpb25UeXBlLkxFR0FDWSxcbiAgICAgICAgZ2FzUHJpY2U6IHRoaXMuX2ZlZT8uZ2FzUHJpY2UgPz8gdGhpcy5fZmVlLmZlZSxcbiAgICAgICAgdjogdGhpcy5nZXRGaW5hbFYoKSxcbiAgICAgIH07XG4gICAgfVxuICB9XG5cbiAgLy8gZW5kcmVnaW9uXG5cbiAgLy8gcmVnaW9uIFdhbGxldEluaXRpYWxpemF0aW9uIGJ1aWxkZXIgbWV0aG9kc1xuICAvKipcbiAgICogU2V0IG9uZSBvZiB0aGUgb3duZXJzIG9mIHRoZSBtdWx0aXNpZyB3YWxsZXQuXG4gICAqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBhZGRyZXNzIEFuIEV0aGVyZXVtIGFkZHJlc3NcbiAgICovXG4gIG93bmVyKGFkZHJlc3M6IHN0cmluZyk6IHZvaWQge1xuICAgIGlmICh0aGlzLl90eXBlICE9PSBUcmFuc2FjdGlvblR5cGUuV2FsbGV0SW5pdGlhbGl6YXRpb24pIHtcbiAgICAgIHRocm93IG5ldyBCdWlsZFRyYW5zYWN0aW9uRXJyb3IoJ011bHRpc2lnIHdhbGxldCBvd25lciBjYW4gb25seSBiZSBzZXQgZm9yIGluaXRpYWxpemF0aW9uIHRyYW5zYWN0aW9ucycpO1xuICAgIH1cbiAgICBpZiAodGhpcy5fd2FsbGV0T3duZXJBZGRyZXNzZXMubGVuZ3RoID49IERFRkFVTFRfTSkge1xuICAgICAgdGhyb3cgbmV3IEJ1aWxkVHJhbnNhY3Rpb25FcnJvcignQSBtYXhpbXVtIG9mICcgKyBERUZBVUxUX00gKyAnIG93bmVycyBjYW4gYmUgc2V0IGZvciBhIG11bHRpc2lnIHdhbGxldCcpO1xuICAgIH1cbiAgICBpZiAoIWlzVmFsaWRFdGhBZGRyZXNzKGFkZHJlc3MpKSB7XG4gICAgICB0aHJvdyBuZXcgQnVpbGRUcmFuc2FjdGlvbkVycm9yKCdJbnZhbGlkIGFkZHJlc3M6ICcgKyBhZGRyZXNzKTtcbiAgICB9XG4gICAgaWYgKHRoaXMuX3dhbGxldE93bmVyQWRkcmVzc2VzLmluY2x1ZGVzKGFkZHJlc3MpKSB7XG4gICAgICB0aHJvdyBuZXcgQnVpbGRUcmFuc2FjdGlvbkVycm9yKCdSZXBlYXRlZCBvd25lciBhZGRyZXNzOiAnICsgYWRkcmVzcyk7XG4gICAgfVxuICAgIHRoaXMuX3dhbGxldE93bmVyQWRkcmVzc2VzLnB1c2goYWRkcmVzcyk7XG4gIH1cblxuICAvKipcbiAgICogQnVpbGQgYSB0cmFuc2FjdGlvbiBmb3IgYSBnZW5lcmljIG11bHRpc2lnIGNvbnRyYWN0LlxuICAgKlxuICAgKiBAcmV0dXJucyB7VHhEYXRhfSBUaGUgRXRoZXJldW0gdHJhbnNhY3Rpb24gZGF0YVxuICAgKi9cbiAgcHJvdGVjdGVkIGJ1aWxkV2FsbGV0SW5pdGlhbGl6YXRpb25UcmFuc2FjdGlvbih3YWxsZXRWZXJzaW9uPzogbnVtYmVyKTogVHhEYXRhIHtcbiAgICBjb25zdCB3YWxsZXRJbml0RGF0YSA9XG4gICAgICB3YWxsZXRWZXJzaW9uID09PSBkZWZhdWx0V2FsbGV0VmVyc2lvblxuICAgICAgICA/IHRoaXMuZ2V0Q29udHJhY3REYXRhKHRoaXMuX3dhbGxldE93bmVyQWRkcmVzc2VzKVxuICAgICAgICA6IGdldFYxV2FsbGV0SW5pdGlhbGl6YXRpb25EYXRhKHRoaXMuX3dhbGxldE93bmVyQWRkcmVzc2VzLCB0aGlzLl9zYWx0KTtcbiAgICByZXR1cm4gdGhpcy5idWlsZEJhc2Uod2FsbGV0SW5pdERhdGEpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIHNtYXJ0IGNvbnRyYWN0IGVuY29kZWQgZGF0YVxuICAgKlxuICAgKiBAcGFyYW0ge3N0cmluZ1tdfSBhZGRyZXNzZXMgLSB0aGUgY29udHJhY3Qgc2lnbmVyc1xuICAgKiBAcmV0dXJucyB7c3RyaW5nfSAtIHRoZSBzbWFydCBjb250cmFjdCBlbmNvZGVkIGRhdGFcbiAgICovXG4gIHByb3RlY3RlZCBnZXRDb250cmFjdERhdGEoYWRkcmVzc2VzOiBzdHJpbmdbXSk6IHN0cmluZyB7XG4gICAgY29uc3QgcGFyYW1zID0gW2FkZHJlc3Nlc107XG4gICAgY29uc3QgcmVzdWx0RW5jb2RlZFBhcmFtZXRlcnMgPSBFdGhlcmV1bUFiaS5yYXdFbmNvZGUod2FsbGV0U2ltcGxlQ29uc3RydWN0b3IsIHBhcmFtcylcbiAgICAgIC50b1N0cmluZygnaGV4JylcbiAgICAgIC5yZXBsYWNlKCcweCcsICcnKTtcbiAgICByZXR1cm4gdGhpcy5fd2FsbGV0U2ltcGxlQnl0ZUNvZGUgKyByZXN1bHRFbmNvZGVkUGFyYW1ldGVycztcbiAgfVxuXG4gIC8vIGVuZHJlZ2lvblxuXG4gIC8vIHJlZ2lvbiBTZW5kIGJ1aWxkZXIgbWV0aG9kc1xuXG4gIGNvbnRyYWN0KGFkZHJlc3M6IHN0cmluZyk6IHZvaWQge1xuICAgIGlmICghaXNWYWxpZEV0aEFkZHJlc3MoYWRkcmVzcykpIHtcbiAgICAgIHRocm93IG5ldyBCdWlsZFRyYW5zYWN0aW9uRXJyb3IoJ0ludmFsaWQgYWRkcmVzczogJyArIGFkZHJlc3MpO1xuICAgIH1cbiAgICB0aGlzLl9jb250cmFjdEFkZHJlc3MgPSBhZGRyZXNzO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldHMgdGhlIHRyYW5zZmVyIGZ1bmRzIGJ1aWxkZXIgaWYgZXhpc3QsIG9yIGNyZWF0ZXMgYSBuZXcgb25lIGZvciB0aGlzIHRyYW5zYWN0aW9uIGFuZCByZXR1cm5zIGl0XG4gICAqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBkYXRhIHRyYW5zZmVyIGRhdGEgdG8gaW5pdGlhbGl6ZSB0aGUgdHJhbnNmZXIgYnVpbGRlciB3aXRoLCBlbXB0eSBpZiBub25lIGdpdmVuXG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0gaXNGaXJzdFNpZ25lciB3aGV0aGVyIHRoZSB0cmFuc2FjdGlvbiBpcyBiZWluZyBzaWduZWQgYnkgdGhlIGZpcnN0IHNpZ25lclxuICAgKiBAcmV0dXJucyB7VHJhbnNmZXJCdWlsZGVyIHwgRVJDNzIxVHJhbnNmZXJCdWlsZGVyIHwgRVJDMTE1NVRyYW5zZmVyQnVpbGRlcn0gdGhlIHRyYW5zZmVyIGJ1aWxkZXJcbiAgICovXG4gIGFic3RyYWN0IHRyYW5zZmVyKFxuICAgIGRhdGE/OiBzdHJpbmcsXG4gICAgaXNGaXJzdFNpZ25lcj86IGJvb2xlYW5cbiAgKTogVHJhbnNmZXJCdWlsZGVyIHwgRVJDNzIxVHJhbnNmZXJCdWlsZGVyIHwgRVJDMTE1NVRyYW5zZmVyQnVpbGRlcjtcblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgc2VyaWFsaXplZCBzZW5kTXVsdGlTaWcgY29udHJhY3QgbWV0aG9kIGRhdGFcbiAgICpcbiAgICogQHJldHVybnMge3N0cmluZ30gc2VyaWFsaXplZCBzZW5kTXVsdGlTaWcgZGF0YVxuICAgKi9cbiAgcHVibGljIGdldFNlbmREYXRhKCk6IHN0cmluZyB7XG4gICAgaWYgKCF0aGlzLl90cmFuc2Zlcikge1xuICAgICAgdGhyb3cgbmV3IEJ1aWxkVHJhbnNhY3Rpb25FcnJvcignTWlzc2luZyB0cmFuc2ZlciBpbmZvcm1hdGlvbicpO1xuICAgIH1cbiAgICBjb25zdCBjaGFpbklkID0gdGhpcy5fY29tbW9uLmNoYWluSWRCTigpLnRvU3RyaW5nKCk7XG4gICAgdGhpcy5fdHJhbnNmZXIud2FsbGV0VmVyc2lvbih0aGlzLl93YWxsZXRWZXJzaW9uKTtcbiAgICAvLyBUaGlzIGNoYW5nZSBpcyBtYWRlIHRvIHN1cHBvcnQgbmV3IGNvbnRyYWN0cyB3aXRoIGRpZmZlcmVudCBlbmNvZGluZyB0eXBlXG4gICAgcmV0dXJuIHRoaXMuX3RyYW5zZmVyLnNpZ25BbmRCdWlsZChjaGFpbklkLCB0aGlzLmNvaW5Vc2VzTm9uUGFja2VkRW5jb2RpbmdGb3JUeERhdGEoKSk7XG4gIH1cblxuICAvKipcbiAgICogRGVjaWRlIGlmIHRoZSBjb2luIHVzZXMgbm9uLXBhY2tlZCBlbmNvZGluZyBmb3IgdHggZGF0YVxuICAgKlxuICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gdHJ1ZSBpZiB0aGUgY29pbiB1c2VzIG5vbi1wYWNrZWQgZW5jb2RpbmcgZm9yIHR4IGRhdGFcbiAgICovXG4gIHB1YmxpYyBjb2luVXNlc05vblBhY2tlZEVuY29kaW5nRm9yVHhEYXRhKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiAoXG4gICAgICB0aGlzLl93YWxsZXRWZXJzaW9uID09PSA0IHx8IHRoaXMuX2NvaW5Db25maWcuZmVhdHVyZXMuaW5jbHVkZXMoQ29pbkZlYXR1cmUuVVNFU19OT05fUEFDS0VEX0VOQ09ESU5HX0ZPUl9UWERBVEEpXG4gICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgYnVpbGRTZW5kVHJhbnNhY3Rpb24oKTogVHhEYXRhIHtcbiAgICBjb25zdCBzZW5kRGF0YSA9IHRoaXMuZ2V0U2VuZERhdGEoKTtcbiAgICBjb25zdCB0eDogVHhEYXRhID0gdGhpcy5idWlsZEJhc2Uoc2VuZERhdGEpO1xuICAgIHR4LnRvID0gdGhpcy5fY29udHJhY3RBZGRyZXNzO1xuICAgIHJldHVybiB0eDtcbiAgfVxuXG4gIC8vIGVuZHJlZ2lvblxuXG4gIC8vIHJlZ2lvbiBBZGRyZXNzSW5pdGlhbGl6YXRpb24gYnVpbGRlciBtZXRob2RzXG5cbiAgLyoqXG4gICAqIFNldCB0aGUgY29udHJhY3QgdHJhbnNhY3Rpb24gbm9uY2UgdG8gY2FsY3VsYXRlIHRoZSBmb3J3YXJkZXIgYWRkcmVzcy5cbiAgICpcbiAgICogQHBhcmFtIHtudW1iZXJ9IGNvbnRyYWN0Q291bnRlciBUaGUgY291bnRlciB0byB1c2VcbiAgICovXG4gIGNvbnRyYWN0Q291bnRlcihjb250cmFjdENvdW50ZXI6IG51bWJlcik6IHZvaWQge1xuICAgIGlmIChjb250cmFjdENvdW50ZXIgPCAwKSB7XG4gICAgICB0aHJvdyBuZXcgQnVpbGRUcmFuc2FjdGlvbkVycm9yKGBJbnZhbGlkIGNvbnRyYWN0IGNvdW50ZXI6ICR7Y29udHJhY3RDb3VudGVyfWApO1xuICAgIH1cblxuICAgIHRoaXMuX2NvbnRyYWN0Q291bnRlciA9IGNvbnRyYWN0Q291bnRlcjtcbiAgfVxuXG4gIC8qKlxuICAgKiBCdWlsZCBhIHRyYW5zYWN0aW9uIHRvIGNyZWF0ZSBhIGZvcndhcmRlci5cbiAgICpcbiAgICogQHJldHVybnMge1R4RGF0YX0gVGhlIEV0aGVyZXVtIHRyYW5zYWN0aW9uIGRhdGFcbiAgICovXG4gIHByaXZhdGUgYnVpbGRBZGRyZXNzSW5pdGlhbGl6YXRpb25UcmFuc2FjdGlvbigpOiBUeERhdGEge1xuICAgIGNvbnN0IGFkZHJlc3NJbml0RGF0YSA9IGdldEFkZHJlc3NJbml0RGF0YUFsbEZvcndhcmRlclZlcnNpb25zKFxuICAgICAgdGhpcy5fZm9yd2FyZGVyVmVyc2lvbixcbiAgICAgIHRoaXMuX2Jhc2VBZGRyZXNzLFxuICAgICAgdGhpcy5fc2FsdCxcbiAgICAgIHRoaXMuX2ZlZUFkZHJlc3NcbiAgICApO1xuICAgIGNvbnN0IHR4OiBUeERhdGEgPSB0aGlzLmJ1aWxkQmFzZShhZGRyZXNzSW5pdERhdGEpO1xuICAgIHR4LnRvID0gdGhpcy5fY29udHJhY3RBZGRyZXNzO1xuXG4gICAgaWYgKHRoaXMuX2NvbnRyYWN0Q291bnRlcikge1xuICAgICAgdHguZGVwbG95ZWRBZGRyZXNzID0gY2FsY3VsYXRlRm9yd2FyZGVyQWRkcmVzcyh0aGlzLl9jb250cmFjdEFkZHJlc3MsIHRoaXMuX2NvbnRyYWN0Q291bnRlcik7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuX3NhbHQgJiYgdGhpcy5faW5pdENvZGUpIHtcbiAgICAgIGNvbnN0IHNhbHRCdWZmZXIgPSBldGhVdGlsLnNldExlbmd0aExlZnQoZXRoVXRpbC50b0J1ZmZlcih0aGlzLl9zYWx0KSwgMzIpO1xuXG4gICAgICBjb25zdCB7IGNyZWF0ZUZvcndhcmRlclBhcmFtcywgY3JlYXRlRm9yd2FyZGVyVHlwZXMgfSA9IGdldENyZWF0ZUZvcndhcmRlclBhcmFtc0FuZFR5cGVzKFxuICAgICAgICB0aGlzLl9iYXNlQWRkcmVzcyxcbiAgICAgICAgc2FsdEJ1ZmZlcixcbiAgICAgICAgdGhpcy5fZmVlQWRkcmVzc1xuICAgICAgKTtcblxuICAgICAgLy8gSGFzaCB0aGUgd2FsbGV0IGJhc2UgYWRkcmVzcyBhbmQgZmVlIGFkZHJlc3MgaWYgcHJlc2VudCB3aXRoIHRoZSBnaXZlbiBzYWx0LCBzbyB0aGUgYWRkcmVzcyBkaXJlY3RseSByZWxpZXMgb24gdGhlIGJhc2UgYWRkcmVzcyBhbmQgZmVlIGFkZHJlc3NcbiAgICAgIGNvbnN0IGNhbGN1bGF0aW9uU2FsdCA9IGV0aFV0aWwuYnVmZmVyVG9IZXgoXG4gICAgICAgIEV0aGVyZXVtQWJpLnNvbGlkaXR5U0hBMyhjcmVhdGVGb3J3YXJkZXJUeXBlcywgY3JlYXRlRm9yd2FyZGVyUGFyYW1zKVxuICAgICAgKTtcbiAgICAgIHR4LmRlcGxveWVkQWRkcmVzcyA9IGNhbGN1bGF0ZUZvcndhcmRlclYxQWRkcmVzcyh0aGlzLl9jb250cmFjdEFkZHJlc3MsIGNhbGN1bGF0aW9uU2FsdCwgdGhpcy5faW5pdENvZGUpO1xuICAgIH1cbiAgICByZXR1cm4gdHg7XG4gIH1cbiAgLy8gZW5kcmVnaW9uXG5cbiAgLy8gcmVnaW9uIGZsdXNoIG1ldGhvZHNcbiAgLyoqXG4gICAqIFNldCB0aGUgZm9yd2FyZGVyIGFkZHJlc3MgdG8gZmx1c2hcbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IGFkZHJlc3MgVGhlIGFkZHJlc3MgdG8gZmx1c2hcbiAgICovXG4gIGZvcndhcmRlckFkZHJlc3MoYWRkcmVzczogc3RyaW5nKTogdm9pZCB7XG4gICAgaWYgKCFpc1ZhbGlkRXRoQWRkcmVzcyhhZGRyZXNzKSkge1xuICAgICAgdGhyb3cgbmV3IEJ1aWxkVHJhbnNhY3Rpb25FcnJvcignSW52YWxpZCBhZGRyZXNzOiAnICsgYWRkcmVzcyk7XG4gICAgfVxuICAgIHRoaXMuX2ZvcndhcmRlckFkZHJlc3MgPSBhZGRyZXNzO1xuICB9XG5cbiAgLyoqXG4gICAqIFNldCB0aGUgYWRkcmVzcyBvZiB0aGUgRVJDMjAgdG9rZW4gY29udHJhY3QgdGhhdCB3ZSBhcmUgZmx1c2hpbmcgdG9rZW5zIGZvclxuICAgKlxuICAgKiBAcGFyYW0ge3N0cmluZ30gYWRkcmVzcyB0aGUgY29udHJhY3QgYWRkcmVzcyBvZiB0aGUgdG9rZW4gdG8gZmx1c2hcbiAgICovXG4gIHRva2VuQWRkcmVzcyhhZGRyZXNzOiBzdHJpbmcpOiB2b2lkIHtcbiAgICBpZiAoIWlzVmFsaWRFdGhBZGRyZXNzKGFkZHJlc3MpKSB7XG4gICAgICB0aHJvdyBuZXcgQnVpbGRUcmFuc2FjdGlvbkVycm9yKCdJbnZhbGlkIGFkZHJlc3M6ICcgKyBhZGRyZXNzKTtcbiAgICB9XG4gICAgdGhpcy5fdG9rZW5BZGRyZXNzID0gYWRkcmVzcztcbiAgfVxuXG4gIC8qKlxuICAgKiBCdWlsZCBhIHRyYW5zYWN0aW9uIHRvIGZsdXNoIHRva2VucyBmcm9tIGEgZm9yd2FyZGVyLlxuICAgKlxuICAgKiBAcmV0dXJucyB7VHhEYXRhfSBUaGUgRXRoZXJldW0gdHJhbnNhY3Rpb24gZGF0YVxuICAgKi9cbiAgcHJpdmF0ZSBidWlsZEZsdXNoVG9rZW5zVHJhbnNhY3Rpb24oKTogVHhEYXRhIHtcbiAgICBpZiAodGhpcy5fZm9yd2FyZGVyVmVyc2lvbiA+PSA0ICYmIHRoaXMuX2NvbnRyYWN0QWRkcmVzcyAhPT0gdGhpcy5fZm9yd2FyZGVyQWRkcmVzcykge1xuICAgICAgdGhyb3cgbmV3IEJ1aWxkVHJhbnNhY3Rpb25FcnJvcignSW52YWxpZCBjb250cmFjdCBhZGRyZXNzOiAnICsgdGhpcy5fY29udHJhY3RBZGRyZXNzKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuYnVpbGRCYXNlKGZsdXNoVG9rZW5zRGF0YSh0aGlzLl9mb3J3YXJkZXJBZGRyZXNzLCB0aGlzLl90b2tlbkFkZHJlc3MsIHRoaXMuX2ZvcndhcmRlclZlcnNpb24pKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBCdWlsZCBhIHRyYW5zYWN0aW9uIHRvIGZsdXNoIHRva2VucyBmcm9tIGEgZm9yd2FyZGVyLlxuICAgKlxuICAgKiBAcmV0dXJucyB7VHhEYXRhfSBUaGUgRXRoZXJldW0gdHJhbnNhY3Rpb24gZGF0YVxuICAgKi9cbiAgcHJpdmF0ZSBidWlsZEZsdXNoQ29pbnNUcmFuc2FjdGlvbigpOiBUeERhdGEge1xuICAgIHJldHVybiB0aGlzLmJ1aWxkQmFzZShmbHVzaENvaW5zRGF0YSgpKTtcbiAgfVxuICAvLyBlbmRyZWdpb25cblxuICAvLyByZWdpb24gZ2VuZXJpYyBjb250cmFjdCBjYWxsXG4gIGRhdGEoZW5jb2RlZENhbGw6IHN0cmluZyk6IHZvaWQge1xuICAgIGNvbnN0IHN1cHBvcnRlZFRyYW5zYWN0aW9uVHlwZXMgPSBbVHJhbnNhY3Rpb25UeXBlLkNvbnRyYWN0Q2FsbCwgVHJhbnNhY3Rpb25UeXBlLlJlY292ZXJ5V2FsbGV0RGVwbG95bWVudF07XG4gICAgaWYgKCFzdXBwb3J0ZWRUcmFuc2FjdGlvblR5cGVzLmluY2x1ZGVzKHRoaXMuX3R5cGUpKSB7XG4gICAgICB0aHJvdyBuZXcgQnVpbGRUcmFuc2FjdGlvbkVycm9yKCdkYXRhIGNhbiBvbmx5IGJlIHNldCBmb3IgY29udHJhY3QgY2FsbCB0cmFuc2FjdGlvbiB0eXBlcycpO1xuICAgIH1cbiAgICB0aGlzLl9kYXRhID0gZW5jb2RlZENhbGw7XG4gIH1cblxuICBwcml2YXRlIGJ1aWxkR2VuZXJpY0NvbnRyYWN0Q2FsbFRyYW5zYWN0aW9uKCk6IFR4RGF0YSB7XG4gICAgcmV0dXJuIHRoaXMuYnVpbGRCYXNlKHRoaXMuX2RhdGEpO1xuICB9XG4gIC8vIGVuZHJlZ2lvblxuXG4gIC8qKiBAaW5oZXJpdGRvYyAqL1xuICBwcm90ZWN0ZWQgZ2V0IHRyYW5zYWN0aW9uKCk6IFRyYW5zYWN0aW9uIHtcbiAgICByZXR1cm4gdGhpcy5fdHJhbnNhY3Rpb247XG4gIH1cblxuICAvKiogQGluaGVyaXRkb2MgKi9cbiAgcHJvdGVjdGVkIHNldCB0cmFuc2FjdGlvbih0cmFuc2FjdGlvbjogVHJhbnNhY3Rpb24pIHtcbiAgICB0aGlzLl90cmFuc2FjdGlvbiA9IHRyYW5zYWN0aW9uO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCB0aGUgZmluYWwgdiB2YWx1ZS4gRmluYWwgdiBpcyBkZXNjcmliZWQgaW4gRUlQLTE1NS5cbiAgICpcbiAgICogQHByb3RlY3RlZCBmb3IgaW50ZXJuYWwgdXNlIHdoZW4gdGhlIGVuYWJsZUZpbmFsVkZpZWxkIGZsYWcgaXMgdHJ1ZS5cbiAgICovXG4gIHByb3RlY3RlZCBnZXRGaW5hbFYoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gZXRoVXRpbC5hZGRIZXhQcmVmaXgodGhpcy5fY29tbW9uLmNoYWluSWRCTigpLm11bG4oMikuYWRkbigzNSkudG9TdHJpbmcoMTYpKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTZXQgdGhlIGZvcndhcmRlciB2ZXJzaW9uIGZvciBhZGRyZXNzIHRvIGJlIGluaXRpYWxpemVkXG4gICAqXG4gICAqIEBwYXJhbSB7bnVtYmVyfSB2ZXJzaW9uIGZvcndhcmRlciB2ZXJzaW9uXG4gICAqL1xuICBmb3J3YXJkZXJWZXJzaW9uKHZlcnNpb246IG51bWJlcik6IHZvaWQge1xuICAgIGlmICh2ZXJzaW9uIDwgMCB8fCB2ZXJzaW9uID4gNCB8fCB2ZXJzaW9uID09PSAzKSB7XG4gICAgICB0aHJvdyBuZXcgQnVpbGRUcmFuc2FjdGlvbkVycm9yKGBJbnZhbGlkIGZvcndhcmRlciB2ZXJzaW9uOiAke3ZlcnNpb259YCk7XG4gICAgfVxuXG4gICAgdGhpcy5fZm9yd2FyZGVyVmVyc2lvbiA9IHZlcnNpb247XG4gIH1cblxuICAvKipcbiAgICogU2V0IHRoZSBzYWx0IHRvIGNyZWF0ZSB0aGUgYWRkcmVzcyB1c2luZyBjcmVhdGUyXG4gICAqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBzYWx0IFRoZSBzYWx0IHRvIGNyZWF0ZSB0aGUgYWRkcmVzcyB1c2luZyBjcmVhdGUyLCBoZXggc3RyaW5nXG4gICAqL1xuICBzYWx0KHNhbHQ6IHN0cmluZyk6IHZvaWQge1xuICAgIHRoaXMuX3NhbHQgPSBzYWx0O1xuICB9XG5cbiAgLyoqXG4gICAqIFRha2UgdGhlIGltcGxlbWVudGF0aW9uIGFkZHJlc3MgZm9yIHRoZSBwcm94eSBjb250cmFjdCwgYW5kIGdldCB0aGUgYmluYXJ5IGluaXRjb2RlIGZvciB0aGUgYXNzb2NpYXRlZCBwcm94eVxuICAgKlxuICAgKiBAcGFyYW0ge3N0cmluZ30gaW1wbGVtZW50YXRpb25BZGRyZXNzIFRoZSBhZGRyZXNzIG9mIHRoZSBpbXBsZW1lbnRhdGlvbiBjb250cmFjdFxuICAgKi9cbiAgaW5pdENvZGUoaW1wbGVtZW50YXRpb25BZGRyZXNzOiBzdHJpbmcpOiB2b2lkIHtcbiAgICBpZiAoIWlzVmFsaWRFdGhBZGRyZXNzKGltcGxlbWVudGF0aW9uQWRkcmVzcykpIHtcbiAgICAgIHRocm93IG5ldyBCdWlsZFRyYW5zYWN0aW9uRXJyb3IoJ0ludmFsaWQgYWRkcmVzczogJyArIGltcGxlbWVudGF0aW9uQWRkcmVzcyk7XG4gICAgfVxuICAgIHRoaXMuX2luaXRDb2RlID0gZ2V0UHJveHlJbml0Y29kZShpbXBsZW1lbnRhdGlvbkFkZHJlc3MpO1xuICB9XG5cbiAgLyoqXG4gICAqIFNldCB0aGUgd2FsbGV0IHZlcnNpb24gZm9yIHdhbGxldCB0byBiZSBpbml0aWFsaXplZFxuICAgKlxuICAgKiBAcGFyYW0ge251bWJlcn0gdmVyc2lvbiB3YWxsZXQgdmVyc2lvblxuICAgKi9cbiAgd2FsbGV0VmVyc2lvbih2ZXJzaW9uOiBudW1iZXIpOiB2b2lkIHtcbiAgICBpZiAodmVyc2lvbiA8IDAgfHwgdmVyc2lvbiA+IDQgfHwgdmVyc2lvbiA9PT0gMykge1xuICAgICAgdGhyb3cgbmV3IEJ1aWxkVHJhbnNhY3Rpb25FcnJvcihgSW52YWxpZCB3YWxsZXQgdmVyc2lvbjogJHt2ZXJzaW9ufWApO1xuICAgIH1cblxuICAgIHRoaXMuX3dhbGxldFZlcnNpb24gPSB2ZXJzaW9uO1xuICB9XG5cbiAgLyoqXG4gICAqIFNldCB0aGUgYmFzZSBhZGRyZXNzIG9mIHRoZSB3YWxsZXRcbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IGFkZHJlc3MgVGhlIHdhbGxldCBjb250cmFjdCBhZGRyZXNzXG4gICAqL1xuICBiYXNlQWRkcmVzcyhhZGRyZXNzOiBzdHJpbmcpOiB2b2lkIHtcbiAgICBpZiAoIWlzVmFsaWRFdGhBZGRyZXNzKGFkZHJlc3MpKSB7XG4gICAgICB0aHJvdyBuZXcgQnVpbGRUcmFuc2FjdGlvbkVycm9yKCdJbnZhbGlkIGFkZHJlc3M6ICcgKyBhZGRyZXNzKTtcbiAgICB9XG4gICAgdGhpcy5fYmFzZUFkZHJlc3MgPSBhZGRyZXNzO1xuICB9XG5cbiAgLyoqXG4gICAqIFNldCB0aGUgZmVlIGFkZHJlc3Mgb2YgdGhlIHdhbGxldFxuICAgKlxuICAgKiBAcGFyYW0ge3N0cmluZ30gYWRkcmVzcyBUaGUgZmVlIGFkZHJlc3Mgb2YgdGhlIHdhbGxldFxuICAgKi9cbiAgZmVlQWRkcmVzcyhhZGRyZXNzOiBzdHJpbmcpOiB2b2lkIHtcbiAgICBpZiAoIWlzVmFsaWRFdGhBZGRyZXNzKGFkZHJlc3MpKSB7XG4gICAgICB0aHJvdyBuZXcgQnVpbGRUcmFuc2FjdGlvbkVycm9yKCdJbnZhbGlkIGFkZHJlc3M6ICcgKyBhZGRyZXNzKTtcbiAgICB9XG4gICAgdGhpcy5fZmVlQWRkcmVzcyA9IGFkZHJlc3M7XG4gIH1cblxuICAvKipcbiAgICogR2V0IHRoZSB3YWxsZXQgdmVyc2lvbiBmb3Igd2FsbGV0XG4gICAqL1xuICBwdWJsaWMgZ2V0V2FsbGV0VmVyc2lvbigpOiBudW1iZXIge1xuICAgIHJldHVybiB0aGlzLl93YWxsZXRWZXJzaW9uO1xuICB9XG59XG4iXX0=
|