@bitgo-beta/sdk-coin-tempo 1.0.1-beta.31 → 1.0.1-beta.310

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/dist/src/index.d.ts +1 -0
  2. package/dist/src/index.d.ts.map +1 -1
  3. package/dist/src/index.js +2 -1
  4. package/dist/src/lib/constants.d.ts +21 -1
  5. package/dist/src/lib/constants.d.ts.map +1 -1
  6. package/dist/src/lib/constants.js +25 -5
  7. package/dist/src/lib/index.d.ts +4 -0
  8. package/dist/src/lib/index.d.ts.map +1 -1
  9. package/dist/src/lib/index.js +5 -1
  10. package/dist/src/lib/keyPair.d.ts +5 -25
  11. package/dist/src/lib/keyPair.d.ts.map +1 -1
  12. package/dist/src/lib/keyPair.js +9 -97
  13. package/dist/src/lib/tip20Abi.d.ts +98 -0
  14. package/dist/src/lib/tip20Abi.d.ts.map +1 -0
  15. package/dist/src/lib/tip20Abi.js +62 -0
  16. package/dist/src/lib/transaction.d.ts +144 -0
  17. package/dist/src/lib/transaction.d.ts.map +1 -0
  18. package/dist/src/lib/transaction.js +216 -0
  19. package/dist/src/lib/transactionBuilder.d.ts +139 -0
  20. package/dist/src/lib/transactionBuilder.d.ts.map +1 -0
  21. package/dist/src/lib/transactionBuilder.js +408 -0
  22. package/dist/src/lib/types.d.ts +27 -0
  23. package/dist/src/lib/types.d.ts.map +1 -0
  24. package/dist/src/lib/types.js +3 -0
  25. package/dist/src/lib/utils.d.ts +70 -7
  26. package/dist/src/lib/utils.d.ts.map +1 -1
  27. package/dist/src/lib/utils.js +148 -16
  28. package/dist/src/register.d.ts.map +1 -1
  29. package/dist/src/register.js +5 -1
  30. package/dist/src/tempo.d.ts +95 -41
  31. package/dist/src/tempo.d.ts.map +1 -1
  32. package/dist/src/tempo.js +447 -76
  33. package/dist/src/tip20Token.d.ts +83 -0
  34. package/dist/src/tip20Token.d.ts.map +1 -0
  35. package/dist/src/tip20Token.js +202 -0
  36. package/dist/test/integration/tip20.d.ts +7 -0
  37. package/dist/test/integration/tip20.d.ts.map +1 -0
  38. package/dist/test/integration/tip20.js +178 -0
  39. package/dist/test/resources/tempo.d.ts +61 -0
  40. package/dist/test/resources/tempo.d.ts.map +1 -0
  41. package/dist/test/resources/tempo.js +79 -0
  42. package/dist/test/unit/index.js +172 -3
  43. package/dist/test/unit/tempo.d.ts +2 -0
  44. package/dist/test/unit/tempo.d.ts.map +1 -0
  45. package/dist/test/unit/tempo.js +207 -0
  46. package/dist/test/unit/transactionBuilder.d.ts +2 -0
  47. package/dist/test/unit/transactionBuilder.d.ts.map +1 -0
  48. package/dist/test/unit/transactionBuilder.js +858 -0
  49. package/dist/test/unit/utils.js +6 -5
  50. package/dist/tsconfig.tsbuildinfo +1 -1
  51. package/package.json +12 -7
@@ -0,0 +1,408 @@
1
+ "use strict";
2
+ /**
3
+ * TIP-20 Transaction Builder
4
+ *
5
+ * Unified builder for TIP-20 transactions supporting:
6
+ * - Single or batch operations
7
+ * - Per-operation memos for tracking
8
+ * - Custom fee token selection
9
+ * - EIP-7702 Account Abstraction (type 0x76)
10
+ */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.Tip20TransactionBuilder = void 0;
13
+ const abstract_eth_1 = require("@bitgo-beta/abstract-eth");
14
+ const sdk_core_1 = require("@bitgo-beta/sdk-core");
15
+ const ethers_1 = require("ethers");
16
+ const transaction_1 = require("./transaction");
17
+ const utils_1 = require("./utils");
18
+ const tip20Abi_1 = require("./tip20Abi");
19
+ const constants_1 = require("./constants");
20
+ /**
21
+ * Transaction Builder for TIP-20 tokens on Tempo blockchain
22
+ * Extends abstract-eth TransactionBuilder with Tempo-specific features
23
+ */
24
+ class Tip20TransactionBuilder extends abstract_eth_1.TransactionBuilder {
25
+ constructor(_coinConfig) {
26
+ super(_coinConfig);
27
+ this.operations = [];
28
+ this.rawCalls = [];
29
+ }
30
+ /**
31
+ * Implement the transfer method from abstract class
32
+ * Note: For TIP-20 transactions, use addOperation() instead
33
+ */
34
+ transfer(data, isFirstSigner) {
35
+ const transferBuilder = new abstract_eth_1.TransferBuilder(undefined, isFirstSigner);
36
+ if (data) {
37
+ transferBuilder.data(data);
38
+ }
39
+ this._transfer = transferBuilder;
40
+ return transferBuilder;
41
+ }
42
+ /**
43
+ * Validate the transaction has all required fields for Tempo AA transactions.
44
+ * Overrides parent class validation since AA transactions use a different model
45
+ * (operations-based rather than single contract address).
46
+ *
47
+ * @throws BuildTransactionError if validation fails
48
+ */
49
+ validateTransaction() {
50
+ if (this.operations.length === 0 && this.rawCalls.length === 0) {
51
+ throw new sdk_core_1.BuildTransactionError('At least one operation or raw call is required to build a transaction');
52
+ }
53
+ if (this._nonce === undefined) {
54
+ throw new sdk_core_1.BuildTransactionError('Nonce is required to build a transaction');
55
+ }
56
+ if (this._gas === undefined) {
57
+ throw new sdk_core_1.BuildTransactionError('Gas limit is required to build a transaction');
58
+ }
59
+ if (this._maxFeePerGas === undefined) {
60
+ throw new sdk_core_1.BuildTransactionError('maxFeePerGas is required to build a transaction');
61
+ }
62
+ if (this._maxPriorityFeePerGas === undefined) {
63
+ throw new sdk_core_1.BuildTransactionError('maxPriorityFeePerGas is required to build a transaction');
64
+ }
65
+ }
66
+ /** @inheritdoc */
67
+ validateRawTransaction(rawTransaction) {
68
+ if (typeof rawTransaction === 'string' && (0, utils_1.isTip20Transaction)(rawTransaction)) {
69
+ try {
70
+ ethers_1.ethers.utils.RLP.decode('0x' + rawTransaction.slice(4));
71
+ return;
72
+ }
73
+ catch (e) {
74
+ throw new sdk_core_1.ParseTransactionError(`Failed to RLP decode TIP-20 transaction: ${e}`);
75
+ }
76
+ }
77
+ super.validateRawTransaction(rawTransaction);
78
+ }
79
+ /** @inheritdoc */
80
+ fromImplementation(rawTransaction, isFirstSigner) {
81
+ if (!rawTransaction) {
82
+ throw new sdk_core_1.InvalidTransactionError('Raw transaction is empty');
83
+ }
84
+ if ((0, utils_1.isTip20Transaction)(rawTransaction)) {
85
+ return this.fromTip20Transaction(rawTransaction);
86
+ }
87
+ return super.fromImplementation(rawTransaction, isFirstSigner);
88
+ }
89
+ /**
90
+ * Deserialize a type 0x76 transaction and restore builder state.
91
+ * RLP field layout mirrors buildBaseRlpData() in transaction.ts.
92
+ */
93
+ fromTip20Transaction(rawTransaction) {
94
+ try {
95
+ const rlpHex = '0x' + rawTransaction.slice(4);
96
+ const decoded = ethers_1.ethers.utils.RLP.decode(rlpHex);
97
+ if (!Array.isArray(decoded) || decoded.length < 13) {
98
+ throw new sdk_core_1.ParseTransactionError('Invalid TIP-20 transaction: unexpected RLP structure');
99
+ }
100
+ const parseBigInt = (hex) => (!hex || hex === '0x' ? 0n : BigInt(hex));
101
+ const parseHexInt = (hex) => (!hex || hex === '0x' ? 0 : parseInt(hex, 16));
102
+ const chainId = parseHexInt(decoded[0]);
103
+ const maxPriorityFeePerGas = parseBigInt(decoded[1]);
104
+ const maxFeePerGas = parseBigInt(decoded[2]);
105
+ const gas = parseBigInt(decoded[3]);
106
+ const callsTuples = decoded[4];
107
+ const nonce = parseHexInt(decoded[7]);
108
+ const feeTokenRaw = decoded[10];
109
+ const calls = callsTuples.map((tuple) => ({
110
+ to: tuple[0],
111
+ value: parseBigInt(tuple[1]),
112
+ data: tuple[2],
113
+ }));
114
+ const operations = [];
115
+ const decodedRawCalls = [];
116
+ for (const call of calls) {
117
+ const op = this.decodeCallToOperation(call);
118
+ if (op !== null) {
119
+ operations.push(op);
120
+ }
121
+ else {
122
+ decodedRawCalls.push({ to: call.to, data: call.data, value: call.value.toString() });
123
+ }
124
+ }
125
+ let signature;
126
+ if (decoded.length >= 14 && decoded[13] && decoded[13].length > 2) {
127
+ const sigBytes = ethers_1.ethers.utils.arrayify(decoded[13]);
128
+ if (sigBytes.length === 65) {
129
+ const r = ethers_1.ethers.utils.hexlify(sigBytes.slice(0, 32));
130
+ const s = ethers_1.ethers.utils.hexlify(sigBytes.slice(32, 64));
131
+ const v = sigBytes[64];
132
+ const yParity = v > 1 ? v - 27 : v;
133
+ signature = { r, s, yParity };
134
+ }
135
+ }
136
+ const feeToken = feeTokenRaw && feeTokenRaw !== '0x' ? feeTokenRaw : undefined;
137
+ const txRequest = {
138
+ type: constants_1.AA_TRANSACTION_TYPE,
139
+ chainId,
140
+ nonce,
141
+ maxFeePerGas,
142
+ maxPriorityFeePerGas,
143
+ gas,
144
+ calls,
145
+ accessList: [],
146
+ feeToken,
147
+ };
148
+ this._nonce = nonce;
149
+ this._gas = gas;
150
+ this._maxFeePerGas = maxFeePerGas;
151
+ this._maxPriorityFeePerGas = maxPriorityFeePerGas;
152
+ this._feeToken = feeToken;
153
+ this.operations = operations;
154
+ this.rawCalls = decodedRawCalls;
155
+ this._restoredSignature = signature;
156
+ const tx = new transaction_1.Tip20Transaction(this._coinConfig, txRequest, operations, decodedRawCalls);
157
+ if (signature) {
158
+ tx.setSignature(signature);
159
+ }
160
+ return tx;
161
+ }
162
+ catch (e) {
163
+ if (e instanceof sdk_core_1.ParseTransactionError)
164
+ throw e;
165
+ throw new sdk_core_1.ParseTransactionError(`Failed to deserialize TIP-20 transaction: ${e}`);
166
+ }
167
+ }
168
+ /**
169
+ * Decode a single AA call's data back into a Tip20Operation.
170
+ * Returns null if the call is not a transferWithMemo — it will be stored as a RawContractCall instead.
171
+ * This preserves calldata fidelity for arbitrary smart contract interactions.
172
+ */
173
+ decodeCallToOperation(call) {
174
+ const iface = new ethers_1.ethers.utils.Interface(tip20Abi_1.TIP20_TRANSFER_WITH_MEMO_ABI);
175
+ try {
176
+ const decoded = iface.decodeFunctionData('transferWithMemo', call.data);
177
+ const toAddress = decoded[0];
178
+ const amountUnits = BigInt(decoded[1].toString());
179
+ const memoBytes32 = decoded[2];
180
+ const amount = (0, utils_1.tip20UnitsToAmount)(amountUnits);
181
+ const stripped = ethers_1.ethers.utils.stripZeros(memoBytes32);
182
+ const memo = stripped.length > 0 ? ethers_1.ethers.utils.toUtf8String(stripped) : undefined;
183
+ return { token: call.to, to: toAddress, amount, memo };
184
+ }
185
+ catch {
186
+ // Not a transferWithMemo call — caller will store as RawContractCall
187
+ return null;
188
+ }
189
+ }
190
+ /**
191
+ * Build the transaction from configured TIP-20 operations and transaction parameters.
192
+ * Signs with _sourceKeyPair if it has been set via sign({ key }).
193
+ */
194
+ async buildImplementation() {
195
+ if (this._nonce === undefined ||
196
+ this._gas === undefined ||
197
+ this._maxFeePerGas === undefined ||
198
+ this._maxPriorityFeePerGas === undefined) {
199
+ throw new sdk_core_1.BuildTransactionError('Transaction validation failed: missing required fields');
200
+ }
201
+ this.fee({
202
+ fee: this._maxFeePerGas.toString(),
203
+ gasLimit: this._gas.toString(),
204
+ eip1559: {
205
+ maxFeePerGas: this._maxFeePerGas.toString(),
206
+ maxPriorityFeePerGas: this._maxPriorityFeePerGas.toString(),
207
+ },
208
+ });
209
+ const calls = this.operations.map((op) => this.operationToCall(op));
210
+ for (const rawCall of this.rawCalls) {
211
+ calls.push({
212
+ to: rawCall.to,
213
+ data: rawCall.data,
214
+ value: rawCall.value ? BigInt(rawCall.value) : 0n,
215
+ });
216
+ }
217
+ const txRequest = {
218
+ type: constants_1.AA_TRANSACTION_TYPE,
219
+ chainId: this._common.chainIdBN().toNumber(),
220
+ nonce: this._nonce,
221
+ maxFeePerGas: this._maxFeePerGas,
222
+ maxPriorityFeePerGas: this._maxPriorityFeePerGas,
223
+ gas: this._gas,
224
+ calls,
225
+ accessList: [],
226
+ feeToken: this._feeToken,
227
+ };
228
+ const tx = new transaction_1.Tip20Transaction(this._coinConfig, txRequest, this.operations, this.rawCalls);
229
+ if (this._sourceKeyPair && this._sourceKeyPair.getKeys().prv) {
230
+ const prv = this._sourceKeyPair.getKeys().prv;
231
+ const unsignedHex = await tx.serialize();
232
+ const msgHash = ethers_1.ethers.utils.keccak256(ethers_1.ethers.utils.arrayify(unsignedHex));
233
+ const signingKey = new ethers_1.ethers.utils.SigningKey('0x' + prv);
234
+ const sig = signingKey.signDigest(ethers_1.ethers.utils.arrayify(msgHash));
235
+ tx.setSignature({
236
+ r: sig.r,
237
+ s: sig.s,
238
+ yParity: sig.recoveryParam ?? 0,
239
+ });
240
+ }
241
+ else if (this._restoredSignature) {
242
+ tx.setSignature(this._restoredSignature);
243
+ }
244
+ return tx;
245
+ }
246
+ /**
247
+ * Add a single operation to the transaction
248
+ * Can be called multiple times to create batch transactions
249
+ *
250
+ * @param operation - TIP-20 operation with token, recipient, amount, and optional memo
251
+ * @returns this builder instance for chaining
252
+ */
253
+ addOperation(operation) {
254
+ this.validateOperation(operation);
255
+ this.operations.push(operation);
256
+ return this;
257
+ }
258
+ /**
259
+ * Add a raw smart contract call with pre-encoded calldata
260
+ * Use this for arbitrary contract interactions where the UI provides ABI-encoded calldata
261
+ *
262
+ * @param call - Raw contract call with target address and pre-encoded calldata
263
+ * @returns this builder instance for chaining
264
+ */
265
+ addRawCall(call) {
266
+ if (!(0, utils_1.isValidAddress)(call.to)) {
267
+ throw new sdk_core_1.BuildTransactionError(`Invalid contract address: ${call.to}`);
268
+ }
269
+ if (!(0, utils_1.isValidHexData)(call.data)) {
270
+ throw new sdk_core_1.BuildTransactionError(`Invalid calldata: must be a non-empty 0x-prefixed hex string with even length`);
271
+ }
272
+ if (call.value !== undefined) {
273
+ try {
274
+ const v = BigInt(call.value);
275
+ if (v < 0n)
276
+ throw new Error();
277
+ }
278
+ catch {
279
+ throw new sdk_core_1.BuildTransactionError(`Invalid value: must be a non-negative integer string`);
280
+ }
281
+ }
282
+ this.rawCalls.push(call);
283
+ return this;
284
+ }
285
+ /**
286
+ * Get all raw contract calls in this transaction
287
+ * @returns Array of raw contract calls
288
+ */
289
+ getRawCalls() {
290
+ return [...this.rawCalls];
291
+ }
292
+ /**
293
+ * Set which TIP-20 token will be used to pay transaction fees
294
+ * This is a global setting for the entire transaction
295
+ *
296
+ * @param tokenAddress - Address of the TIP-20 token to use for fees
297
+ * @returns this builder instance for chaining
298
+ */
299
+ feeToken(tokenAddress) {
300
+ if (!(0, utils_1.isValidAddress)(tokenAddress)) {
301
+ throw new sdk_core_1.BuildTransactionError(`Invalid fee token address: ${tokenAddress}`);
302
+ }
303
+ this._feeToken = tokenAddress;
304
+ return this;
305
+ }
306
+ /**
307
+ * Set the transaction nonce
308
+ *
309
+ * @param nonce - Transaction nonce
310
+ * @returns this builder instance for chaining
311
+ */
312
+ nonce(nonce) {
313
+ if (nonce < 0) {
314
+ throw new sdk_core_1.BuildTransactionError(`Invalid nonce: ${nonce}`);
315
+ }
316
+ this._nonce = nonce;
317
+ return this;
318
+ }
319
+ /**
320
+ * Set the gas limit for the transaction
321
+ *
322
+ * @param gas - Gas limit
323
+ * @returns this builder instance for chaining
324
+ */
325
+ gas(gas) {
326
+ const gasValue = typeof gas === 'string' ? BigInt(gas) : gas;
327
+ if (gasValue <= 0n) {
328
+ throw new sdk_core_1.BuildTransactionError(`Invalid gas limit: ${gas}`);
329
+ }
330
+ this._gas = gasValue;
331
+ return this;
332
+ }
333
+ /**
334
+ * Set the maximum fee per gas (EIP-1559)
335
+ *
336
+ * @param maxFeePerGas - Maximum fee per gas in wei
337
+ * @returns this builder instance for chaining
338
+ */
339
+ maxFeePerGas(maxFeePerGas) {
340
+ const feeValue = typeof maxFeePerGas === 'string' ? BigInt(maxFeePerGas) : maxFeePerGas;
341
+ if (feeValue < 0n) {
342
+ throw new sdk_core_1.BuildTransactionError(`Invalid maxFeePerGas: ${maxFeePerGas}`);
343
+ }
344
+ this._maxFeePerGas = feeValue;
345
+ return this;
346
+ }
347
+ /**
348
+ * Set the maximum priority fee per gas (EIP-1559)
349
+ *
350
+ * @param maxPriorityFeePerGas - Maximum priority fee per gas in wei
351
+ * @returns this builder instance for chaining
352
+ */
353
+ maxPriorityFeePerGas(maxPriorityFeePerGas) {
354
+ const feeValue = typeof maxPriorityFeePerGas === 'string' ? BigInt(maxPriorityFeePerGas) : maxPriorityFeePerGas;
355
+ if (feeValue < 0n) {
356
+ throw new sdk_core_1.BuildTransactionError(`Invalid maxPriorityFeePerGas: ${maxPriorityFeePerGas}`);
357
+ }
358
+ this._maxPriorityFeePerGas = feeValue;
359
+ return this;
360
+ }
361
+ /**
362
+ * Get all operations in this transaction
363
+ * @returns Array of TIP-20 operations
364
+ */
365
+ getOperations() {
366
+ return [...this.operations];
367
+ }
368
+ /**
369
+ * Get the fee token address if set
370
+ * @returns Fee token address or undefined
371
+ */
372
+ getFeeToken() {
373
+ return this._feeToken;
374
+ }
375
+ /**
376
+ * Validate a single operation
377
+ * @param operation - Operation to validate
378
+ * @throws BuildTransactionError if invalid
379
+ */
380
+ validateOperation(operation) {
381
+ if (!(0, utils_1.isValidAddress)(operation.token)) {
382
+ throw new sdk_core_1.BuildTransactionError(`Invalid token address: ${operation.token}`);
383
+ }
384
+ if (!(0, utils_1.isValidAddress)(operation.to)) {
385
+ throw new sdk_core_1.BuildTransactionError(`Invalid recipient address: ${operation.to}`);
386
+ }
387
+ if (!(0, utils_1.isValidTip20Amount)(operation.amount)) {
388
+ throw new sdk_core_1.BuildTransactionError(`Invalid amount: ${operation.amount}`);
389
+ }
390
+ if (operation.memo !== undefined && !(0, utils_1.isValidMemoId)(operation.memo)) {
391
+ throw new sdk_core_1.BuildTransactionError(`Invalid memo: must be a non-negative integer`);
392
+ }
393
+ }
394
+ /**
395
+ * Convert a TIP-20 operation to an AA call
396
+ */
397
+ operationToCall(op) {
398
+ const amountInUnits = (0, utils_1.amountToTip20Units)(op.amount);
399
+ const data = (0, utils_1.encodeTip20TransferWithMemo)(op.to, amountInUnits, op.memo);
400
+ return {
401
+ to: op.token,
402
+ data,
403
+ value: 0n,
404
+ };
405
+ }
406
+ }
407
+ exports.Tip20TransactionBuilder = Tip20TransactionBuilder;
408
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhbnNhY3Rpb25CdWlsZGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2xpYi90cmFuc2FjdGlvbkJ1aWxkZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Ozs7OztHQVFHOzs7QUFFSCwyREFJa0M7QUFDbEMsbURBSzhCO0FBRTlCLG1DQUFnQztBQUVoQywrQ0FBMEU7QUFDMUUsbUNBU2lCO0FBQ2pCLHlDQUEwRDtBQUMxRCwyQ0FBa0Q7QUFFbEQ7OztHQUdHO0FBQ0gsTUFBYSx1QkFBd0IsU0FBUSxpQ0FBMEI7SUFVckUsWUFBWSxXQUFpQztRQUMzQyxLQUFLLENBQUMsV0FBVyxDQUFDLENBQUM7UUFWYixlQUFVLEdBQXFCLEVBQUUsQ0FBQztRQUNsQyxhQUFRLEdBQXNCLEVBQUUsQ0FBQztJQVV6QyxDQUFDO0lBRUQ7OztPQUdHO0lBQ0gsUUFBUSxDQUFDLElBQWEsRUFBRSxhQUF1QjtRQUM3QyxNQUFNLGVBQWUsR0FBRyxJQUFJLDhCQUFlLENBQUMsU0FBUyxFQUFFLGFBQWEsQ0FBQyxDQUFDO1FBQ3RFLElBQUksSUFBSSxFQUFFLENBQUM7WUFDVCxlQUFlLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQzdCLENBQUM7UUFDRCxJQUFJLENBQUMsU0FBUyxHQUFHLGVBQWUsQ0FBQztRQUNqQyxPQUFPLGVBQWUsQ0FBQztJQUN6QixDQUFDO0lBRUQ7Ozs7OztPQU1HO0lBQ0gsbUJBQW1CO1FBQ2pCLElBQUksSUFBSSxDQUFDLFVBQVUsQ0FBQyxNQUFNLEtBQUssQ0FBQyxJQUFJLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRSxDQUFDO1lBQy9ELE1BQU0sSUFBSSxnQ0FBcUIsQ0FBQyx1RUFBdUUsQ0FBQyxDQUFDO1FBQzNHLENBQUM7UUFFRCxJQUFJLElBQUksQ0FBQyxNQUFNLEtBQUssU0FBUyxFQUFFLENBQUM7WUFDOUIsTUFBTSxJQUFJLGdDQUFxQixDQUFD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QyxtQkFBbUIsU0FBUyxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUM7UUFDekUsQ0FBQztRQUVELElBQUksU0FBUyxDQUFDLElBQUksS0FBSyxTQUFTLElBQUksQ0FBQyxJQUFBLHFCQUFhLEVBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUM7WUFDbkUsTUFBTSxJQUFJLGdDQUFxQixDQUFDLDhDQUE4QyxDQUFDLENBQUM7UUFDbEYsQ0FBQztJQUNILENBQUM7SUFFRDs7T0FFRztJQUNLLGVBQWUsQ0FBQyxFQUFrQjtRQUN4QyxNQUFNLGFBQWEsR0FBRyxJQUFBLDBCQUFrQixFQUFDLEVBQUUsQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUNwRCxNQUFNLElBQUksR0FBRyxJQUFBLG1DQUEyQixFQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsYUFBYSxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUV4RSxPQUFPO1lBQ0wsRUFBRSxFQUFFLEVBQUUsQ0FBQyxLQUFLO1lBQ1osSUFBSTtZQUNKLEtBQUssRUFBRSxFQUFFO1NBQ1YsQ0FBQztJQUNKLENBQUM7Q0FDRjtBQTlhRCwwREE4YUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIFRJUC0yMCBUcmFuc2FjdGlvbiBCdWlsZGVyXG4gKlxuICogVW5pZmllZCBidWlsZGVyIGZvciBUSVAtMjAgdHJhbnNhY3Rpb25zIHN1cHBvcnRpbmc6XG4gKiAtIFNpbmdsZSBvciBiYXRjaCBvcGVyYXRpb25zXG4gKiAtIFBlci1vcGVyYXRpb24gbWVtb3MgZm9yIHRyYWNraW5nXG4gKiAtIEN1c3RvbSBmZWUgdG9rZW4gc2VsZWN0aW9uXG4gKiAtIEVJUC03NzAyIEFjY291bnQgQWJzdHJhY3Rpb24gKHR5cGUgMHg3NilcbiAqL1xuXG5pbXBvcnQge1xuICBUcmFuc2FjdGlvbiBhcyBFdGhUcmFuc2FjdGlvbixcbiAgVHJhbnNhY3Rpb25CdWlsZGVyIGFzIEFic3RyYWN0VHJhbnNhY3Rpb25CdWlsZGVyLFxuICBUcmFuc2ZlckJ1aWxkZXIsXG59IGZyb20gJ0BiaXRnby1iZXRhL2Fic3RyYWN0LWV0aCc7XG5pbXBvcnQge1xuICBCYXNlVHJhbnNhY3Rpb24sXG4gIEJ1aWxkVHJhbnNhY3Rpb25FcnJvcixcbiAgSW52YWxpZFRyYW5zYWN0aW9uRXJyb3IsXG4gIFBhcnNlVHJhbnNhY3Rpb25FcnJvcixcbn0gZnJvbSAnQGJpdGdvLWJldGEvc2RrLWNvcmUnO1xuaW1wb3J0IHsgQmFzZUNvaW4gYXMgQ29pbkNvbmZpZyB9IGZyb20gJ0BiaXRnby1iZXRhL3N0YXRpY3MnO1xuaW1wb3J0IHsgZXRoZXJzIH0gZnJvbSAnZXRoZXJzJztcbmltcG9ydCB7IEFkZHJlc3MsIEhleCwgUmF3Q29udHJhY3RDYWxsLCBUaXAyME9wZXJhdGlvbiB9IGZyb20gJy4vdHlwZXMnO1xuaW1wb3J0IHsgVGlwMjBUcmFuc2FjdGlvbiwgVGlwMjBUcmFuc2FjdGlvblJlcXVlc3QgfSBmcm9tICcuL3RyYW5zYWN0aW9uJztcbmltcG9ydCB7XG4gIGFtb3VudFRvVGlwMjBVbml0cyxcbiAgZW5jb2RlVGlwMjBUcmFuc2ZlcldpdGhNZW1vLFxuICBpc1RpcDIwVHJhbnNhY3Rpb24sXG4gIGlzVmFsaWRBZGRyZXNzLFxuICBpc1ZhbGlkSGV4RGF0YSxcbiAgaXNWYWxpZE1lbW9JZCxcbiAgaXNWYWxpZFRpcDIwQW1vdW50LFxuICB0aXAyMFVuaXRzVG9BbW91bnQsXG59IGZyb20gJy4vdXRpbHMnO1xuaW1wb3J0IHsgVElQMjBfVFJBTlNGRVJfV0lUSF9NRU1PX0FCSSB9IGZyb20gJy4vdGlwMjBBYmknO1xuaW1wb3J0IHsgQUFfVFJBTlNBQ1RJT05fVFlQRSB9IGZyb20gJy4vY29uc3RhbnRzJztcblxuLyoqXG4gKiBUcmFuc2FjdGlvbiBCdWlsZGVyIGZvciBUSVAtMjAgdG9rZW5zIG9uIFRlbXBvIGJsb2NrY2hhaW5cbiAqIEV4dGVuZHMgYWJzdHJhY3QtZXRoIFRyYW5zYWN0aW9uQnVpbGRlciB3aXRoIFRlbXBvLXNwZWNpZmljIGZlYXR1cmVzXG4gKi9cbmV4cG9ydCBjbGFzcyBUaXAyMFRyYW5zYWN0aW9uQnVpbGRlciBleHRlbmRzIEFic3RyYWN0VHJhbnNhY3Rpb25CdWlsZGVyIHtcbiAgcHJpdmF0ZSBvcGVyYXRpb25zOiBUaXAyME9wZXJhdGlvbltdID0gW107XG4gIHByaXZhdGUgcmF3Q2FsbHM6IFJhd0NvbnRyYWN0Q2FsbFtdID0gW107XG4gIHByaXZhdGUgX2ZlZVRva2VuPzogQWRkcmVzcztcbiAgcHJpdmF0ZSBfbm9uY2U/OiBudW1iZXI7XG4gIHByaXZhdGUgX2dhcz86IGJpZ2ludDtcbiAgcHJpdmF0ZSBfbWF4RmVlUGVyR2FzPzogYmlnaW50O1xuICBwcml2YXRlIF9tYXhQcmlvcml0eUZlZVBlckdhcz86IGJpZ2ludDtcbiAgcHJpdmF0ZSBfcmVzdG9yZWRTaWduYXR1cmU/OiB7IHI6IEhleDsgczogSGV4OyB5UGFyaXR5OiBudW1iZXIgfTtcblxuICBjb25zdHJ1Y3RvcihfY29pbkNvbmZpZzogUmVhZG9ubHk8Q29pbkNvbmZpZz4pIHtcbiAgICBzdXBlcihfY29pbkNvbmZpZyk7XG4gIH1cblxuICAvKipcbiAgICogSW1wbGVtZW50IHRoZSB0cmFuc2ZlciBtZXRob2QgZnJvbSBhYnN0cmFjdCBjbGFzc1xuICAgKiBOb3RlOiBGb3IgVElQLTIwIHRyYW5zYWN0aW9ucywgdXNlIGFkZE9wZXJhdGlvbigpIGluc3RlYWRcbiAgICovXG4gIHRyYW5zZmVyKGRhdGE/OiBzdHJpbmcsIGlzRmlyc3RTaWduZXI/OiBib29sZWFuKTogVHJhbnNmZXJCdWlsZGVyIHtcbiAgICBjb25zdCB0cmFuc2ZlckJ1aWxkZXIgPSBuZXcgVHJhbnNmZXJCdWlsZGVyKHVuZGVmaW5lZCwgaXNGaXJzdFNpZ25lcik7XG4gICAgaWYgKGRhdGEpIHtcbiAgICAgIHRyYW5zZmVyQnVpbGRlci5kYXRhKGRhdGEpO1xuICAgIH1cbiAgICB0aGlzLl90cmFuc2ZlciA9IHRyYW5zZmVyQnVpbGRlcjtcbiAgICByZXR1cm4gdHJhbnNmZXJCdWlsZGVyO1xuICB9XG5cbiAgLyoqXG4gICAqIFZhbGlkYXRlIHRoZSB0cmFuc2FjdGlvbiBoYXMgYWxsIHJlcXVpcmVkIGZpZWxkcyBmb3IgVGVtcG8gQUEgdHJhbnNhY3Rpb25zLlxuICAgKiBPdmVycmlkZXMgcGFyZW50IGNsYXNzIHZhbGlkYXRpb24gc2luY2UgQUEgdHJhbnNhY3Rpb25zIHVzZSBhIGRpZmZlcmVudCBtb2RlbFxuICAgKiAob3BlcmF0aW9ucy1iYXNlZCByYXRoZXIgdGhhbiBzaW5nbGUgY29udHJhY3QgYWRkcmVzcykuXG4gICAqXG4gICAqIEB0aHJvd3MgQnVpbGRUcmFuc2FjdGlvbkVycm9yIGlmIHZhbGlkYXRpb24gZmFpbHNcbiAgICovXG4gIHZhbGlkYXRlVHJhbnNhY3Rpb24oKTogdm9pZCB7XG4gICAgaWYgKHRoaXMub3BlcmF0aW9ucy5sZW5ndGggPT09IDAgJiYgdGhpcy5yYXdDYWxscy5sZW5ndGggPT09IDApIHtcbiAgICAgIHRocm93IG5ldyBCdWlsZFRyYW5zYWN0aW9uRXJyb3IoJ0F0IGxlYXN0IG9uZSBvcGVyYXRpb24gb3IgcmF3IGNhbGwgaXMgcmVxdWlyZWQgdG8gYnVpbGQgYSB0cmFuc2FjdGlvbicpO1xuICAgIH1cblxuICAgIGlmICh0aGlzLl9ub25jZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aHJvdyBuZXcgQnVpbGRUcmFuc2FjdGlvbkVycm9yKCdOb25jZSBpcyByZXF1aXJlZCB0byBidWlsZCBhIHRyYW5zYWN0aW9uJyk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuX2dhcyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aHJvdyBuZXcgQnVpbGRUcmFuc2FjdGlvbkVycm9yKCdHYXMgbGltaXQgaXMgcmVxdWlyZWQgdG8gYnVpbGQgYSB0cmFuc2FjdGlvbicpO1xuICAgIH1cblxuICAgIGlmICh0aGlzLl9tYXhGZWVQZXJHYXMgPT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhyb3cgbmV3IEJ1aWxkVHJhbnNhY3Rpb25FcnJvcignbWF4RmVlUGVyR2FzIGlzIHJlcXVpcmVkIHRvIGJ1aWxkIGEgdHJhbnNhY3Rpb24nKTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5fbWF4UHJpb3JpdHlGZWVQZXJHYXMgPT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhyb3cgbmV3IEJ1aWxkVHJhbnNhY3Rpb25FcnJvcignbWF4UHJpb3JpdHlGZWVQZXJHYXMgaXMgcmVxdWlyZWQgdG8gYnVpbGQgYSB0cmFuc2FjdGlvbicpO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBAaW5oZXJpdGRvYyAqL1xuICB2YWxpZGF0ZVJhd1RyYW5zYWN0aW9uKHJhd1RyYW5zYWN0aW9uOiBhbnkpOiB2b2lkIHtcbiAgICBpZiAodHlwZW9mIHJhd1RyYW5zYWN0aW9uID09PSAnc3RyaW5nJyAmJiBpc1RpcDIwVHJhbnNhY3Rpb24ocmF3VHJhbnNhY3Rpb24pKSB7XG4gICAgICB0cnkge1xuICAgICAgICBldGhlcnMudXRpbHMuUkxQLmRlY29kZSgnMHgnICsgcmF3VHJhbnNhY3Rpb24uc2xpY2UoNCkpO1xuICAgICAgICByZXR1cm47XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIHRocm93IG5ldyBQYXJzZVRyYW5zYWN0aW9uRXJyb3IoYEZhaWxlZCB0byBSTFAgZGVjb2RlIFRJUC0yMCB0cmFuc2FjdGlvbjogJHtlfWApO1xuICAgICAgfVxuICAgIH1cbiAgICBzdXBlci52YWxpZGF0ZVJhd1RyYW5zYWN0aW9uKHJhd1RyYW5zYWN0aW9uKTtcbiAgfVxuXG4gIC8qKiBAaW5oZXJpdGRvYyAqL1xuICBwcm90ZWN0ZWQgZnJvbUltcGxlbWVudGF0aW9uKHJhd1RyYW5zYWN0aW9uOiBzdHJpbmcsIGlzRmlyc3RTaWduZXI/OiBib29sZWFuKTogRXRoVHJhbnNhY3Rpb24ge1xuICAgIGlmICghcmF3VHJhbnNhY3Rpb24pIHtcbiAgICAgIHRocm93IG5ldyBJbnZhbGlkVHJhbnNhY3Rpb25FcnJvcignUmF3IHRyYW5zYWN0aW9uIGlzIGVtcHR5Jyk7XG4gICAgfVxuICAgIGlmIChpc1RpcDIwVHJhbnNhY3Rpb24ocmF3VHJhbnNhY3Rpb24pKSB7XG4gICAgICByZXR1cm4gdGhpcy5mcm9tVGlwMjBUcmFuc2FjdGlvbihyYXdUcmFuc2FjdGlvbikgYXMgdW5rbm93biBhcyBFdGhUcmFuc2FjdGlvbjtcbiAgICB9XG4gICAgcmV0dXJuIHN1cGVyLmZyb21JbXBsZW1lbnRhdGlvbihyYXdUcmFuc2FjdGlvbiwgaXNGaXJzdFNpZ25lcik7XG4gIH1cblxuICAvKipcbiAgICogRGVzZXJpYWxpemUgYSB0eXBlIDB4NzYgdHJhbnNhY3Rpb24gYW5kIHJlc3RvcmUgYnVpbGRlciBzdGF0ZS5cbiAgICogUkxQIGZpZWxkIGxheW91dCBtaXJyb3JzIGJ1aWxkQmFzZVJscERhdGEoKSBpbiB0cmFuc2FjdGlvbi50cy5cbiAgICovXG4gIHByaXZhdGUgZnJvbVRpcDIwVHJhbnNhY3Rpb24ocmF3VHJhbnNhY3Rpb246IHN0cmluZyk6IFRpcDIwVHJhbnNhY3Rpb24ge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBybHBIZXggPSAnMHgnICsgcmF3VHJhbnNhY3Rpb24uc2xpY2UoNCk7XG4gICAgICBjb25zdCBkZWNvZGVkID0gZXRoZXJzLnV0aWxzLlJMUC5kZWNvZGUocmxwSGV4KSBhcyBhbnlbXTtcblxuICAgICAgaWYgKCFBcnJheS5pc0FycmF5KGRlY29kZWQpIHx8IGRlY29kZWQubGVuZ3RoIDwgMTMpIHtcbiAgICAgICAgdGhyb3cgbmV3IFBhcnNlVHJhbnNhY3Rpb25FcnJvcignSW52YWxpZCBUSVAtMjAgdHJhbnNhY3Rpb246IHVuZXhwZWN0ZWQgUkxQIHN0cnVjdHVyZScpO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBwYXJzZUJpZ0ludCA9IChoZXg6IHN0cmluZyk6IGJpZ2ludCA9PiAoIWhleCB8fCBoZXggPT09ICcweCcgPyAwbiA6IEJpZ0ludChoZXgpKTtcbiAgICAgIGNvbnN0IHBhcnNlSGV4SW50ID0gKGhleDogc3RyaW5nKTogbnVtYmVyID0+ICghaGV4IHx8IGhleCA9PT0gJzB4JyA/IDAgOiBwYXJzZUludChoZXgsIDE2KSk7XG5cbiAgICAgIGNvbnN0IGNoYWluSWQgPSBwYXJzZUhleEludChkZWNvZGVkWzBdIGFzIHN0cmluZyk7XG4gICAgICBjb25zdCBtYXhQcmlvcml0eUZlZVBlckdhcyA9IHBhcnNlQmlnSW50KGRlY29kZWRbMV0gYXMgc3RyaW5nKTtcbiAgICAgIGNvbnN0IG1heEZlZVBlckdhcyA9IHBhcnNlQmlnSW50KGRlY29kZWRbMl0gYXMgc3RyaW5nKTtcbiAgICAgIGNvbnN0IGdhcyA9IHBhcnNlQmlnSW50KGRlY29kZWRbM10gYXMgc3RyaW5nKTtcbiAgICAgIGNvbnN0IGNhbGxzVHVwbGVzID0gZGVjb2RlZFs0XSBhcyBzdHJpbmdbXVtdO1xuICAgICAgY29uc3Qgbm9uY2UgPSBwYXJzZUhleEludChkZWNvZGVkWzddIGFzIHN0cmluZyk7XG4gICAgICBjb25zdCBmZWVUb2tlblJhdyA9IGRlY29kZWRbMTBdIGFzIHN0cmluZztcblxuICAgICAgY29uc3QgY2FsbHM6IHsgdG86IEFkZHJlc3M7IGRhdGE6IEhleDsgdmFsdWU6IGJpZ2ludCB9W10gPSBjYWxsc1R1cGxlcy5tYXAoKHR1cGxlKSA9PiAoe1xuICAgICAgICB0bzogdHVwbGVbMF0gYXMgQWRkcmVzcyxcbiAgICAgICAgdmFsdWU6IHBhcnNlQmlnSW50KHR1cGxlWzFdIGFzIHN0cmluZyksXG4gICAgICAgIGRhdGE6IHR1cGxlWzJdIGFzIEhleCxcbiAgICAgIH0pKTtcblxuICAgICAgY29uc3Qgb3BlcmF0aW9uczogVGlwMjBPcGVyYXRpb25bXSA9IFtdO1xuICAgICAgY29uc3QgZGVjb2RlZFJhd0NhbGxzOiBSYXdDb250cmFjdENhbGxbXSA9IFtdO1xuICAgICAgZm9yIChjb25zdCBjYWxsIG9mIGNhbGxzKSB7XG4gICAgICAgIGNvbnN0IG9wID0gdGhpcy5kZWNvZGVDYWxsVG9PcGVyYXRpb24oY2FsbCk7XG4gICAgICAgIGlmIChvcCAhPT0gbnVsbCkge1xuICAgICAgICAgIG9wZXJhdGlvbnMucHVzaChvcCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgZGVjb2RlZFJhd0NhbGxzLnB1c2goeyB0bzogY2FsbC50bywgZGF0YTogY2FsbC5kYXRhLCB2YWx1ZTogY2FsbC52YWx1ZS50b1N0cmluZygpIH0pO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGxldCBzaWduYXR1cmU6IHsgcjogSGV4OyBzOiBIZXg7IHlQYXJpdHk6IG51bWJlciB9IHwgdW5kZWZpbmVkO1xuICAgICAgaWYgKGRlY29kZWQubGVuZ3RoID49IDE0ICYmIGRlY29kZWRbMTNdICYmIChkZWNvZGVkWzEzXSBhcyBzdHJpbmcpLmxlbmd0aCA+IDIpIHtcbiAgICAgICAgY29uc3Qgc2lnQnl0ZXMgPSBldGhlcnMudXRpbHMuYXJyYXlpZnkoZGVjb2RlZFsxM10gYXMgc3RyaW5nKTtcbiAgICAgICAgaWYgKHNpZ0J5dGVzLmxlbmd0aCA9PT0gNjUpIHtcbiAgICAgICAgICBjb25zdCByID0gZXRoZXJzLnV0aWxzLmhleGxpZnkoc2lnQnl0ZXMuc2xpY2UoMCwgMzIpKSBhcyBIZXg7XG4gICAgICAgICAgY29uc3QgcyA9IGV0aGVycy51dGlscy5oZXhsaWZ5KHNpZ0J5dGVzLnNsaWNlKDMyLCA2NCkpIGFzIEhleDtcbiAgICAgICAgICBjb25zdCB2ID0gc2lnQnl0ZXNbNjRdO1xuICAgICAgICAgIGNvbnN0IHlQYXJpdHkgPSB2ID4gMSA/IHYgLSAyNyA6IHY7XG4gICAgICAgICAgc2lnbmF0dXJlID0geyByLCBzLCB5UGFyaXR5IH07XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgY29uc3QgZmVlVG9rZW4gPSBmZWVUb2tlblJhdyAmJiBmZWVUb2tlblJhdyAhPT0gJzB4JyA/IChmZWVUb2tlblJhdyBhcyBBZGRyZXNzKSA6IHVuZGVmaW5lZDtcblxuICAgICAgY29uc3QgdHhSZXF1ZXN0OiBUaXAyMFRyYW5zYWN0aW9uUmVxdWVzdCA9IHtcbiAgICAgICAgdHlwZTogQUFfVFJBTlNBQ1RJT05fVFlQRSxcbiAgICAgICAgY2hhaW5JZCxcbiAgICAgICAgbm9uY2UsXG4gICAgICAgIG1heEZlZVBlckdhcyxcbiAgICAgICAgbWF4UHJpb3JpdHlGZWVQZXJHYXMsXG4gICAgICAgIGdhcyxcbiAgICAgICAgY2FsbHMsXG4gICAgICAgIGFjY2Vzc0xpc3Q6IFtdLFxuICAgICAgICBmZWVUb2tlbixcbiAgICAgIH07XG5cbiAgICAgIHRoaXMuX25vbmNlID0gbm9uY2U7XG4gICAgICB0aGlzLl9nYXMgPSBnYXM7XG4gICAgICB0aGlzLl9tYXhGZWVQZXJHYXMgPSBtYXhGZWVQZXJHYXM7XG4gICAgICB0aGlzLl9tYXhQcmlvcml0eUZlZVBlckdhcyA9IG1heFByaW9yaXR5RmVlUGVyR2FzO1xuICAgICAgdGhpcy5fZmVlVG9rZW4gPSBmZWVUb2tlbjtcbiAgICAgIHRoaXMub3BlcmF0aW9ucyA9IG9wZXJhdGlvbnM7XG4gICAgICB0aGlzLnJhd0NhbGxzID0gZGVjb2RlZFJhd0NhbGxzO1xuICAgICAgdGhpcy5fcmVzdG9yZWRTaWduYXR1cmUgPSBzaWduYXR1cmU7XG5cbiAgICAgIGNvbnN0IHR4ID0gbmV3IFRpcDIwVHJhbnNhY3Rpb24odGhpcy5fY29pbkNvbmZpZywgdHhSZXF1ZXN0LCBvcGVyYXRpb25zLCBkZWNvZGVkUmF3Q2FsbHMpO1xuICAgICAgaWYgKHNpZ25hdHVyZSkge1xuICAgICAgICB0eC5zZXRTaWduYXR1cmUoc2lnbmF0dXJlKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiB0eDtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoZSBpbnN0YW5jZW9mIFBhcnNlVHJhbnNhY3Rpb25FcnJvcikgdGhyb3cgZTtcbiAgICAgIHRocm93IG5ldyBQYXJzZVRyYW5zYWN0aW9uRXJyb3IoYEZhaWxlZCB0byBkZXNlcmlhbGl6ZSBUSVAtMjAgdHJhbnNhY3Rpb246ICR7ZX1gKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogRGVjb2RlIGEgc2luZ2xlIEFBIGNhbGwncyBkYXRhIGJhY2sgaW50byBhIFRpcDIwT3BlcmF0aW9uLlxuICAgKiBSZXR1cm5zIG51bGwgaWYgdGhlIGNhbGwgaXMgbm90IGEgdHJhbnNmZXJXaXRoTWVtbyDigJQgaXQgd2lsbCBiZSBzdG9yZWQgYXMgYSBSYXdDb250cmFjdENhbGwgaW5zdGVhZC5cbiAgICogVGhpcyBwcmVzZXJ2ZXMgY2FsbGRhdGEgZmlkZWxpdHkgZm9yIGFyYml0cmFyeSBzbWFydCBjb250cmFjdCBpbnRlcmFjdGlvbnMuXG4gICAqL1xuICBwcml2YXRlIGRlY29kZUNhbGxUb09wZXJhdGlvbihjYWxsOiB7IHRvOiBBZGRyZXNzOyBkYXRhOiBIZXg7IHZhbHVlOiBiaWdpbnQgfSk6IFRpcDIwT3BlcmF0aW9uIHwgbnVsbCB7XG4gICAgY29uc3QgaWZhY2UgPSBuZXcgZXRoZXJzLnV0aWxzLkludGVyZmFjZShUSVAyMF9UUkFOU0ZFUl9XSVRIX01FTU9fQUJJKTtcbiAgICB0cnkge1xuICAgICAgY29uc3QgZGVjb2RlZCA9IGlmYWNlLmRlY29kZUZ1bmN0aW9uRGF0YSgndHJhbnNmZXJXaXRoTWVtbycsIGNhbGwuZGF0YSk7XG4gICAgICBjb25zdCB0b0FkZHJlc3MgPSBkZWNvZGVkWzBdIGFzIHN0cmluZztcbiAgICAgIGNvbnN0IGFtb3VudFVuaXRzID0gQmlnSW50KGRlY29kZWRbMV0udG9TdHJpbmcoKSk7XG4gICAgICBjb25zdCBtZW1vQnl0ZXMzMiA9IGRlY29kZWRbMl0gYXMgc3RyaW5nO1xuXG4gICAgICBjb25zdCBhbW91bnQgPSB0aXAyMFVuaXRzVG9BbW91bnQoYW1vdW50VW5pdHMpO1xuXG4gICAgICBjb25zdCBzdHJpcHBlZCA9IGV0aGVycy51dGlscy5zdHJpcFplcm9zKG1lbW9CeXRlczMyKTtcbiAgICAgIGNvbnN0IG1lbW8gPSBzdHJpcHBlZC5sZW5ndGggPiAwID8gZXRoZXJzLnV0aWxzLnRvVXRmOFN0cmluZyhzdHJpcHBlZCkgOiB1bmRlZmluZWQ7XG5cbiAgICAgIHJldHVybiB7IHRva2VuOiBjYWxsLnRvLCB0bzogdG9BZGRyZXNzLCBhbW91bnQsIG1lbW8gfTtcbiAgICB9IGNhdGNoIHtcbiAgICAgIC8vIE5vdCBhIHRyYW5zZmVyV2l0aE1lbW8gY2FsbCDigJQgY2FsbGVyIHdpbGwgc3RvcmUgYXMgUmF3Q29udHJhY3RDYWxsXG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQnVpbGQgdGhlIHRyYW5zYWN0aW9uIGZyb20gY29uZmlndXJlZCBUSVAtMjAgb3BlcmF0aW9ucyBhbmQgdHJhbnNhY3Rpb24gcGFyYW1ldGVycy5cbiAgICogU2lnbnMgd2l0aCBfc291cmNlS2V5UGFpciBpZiBpdCBoYXMgYmVlbiBzZXQgdmlhIHNpZ24oeyBrZXkgfSkuXG4gICAqL1xuICBwcm90ZWN0ZWQgYXN5bmMgYnVpbGRJbXBsZW1lbnRhdGlvbigpOiBQcm9taXNlPEJhc2VUcmFuc2FjdGlvbj4ge1xuICAgIGlmIChcbiAgICAgIHRoaXMuX25vbmNlID09PSB1bmRlZmluZWQgfHxcbiAgICAgIHRoaXMuX2dhcyA9PT0gdW5kZWZpbmVkIHx8XG4gICAgICB0aGlzLl9tYXhGZWVQZXJHYXMgPT09IHVuZGVmaW5lZCB8fFxuICAgICAgdGhpcy5fbWF4UHJpb3JpdHlGZWVQZXJHYXMgPT09IHVuZGVmaW5lZFxuICAgICkge1xuICAgICAgdGhyb3cgbmV3IEJ1aWxkVHJhbnNhY3Rpb25FcnJvcignVHJhbnNhY3Rpb24gdmFsaWRhdGlvbiBmYWlsZWQ6IG1pc3NpbmcgcmVxdWlyZWQgZmllbGRzJyk7XG4gICAgfVxuXG4gICAgdGhpcy5mZWUoe1xuICAgICAgZmVlOiB0aGlzLl9tYXhGZWVQZXJHYXMudG9TdHJpbmcoKSxcbiAgICAgIGdhc0xpbWl0OiB0aGlzLl9nYXMudG9TdHJpbmcoKSxcbiAgICAgIGVpcDE1NTk6IHtcbiAgICAgICAgbWF4RmVlUGVyR2FzOiB0aGlzLl9tYXhGZWVQZXJHYXMudG9TdHJpbmcoKSxcbiAgICAgICAgbWF4UHJpb3JpdHlGZWVQZXJHYXM6IHRoaXMuX21heFByaW9yaXR5RmVlUGVyR2FzLnRvU3RyaW5nKCksXG4gICAgICB9LFxuICAgIH0pO1xuXG4gICAgY29uc3QgY2FsbHMgPSB0aGlzLm9wZXJhdGlvbnMubWFwKChvcCkgPT4gdGhpcy5vcGVyYXRpb25Ub0NhbGwob3ApKTtcblxuICAgIGZvciAoY29uc3QgcmF3Q2FsbCBvZiB0aGlzLnJhd0NhbGxzKSB7XG4gICAgICBjYWxscy5wdXNoKHtcbiAgICAgICAgdG86IHJhd0NhbGwudG8gYXMgQWRkcmVzcyxcbiAgICAgICAgZGF0YTogcmF3Q2FsbC5kYXRhIGFzIEhleCxcbiAgICAgICAgdmFsdWU6IHJhd0NhbGwudmFsdWUgPyBCaWdJbnQocmF3Q2FsbC52YWx1ZSkgOiAwbixcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGNvbnN0IHR4UmVxdWVzdDogVGlwMjBUcmFuc2FjdGlvblJlcXVlc3QgPSB7XG4gICAgICB0eXBlOiBBQV9UUkFOU0FDVElPTl9UWVBFLFxuICAgICAgY2hhaW5JZDogdGhpcy5fY29tbW9uLmNoYWluSWRCTigpLnRvTnVtYmVyKCksXG4gICAgICBub25jZTogdGhpcy5fbm9uY2UsXG4gICAgICBtYXhGZWVQZXJHYXM6IHRoaXMuX21heEZlZVBlckdhcyxcbiAgICAgIG1heFByaW9yaXR5RmVlUGVyR2FzOiB0aGlzLl9tYXhQcmlvcml0eUZlZVBlckdhcyxcbiAgICAgIGdhczogdGhpcy5fZ2FzLFxuICAgICAgY2FsbHMsXG4gICAgICBhY2Nlc3NMaXN0OiBbXSxcbiAgICAgIGZlZVRva2VuOiB0aGlzLl9mZWVUb2tlbixcbiAgICB9O1xuXG4gICAgY29uc3QgdHggPSBuZXcgVGlwMjBUcmFuc2FjdGlvbih0aGlzLl9jb2luQ29uZmlnLCB0eFJlcXVlc3QsIHRoaXMub3BlcmF0aW9ucywgdGhpcy5yYXdDYWxscyk7XG5cbiAgICBpZiAodGhpcy5fc291cmNlS2V5UGFpciAmJiB0aGlzLl9zb3VyY2VLZXlQYWlyLmdldEtleXMoKS5wcnYpIHtcbiAgICAgIGNvbnN0IHBydiA9IHRoaXMuX3NvdXJjZUtleVBhaXIuZ2V0S2V5cygpLnBydiE7XG4gICAgICBjb25zdCB1bnNpZ25lZEhleCA9IGF3YWl0IHR4LnNlcmlhbGl6ZSgpO1xuICAgICAgY29uc3QgbXNnSGFzaCA9IGV0aGVycy51dGlscy5rZWNjYWsyNTYoZXRoZXJzLnV0aWxzLmFycmF5aWZ5KHVuc2lnbmVkSGV4KSk7XG4gICAgICBjb25zdCBzaWduaW5nS2V5ID0gbmV3IGV0aGVycy51dGlscy5TaWduaW5nS2V5KCcweCcgKyBwcnYpO1xuICAgICAgY29uc3Qgc2lnID0gc2lnbmluZ0tleS5zaWduRGlnZXN0KGV0aGVycy51dGlscy5hcnJheWlmeShtc2dIYXNoKSk7XG4gICAgICB0eC5zZXRTaWduYXR1cmUoe1xuICAgICAgICByOiBzaWcuciBhcyBIZXgsXG4gICAgICAgIHM6IHNpZy5zIGFzIEhleCxcbiAgICAgICAgeVBhcml0eTogc2lnLnJlY292ZXJ5UGFyYW0gPz8gMCxcbiAgICAgIH0pO1xuICAgIH0gZWxzZSBpZiAodGhpcy5fcmVzdG9yZWRTaWduYXR1cmUpIHtcbiAgICAgIHR4LnNldFNpZ25hdHVyZSh0aGlzLl9yZXN0b3JlZFNpZ25hdHVyZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHR4O1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZCBhIHNpbmdsZSBvcGVyYXRpb24gdG8gdGhlIHRyYW5zYWN0aW9uXG4gICAqIENhbiBiZSBjYWxsZWQgbXVsdGlwbGUgdGltZXMgdG8gY3JlYXRlIGJhdGNoIHRyYW5zYWN0aW9uc1xuICAgKlxuICAgKiBAcGFyYW0gb3BlcmF0aW9uIC0gVElQLTIwIG9wZXJhdGlvbiB3aXRoIHRva2VuLCByZWNpcGllbnQsIGFtb3VudCwgYW5kIG9wdGlvbmFsIG1lbW9cbiAgICogQHJldHVybnMgdGhpcyBidWlsZGVyIGluc3RhbmNlIGZvciBjaGFpbmluZ1xuICAgKi9cbiAgYWRkT3BlcmF0aW9uKG9wZXJhdGlvbjogVGlwMjBPcGVyYXRpb24pOiB0aGlzIHtcbiAgICB0aGlzLnZhbGlkYXRlT3BlcmF0aW9uKG9wZXJhdGlvbik7XG4gICAgdGhpcy5vcGVyYXRpb25zLnB1c2gob3BlcmF0aW9uKTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGQgYSByYXcgc21hcnQgY29udHJhY3QgY2FsbCB3aXRoIHByZS1lbmNvZGVkIGNhbGxkYXRhXG4gICAqIFVzZSB0aGlzIGZvciBhcmJpdHJhcnkgY29udHJhY3QgaW50ZXJhY3Rpb25zIHdoZXJlIHRoZSBVSSBwcm92aWRlcyBBQkktZW5jb2RlZCBjYWxsZGF0YVxuICAgKlxuICAgKiBAcGFyYW0gY2FsbCAtIFJhdyBjb250cmFjdCBjYWxsIHdpdGggdGFyZ2V0IGFkZHJlc3MgYW5kIHByZS1lbmNvZGVkIGNhbGxkYXRhXG4gICAqIEByZXR1cm5zIHRoaXMgYnVpbGRlciBpbnN0YW5jZSBmb3IgY2hhaW5pbmdcbiAgICovXG4gIGFkZFJhd0NhbGwoY2FsbDogUmF3Q29udHJhY3RDYWxsKTogdGhpcyB7XG4gICAgaWYgKCFpc1ZhbGlkQWRkcmVzcyhjYWxsLnRvKSkge1xuICAgICAgdGhyb3cgbmV3IEJ1aWxkVHJhbnNhY3Rpb25FcnJvcihgSW52YWxpZCBjb250cmFjdCBhZGRyZXNzOiAke2NhbGwudG99YCk7XG4gICAgfVxuICAgIGlmICghaXNWYWxpZEhleERhdGEoY2FsbC5kYXRhKSkge1xuICAgICAgdGhyb3cgbmV3IEJ1aWxkVHJhbnNhY3Rpb25FcnJvcihgSW52YWxpZCBjYWxsZGF0YTogbXVzdCBiZSBhIG5vbi1lbXB0eSAweC1wcmVmaXhlZCBoZXggc3RyaW5nIHdpdGggZXZlbiBsZW5ndGhgKTtcbiAgICB9XG4gICAgaWYgKGNhbGwudmFsdWUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgdiA9IEJpZ0ludChjYWxsLnZhbHVlKTtcbiAgICAgICAgaWYgKHYgPCAwbikgdGhyb3cgbmV3IEVycm9yKCk7XG4gICAgICB9IGNhdGNoIHtcbiAgICAgICAgdGhyb3cgbmV3IEJ1aWxkVHJhbnNhY3Rpb25FcnJvcihgSW52YWxpZCB2YWx1ZTogbXVzdCBiZSBhIG5vbi1uZWdhdGl2ZSBpbnRlZ2VyIHN0cmluZ2ApO1xuICAgICAgfVxuICAgIH1cbiAgICB0aGlzLnJhd0NhbGxzLnB1c2goY2FsbCk7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogR2V0IGFsbCByYXcgY29udHJhY3QgY2FsbHMgaW4gdGhpcyB0cmFuc2FjdGlvblxuICAgKiBAcmV0dXJucyBBcnJheSBvZiByYXcgY29udHJhY3QgY2FsbHNcbiAgICovXG4gIGdldFJhd0NhbGxzKCk6IFJhd0NvbnRyYWN0Q2FsbFtdIHtcbiAgICByZXR1cm4gWy4uLnRoaXMucmF3Q2FsbHNdO1xuICB9XG5cbiAgLyoqXG4gICAqIFNldCB3aGljaCBUSVAtMjAgdG9rZW4gd2lsbCBiZSB1c2VkIHRvIHBheSB0cmFuc2FjdGlvbiBmZWVzXG4gICAqIFRoaXMgaXMgYSBnbG9iYWwgc2V0dGluZyBmb3IgdGhlIGVudGlyZSB0cmFuc2FjdGlvblxuICAgKlxuICAgKiBAcGFyYW0gdG9rZW5BZGRyZXNzIC0gQWRkcmVzcyBvZiB0aGUgVElQLTIwIHRva2VuIHRvIHVzZSBmb3IgZmVlc1xuICAgKiBAcmV0dXJucyB0aGlzIGJ1aWxkZXIgaW5zdGFuY2UgZm9yIGNoYWluaW5nXG4gICAqL1xuICBmZWVUb2tlbih0b2tlbkFkZHJlc3M6IHN0cmluZyk6IHRoaXMge1xuICAgIGlmICghaXNWYWxpZEFkZHJlc3ModG9rZW5BZGRyZXNzKSkge1xuICAgICAgdGhyb3cgbmV3IEJ1aWxkVHJhbnNhY3Rpb25FcnJvcihgSW52YWxpZCBmZWUgdG9rZW4gYWRkcmVzczogJHt0b2tlbkFkZHJlc3N9YCk7XG4gICAgfVxuICAgIHRoaXMuX2ZlZVRva2VuID0gdG9rZW5BZGRyZXNzIGFzIEFkZHJlc3M7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogU2V0IHRoZSB0cmFuc2FjdGlvbiBub25jZVxuICAgKlxuICAgKiBAcGFyYW0gbm9uY2UgLSBUcmFuc2FjdGlvbiBub25jZVxuICAgKiBAcmV0dXJucyB0aGlzIGJ1aWxkZXIgaW5zdGFuY2UgZm9yIGNoYWluaW5nXG4gICAqL1xuICBub25jZShub25jZTogbnVtYmVyKTogdGhpcyB7XG4gICAgaWYgKG5vbmNlIDwgMCkge1xuICAgICAgdGhyb3cgbmV3IEJ1aWxkVHJhbnNhY3Rpb25FcnJvcihgSW52YWxpZCBub25jZTogJHtub25jZX1gKTtcbiAgICB9XG4gICAgdGhpcy5fbm9uY2UgPSBub25jZTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBTZXQgdGhlIGdhcyBsaW1pdCBmb3IgdGhlIHRyYW5zYWN0aW9uXG4gICAqXG4gICAqIEBwYXJhbSBnYXMgLSBHYXMgbGltaXRcbiAgICogQHJldHVybnMgdGhpcyBidWlsZGVyIGluc3RhbmNlIGZvciBjaGFpbmluZ1xuICAgKi9cbiAgZ2FzKGdhczogc3RyaW5nIHwgYmlnaW50KTogdGhpcyB7XG4gICAgY29uc3QgZ2FzVmFsdWUgPSB0eXBlb2YgZ2FzID09PSAnc3RyaW5nJyA/IEJpZ0ludChnYXMpIDogZ2FzO1xuICAgIGlmIChnYXNWYWx1ZSA8PSAwbikge1xuICAgICAgdGhyb3cgbmV3IEJ1aWxkVHJhbnNhY3Rpb25FcnJvcihgSW52YWxpZCBnYXMgbGltaXQ6ICR7Z2FzfWApO1xuICAgIH1cbiAgICB0aGlzLl9nYXMgPSBnYXNWYWx1ZTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBTZXQgdGhlIG1heGltdW0gZmVlIHBlciBnYXMgKEVJUC0xNTU5KVxuICAgKlxuICAgKiBAcGFyYW0gbWF4RmVlUGVyR2FzIC0gTWF4aW11bSBmZWUgcGVyIGdhcyBpbiB3ZWlcbiAgICogQHJldHVybnMgdGhpcyBidWlsZGVyIGluc3RhbmNlIGZvciBjaGFpbmluZ1xuICAgKi9cbiAgbWF4RmVlUGVyR2FzKG1heEZlZVBlckdhczogc3RyaW5nIHwgYmlnaW50KTogdGhpcyB7XG4gICAgY29uc3QgZmVlVmFsdWUgPSB0eXBlb2YgbWF4RmVlUGVyR2FzID09PSAnc3RyaW5nJyA/IEJpZ0ludChtYXhGZWVQZXJHYXMpIDogbWF4RmVlUGVyR2FzO1xuICAgIGlmIChmZWVWYWx1ZSA8IDBuKSB7XG4gICAgICB0aHJvdyBuZXcgQnVpbGRUcmFuc2FjdGlvbkVycm9yKGBJbnZhbGlkIG1heEZlZVBlckdhczogJHttYXhGZWVQZXJHYXN9YCk7XG4gICAgfVxuICAgIHRoaXMuX21heEZlZVBlckdhcyA9IGZlZVZhbHVlO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIFNldCB0aGUgbWF4aW11bSBwcmlvcml0eSBmZWUgcGVyIGdhcyAoRUlQLTE1NTkpXG4gICAqXG4gICAqIEBwYXJhbSBtYXhQcmlvcml0eUZlZVBlckdhcyAtIE1heGltdW0gcHJpb3JpdHkgZmVlIHBlciBnYXMgaW4gd2VpXG4gICAqIEByZXR1cm5zIHRoaXMgYnVpbGRlciBpbnN0YW5jZSBmb3IgY2hhaW5pbmdcbiAgICovXG4gIG1heFByaW9yaXR5RmVlUGVyR2FzKG1heFByaW9yaXR5RmVlUGVyR2FzOiBzdHJpbmcgfCBiaWdpbnQpOiB0aGlzIHtcbiAgICBjb25zdCBmZWVWYWx1ZSA9IHR5cGVvZiBtYXhQcmlvcml0eUZlZVBlckdhcyA9PT0gJ3N0cmluZycgPyBCaWdJbnQobWF4UHJpb3JpdHlGZWVQZXJHYXMpIDogbWF4UHJpb3JpdHlGZWVQZXJHYXM7XG4gICAgaWYgKGZlZVZhbHVlIDwgMG4pIHtcbiAgICAgIHRocm93IG5ldyBCdWlsZFRyYW5zYWN0aW9uRXJyb3IoYEludmFsaWQgbWF4UHJpb3JpdHlGZWVQZXJHYXM6ICR7bWF4UHJpb3JpdHlGZWVQZXJHYXN9YCk7XG4gICAgfVxuICAgIHRoaXMuX21heFByaW9yaXR5RmVlUGVyR2FzID0gZmVlVmFsdWU7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogR2V0IGFsbCBvcGVyYXRpb25zIGluIHRoaXMgdHJhbnNhY3Rpb25cbiAgICogQHJldHVybnMgQXJyYXkgb2YgVElQLTIwIG9wZXJhdGlvbnNcbiAgICovXG4gIGdldE9wZXJhdGlvbnMoKTogVGlwMjBPcGVyYXRpb25bXSB7XG4gICAgcmV0dXJuIFsuLi50aGlzLm9wZXJhdGlvbnNdO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCB0aGUgZmVlIHRva2VuIGFkZHJlc3MgaWYgc2V0XG4gICAqIEByZXR1cm5zIEZlZSB0b2tlbiBhZGRyZXNzIG9yIHVuZGVmaW5lZFxuICAgKi9cbiAgZ2V0RmVlVG9rZW4oKTogQWRkcmVzcyB8IHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIHRoaXMuX2ZlZVRva2VuO1xuICB9XG5cbiAgLyoqXG4gICAqIFZhbGlkYXRlIGEgc2luZ2xlIG9wZXJhdGlvblxuICAgKiBAcGFyYW0gb3BlcmF0aW9uIC0gT3BlcmF0aW9uIHRvIHZhbGlkYXRlXG4gICAqIEB0aHJvd3MgQnVpbGRUcmFuc2FjdGlvbkVycm9yIGlmIGludmFsaWRcbiAgICovXG4gIHByaXZhdGUgdmFsaWRhdGVPcGVyYXRpb24ob3BlcmF0aW9uOiBUaXAyME9wZXJhdGlvbik6IHZvaWQge1xuICAgIGlmICghaXNWYWxpZEFkZHJlc3Mob3BlcmF0aW9uLnRva2VuKSkge1xuICAgICAgdGhyb3cgbmV3IEJ1aWxkVHJhbnNhY3Rpb25FcnJvcihgSW52YWxpZCB0b2tlbiBhZGRyZXNzOiAke29wZXJhdGlvbi50b2tlbn1gKTtcbiAgICB9XG5cbiAgICBpZiAoIWlzVmFsaWRBZGRyZXNzKG9wZXJhdGlvbi50bykpIHtcbiAgICAgIHRocm93IG5ldyBCdWlsZFRyYW5zYWN0aW9uRXJyb3IoYEludmFsaWQgcmVjaXBpZW50IGFkZHJlc3M6ICR7b3BlcmF0aW9uLnRvfWApO1xuICAgIH1cblxuICAgIGlmICghaXNWYWxpZFRpcDIwQW1vdW50KG9wZXJhdGlvbi5hbW91bnQpKSB7XG4gICAgICB0aHJvdyBuZXcgQnVpbGRUcmFuc2FjdGlvbkVycm9yKGBJbnZhbGlkIGFtb3VudDogJHtvcGVyYXRpb24uYW1vdW50fWApO1xuICAgIH1cblxuICAgIGlmIChvcGVyYXRpb24ubWVtbyAhPT0gdW5kZWZpbmVkICYmICFpc1ZhbGlkTWVtb0lkKG9wZXJhdGlvbi5tZW1vKSkge1xuICAgICAgdGhyb3cgbmV3IEJ1aWxkVHJhbnNhY3Rpb25FcnJvcihgSW52YWxpZCBtZW1vOiBtdXN0IGJlIGEgbm9uLW5lZ2F0aXZlIGludGVnZXJgKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQ29udmVydCBhIFRJUC0yMCBvcGVyYXRpb24gdG8gYW4gQUEgY2FsbFxuICAgKi9cbiAgcHJpdmF0ZSBvcGVyYXRpb25Ub0NhbGwob3A6IFRpcDIwT3BlcmF0aW9uKTogeyB0bzogQWRkcmVzczsgZGF0YTogSGV4OyB2YWx1ZTogYmlnaW50IH0ge1xuICAgIGNvbnN0IGFtb3VudEluVW5pdHMgPSBhbW91bnRUb1RpcDIwVW5pdHMob3AuYW1vdW50KTtcbiAgICBjb25zdCBkYXRhID0gZW5jb2RlVGlwMjBUcmFuc2ZlcldpdGhNZW1vKG9wLnRvLCBhbW91bnRJblVuaXRzLCBvcC5tZW1vKTtcblxuICAgIHJldHVybiB7XG4gICAgICB0bzogb3AudG9rZW4sXG4gICAgICBkYXRhLFxuICAgICAgdmFsdWU6IDBuLFxuICAgIH07XG4gIH1cbn1cbiJdfQ==
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Type aliases for Ethereum addresses and hex strings
3
+ */
4
+ export type Address = string;
5
+ export type Hex = string;
6
+ export type TransactionSerializedEIP7702 = string;
7
+ /**
8
+ * TIP-20 Operation with optional memo
9
+ * Represents a single transfer operation in a transaction
10
+ */
11
+ export interface Tip20Operation {
12
+ token: Address;
13
+ to: Address;
14
+ amount: string;
15
+ memo?: string;
16
+ }
17
+ /**
18
+ * Raw smart contract call with pre-encoded calldata
19
+ * Used for arbitrary contract interactions (e.g., mint(), approve())
20
+ * where the caller provides the full ABI-encoded calldata
21
+ */
22
+ export interface RawContractCall {
23
+ to: Address;
24
+ data: Hex;
25
+ value?: string;
26
+ }
27
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/lib/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,MAAM,OAAO,GAAG,MAAM,CAAC;AAC7B,MAAM,MAAM,GAAG,GAAG,MAAM,CAAC;AACzB,MAAM,MAAM,4BAA4B,GAAG,MAAM,CAAC;AAElD;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,OAAO,CAAC;IACf,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,OAAO,CAAC;IACZ,IAAI,EAAE,GAAG,CAAC;IACV,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB"}
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvbGliL3R5cGVzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiIiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIFR5cGUgYWxpYXNlcyBmb3IgRXRoZXJldW0gYWRkcmVzc2VzIGFuZCBoZXggc3RyaW5nc1xuICovXG5leHBvcnQgdHlwZSBBZGRyZXNzID0gc3RyaW5nO1xuZXhwb3J0IHR5cGUgSGV4ID0gc3RyaW5nO1xuZXhwb3J0IHR5cGUgVHJhbnNhY3Rpb25TZXJpYWxpemVkRUlQNzcwMiA9IHN0cmluZztcblxuLyoqXG4gKiBUSVAtMjAgT3BlcmF0aW9uIHdpdGggb3B0aW9uYWwgbWVtb1xuICogUmVwcmVzZW50cyBhIHNpbmdsZSB0cmFuc2ZlciBvcGVyYXRpb24gaW4gYSB0cmFuc2FjdGlvblxuICovXG5leHBvcnQgaW50ZXJmYWNlIFRpcDIwT3BlcmF0aW9uIHtcbiAgdG9rZW46IEFkZHJlc3M7XG4gIHRvOiBBZGRyZXNzO1xuICBhbW91bnQ6IHN0cmluZztcbiAgbWVtbz86IHN0cmluZztcbn1cblxuLyoqXG4gKiBSYXcgc21hcnQgY29udHJhY3QgY2FsbCB3aXRoIHByZS1lbmNvZGVkIGNhbGxkYXRhXG4gKiBVc2VkIGZvciBhcmJpdHJhcnkgY29udHJhY3QgaW50ZXJhY3Rpb25zIChlLmcuLCBtaW50KCksIGFwcHJvdmUoKSlcbiAqIHdoZXJlIHRoZSBjYWxsZXIgcHJvdmlkZXMgdGhlIGZ1bGwgQUJJLWVuY29kZWQgY2FsbGRhdGFcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBSYXdDb250cmFjdENhbGwge1xuICB0bzogQWRkcmVzcztcbiAgZGF0YTogSGV4O1xuICB2YWx1ZT86IHN0cmluZztcbn1cbiJdfQ==
@@ -1,25 +1,88 @@
1
1
  /**
2
- * Utility functions for Tempo
2
+ * Tempo Utility Functions
3
+ *
4
+ * Since Tempo is EVM-compatible, we can reuse Ethereum utilities
3
5
  */
6
+ type Address = string;
7
+ type Hex = string;
4
8
  /**
5
- * Check if the address is valid
6
- * @param address
9
+ * Check if address is valid Ethereum-style address
10
+ * Uses ethers.js isAddress for proper validation including checksum
7
11
  */
8
12
  export declare function isValidAddress(address: string): boolean;
9
13
  /**
10
- * Check if the public key is valid
11
- * @param publicKey
14
+ * Check if public key is valid (BIP32 xpub format)
15
+ * TODO: Replace with ETH utils when implementing
12
16
  */
13
17
  export declare function isValidPublicKey(publicKey: string): boolean;
14
18
  /**
15
- * Check if the private key is valid
16
- * @param privateKey
19
+ * Check if private key is valid (BIP32 xprv format)
20
+ * TODO: Replace with ETH utils when implementing
17
21
  */
18
22
  export declare function isValidPrivateKey(privateKey: string): boolean;
23
+ /**
24
+ * TIP-20 Utility Functions
25
+ */
26
+ /**
27
+ * Convert human-readable amount to TIP-20 units (6 decimals)
28
+ * @param amount - Human-readable amount (e.g., "1.5")
29
+ * @returns Amount in TIP-20 smallest units as bigint
30
+ * @example amountToTip20Units("1.5") => 1500000n
31
+ */
32
+ export declare function amountToTip20Units(amount: string): bigint;
33
+ /**
34
+ * Convert TIP-20 units (6 decimals) to human-readable amount
35
+ * @param units - Amount in TIP-20 smallest units
36
+ * @returns Human-readable amount string
37
+ * @example tip20UnitsToAmount(1500000n) => "1.5"
38
+ */
39
+ export declare function tip20UnitsToAmount(units: bigint): string;
40
+ /**
41
+ * Convert string to bytes32 for memo field
42
+ * @param memo - Memo string to encode
43
+ * @returns Hex-encoded bytes32 value
44
+ * @example stringToBytes32("INVOICE-001") => "0x494e564f4943452d30303100..."
45
+ */
46
+ export declare function stringToBytes32(memo: string): Hex;
47
+ /**
48
+ * Encode TIP-20 transferWithMemo function call using ethers.js
49
+ * @param to - Recipient address
50
+ * @param amount - Amount in TIP-20 units (bigint)
51
+ * @param memo - Optional memo string
52
+ * @returns Encoded function call data
53
+ */
54
+ export declare function encodeTip20TransferWithMemo(to: Address, amount: bigint, memo?: string): Hex;
55
+ /**
56
+ * Validate TIP-20 amount format
57
+ * @param amount - Amount string to validate
58
+ * @returns true if valid, false otherwise
59
+ */
60
+ export declare function isValidTip20Amount(amount: string): boolean;
61
+ /**
62
+ * Check if a raw transaction string is a Tempo AA transaction (type 0x76)
63
+ */
64
+ export declare function isTip20Transaction(raw: string): boolean;
65
+ /**
66
+ * Validate that a memoId is a valid non-negative integer string
67
+ */
68
+ export declare function isValidMemoId(memoId: string): boolean;
69
+ /**
70
+ * Validate that a string is a non-empty 0x-prefixed hex string
71
+ * Used to validate pre-encoded calldata for raw contract calls
72
+ */
73
+ export declare function isValidHexData(data: string): boolean;
19
74
  declare const utils: {
20
75
  isValidAddress: typeof isValidAddress;
21
76
  isValidPublicKey: typeof isValidPublicKey;
22
77
  isValidPrivateKey: typeof isValidPrivateKey;
78
+ amountToTip20Units: typeof amountToTip20Units;
79
+ tip20UnitsToAmount: typeof tip20UnitsToAmount;
80
+ stringToBytes32: typeof stringToBytes32;
81
+ encodeTip20TransferWithMemo: typeof encodeTip20TransferWithMemo;
82
+ isValidTip20Amount: typeof isValidTip20Amount;
83
+ isTip20Transaction: typeof isTip20Transaction;
84
+ isValidMemoId: typeof isValidMemoId;
85
+ isValidHexData: typeof isValidHexData;
23
86
  };
24
87
  export default utils;
25
88
  //# sourceMappingURL=utils.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/lib/utils.ts"],"names":[],"mappings":"AAEA;;GAEG;AAEH;;;GAGG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAGvD;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAG3D;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAG7D;AAED,QAAA,MAAM,KAAK;;;;CAIV,CAAC;AAEF,eAAe,KAAK,CAAC"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/lib/utils.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AASH,KAAK,OAAO,GAAG,MAAM,CAAC;AACtB,KAAK,GAAG,GAAG,MAAM,CAAC;AAElB;;;GAGG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAKvD;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAU3D;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAU7D;AAED;;GAEG;AAEH;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAMzD;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAExD;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,GAAG,CAOjD;AAED;;;;;;GAMG;AACH,wBAAgB,2BAA2B,CAAC,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,GAAG,CAK3F;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAc1D;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAEvD;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAErD;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEpD;AAED,QAAA,MAAM,KAAK;;;;;;;;;;;;CAYV,CAAC;AAEF,eAAe,KAAK,CAAC"}