@bitgo-beta/abstract-substrate 1.0.1-beta.9 → 1.0.1-beta.90

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 (45) hide show
  1. package/CHANGELOG.md +41 -0
  2. package/dist/src/abstractSubstrateCoin.d.ts +20 -3
  3. package/dist/src/abstractSubstrateCoin.d.ts.map +1 -1
  4. package/dist/src/abstractSubstrateCoin.js +76 -14
  5. package/dist/src/index.d.ts +1 -0
  6. package/dist/src/index.d.ts.map +1 -1
  7. package/dist/src/index.js +16 -1
  8. package/dist/src/lib/constants.d.ts +2 -0
  9. package/dist/src/lib/constants.d.ts.map +1 -0
  10. package/dist/src/lib/constants.js +5 -0
  11. package/dist/src/lib/errors.d.ts +8 -0
  12. package/dist/src/lib/errors.d.ts.map +1 -0
  13. package/dist/src/lib/errors.js +19 -0
  14. package/dist/src/lib/iface.d.ts +140 -0
  15. package/dist/src/lib/iface.d.ts.map +1 -0
  16. package/dist/src/lib/iface.js +35 -0
  17. package/dist/src/lib/index.d.ts +12 -0
  18. package/dist/src/lib/index.d.ts.map +1 -0
  19. package/dist/src/lib/index.js +61 -0
  20. package/dist/src/lib/keyPair.d.ts +24 -0
  21. package/dist/src/lib/keyPair.d.ts.map +1 -0
  22. package/dist/src/lib/keyPair.js +63 -0
  23. package/dist/src/lib/nativeTransferBuilder.d.ts +61 -0
  24. package/dist/src/lib/nativeTransferBuilder.d.ts.map +1 -0
  25. package/dist/src/lib/nativeTransferBuilder.js +147 -0
  26. package/dist/src/lib/singletonRegistry.d.ts +8 -0
  27. package/dist/src/lib/singletonRegistry.d.ts.map +1 -0
  28. package/dist/src/lib/singletonRegistry.js +20 -0
  29. package/dist/src/lib/transaction.d.ts +73 -0
  30. package/dist/src/lib/transaction.d.ts.map +1 -0
  31. package/dist/src/lib/transaction.js +424 -0
  32. package/dist/src/lib/transactionBuilder.d.ts +121 -0
  33. package/dist/src/lib/transactionBuilder.d.ts.map +1 -0
  34. package/dist/src/lib/transactionBuilder.js +334 -0
  35. package/dist/src/lib/transferBuilder.d.ts +6 -0
  36. package/dist/src/lib/transferBuilder.d.ts.map +1 -0
  37. package/dist/src/lib/transferBuilder.js +11 -0
  38. package/dist/src/lib/txnSchema.d.ts +9 -0
  39. package/dist/src/lib/txnSchema.d.ts.map +1 -0
  40. package/dist/src/lib/txnSchema.js +52 -0
  41. package/dist/src/lib/utils.d.ts +122 -0
  42. package/dist/src/lib/utils.d.ts.map +1 -0
  43. package/dist/src/lib/utils.js +227 -0
  44. package/dist/tsconfig.tsbuildinfo +1 -1
  45. package/package.json +18 -5
@@ -0,0 +1,227 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.Utils = void 0;
7
+ const sdk_core_1 = require("@bitgo-beta/sdk-core");
8
+ const keyring_1 = require("@polkadot/keyring");
9
+ const decode_1 = require("@polkadot/keyring/pair/decode");
10
+ const Extrinsic_1 = require("@polkadot/types/extrinsic/v4/Extrinsic");
11
+ const util_1 = require("@polkadot/util");
12
+ const util_crypto_1 = require("@polkadot/util-crypto");
13
+ const txwrapper_polkadot_1 = require("@substrate/txwrapper-polkadot");
14
+ const bs58_1 = __importDefault(require("bs58"));
15
+ const hi_base32_1 = __importDefault(require("hi-base32"));
16
+ const tweetnacl_1 = __importDefault(require("tweetnacl"));
17
+ const _1 = require(".");
18
+ class Utils {
19
+ /** @inheritdoc */
20
+ isValidAddress(address) {
21
+ try {
22
+ (0, keyring_1.encodeAddress)((0, util_1.isHex)(address) ? (0, util_1.hexToU8a)(address) : (0, keyring_1.decodeAddress)(address));
23
+ return true;
24
+ }
25
+ catch (error) {
26
+ return false;
27
+ }
28
+ }
29
+ /** @inheritdoc */
30
+ isValidBlockId(hash) {
31
+ return (0, util_1.isHex)(hash, 256);
32
+ }
33
+ /** @inheritdoc */
34
+ isValidPrivateKey(key) {
35
+ try {
36
+ const decodedPrv = (0, util_1.hexToU8a)(key);
37
+ return decodedPrv.length === tweetnacl_1.default.sign.secretKeyLength / 2;
38
+ }
39
+ catch (e) {
40
+ return false;
41
+ }
42
+ }
43
+ /** @inheritdoc */
44
+ isValidPublicKey(key) {
45
+ let pubKey = key;
46
+ // convert base58 pub key to hex format
47
+ // tss common pub is in base58 format and decodes to length of 32
48
+ if ((0, sdk_core_1.isBase58)(pubKey, 32)) {
49
+ const base58Decode = bs58_1.default.decode(pubKey);
50
+ pubKey = base58Decode.toString('hex');
51
+ }
52
+ return (0, sdk_core_1.isValidEd25519PublicKey)(pubKey);
53
+ }
54
+ /** @inheritdoc */
55
+ isValidSignature(signature) {
56
+ const signatureU8a = (0, util_1.u8aToU8a)(signature);
57
+ return [64, 65, 66].includes(signatureU8a.length);
58
+ }
59
+ /**
60
+ * Verifies the signature on a given message
61
+ *
62
+ * @param {string} signedMessage the signed message for the signature
63
+ * @param {string} signature the signature to verify
64
+ * @param {string} address the address of the signer
65
+ * @returns {boolean} whether the signature is valid or not
66
+ */
67
+ verifySignature(signedMessage, signature, address) {
68
+ const publicKey = (0, keyring_1.decodeAddress)(address);
69
+ const hexPublicKey = (0, util_1.u8aToHex)(publicKey);
70
+ return (0, util_crypto_1.signatureVerify)(signedMessage, signature, hexPublicKey).isValid;
71
+ }
72
+ /** @inheritdoc */
73
+ isValidTransactionId(txId) {
74
+ return (0, util_1.isHex)(txId, 256);
75
+ }
76
+ /**
77
+ * decodeSeed decodes a substrate seed
78
+ *
79
+ * @param {string} seed - the seed to be validated.
80
+ * @returns {Seed} - the object Seed
81
+ */
82
+ decodeSeed(seed) {
83
+ const decoded = hi_base32_1.default.decode.asBytes(seed);
84
+ return {
85
+ seed: Buffer.from(decoded),
86
+ };
87
+ }
88
+ /**
89
+ * keyPairFromSeed generates an object with secretKey and publicKey using the substrate sdk
90
+ * @param seed 32 bytes long seed
91
+ * @returns KeyPair
92
+ */
93
+ keyPairFromSeed(seed) {
94
+ const keyring = new keyring_1.Keyring({ type: 'ed25519' });
95
+ const keyringPair = keyring.addFromSeed(seed);
96
+ const pairJson = keyringPair.toJson();
97
+ const decodedKeyPair = (0, decode_1.decodePair)('', (0, util_crypto_1.base64Decode)(pairJson.encoded), pairJson.encoding.type);
98
+ return new _1.KeyPair({ prv: Buffer.from(decodedKeyPair.secretKey).toString('hex') });
99
+ }
100
+ /**
101
+ * Signing function. Implement this on the OFFLINE signing device.
102
+ *
103
+ * @param {KeyringPair} pair - The signing pair.
104
+ * @param {string} signingPayload - Payload to sign.
105
+ * @param {UnsignedTransaction} transaction - raw transaction to sign
106
+ * @param {Object} options
107
+ * @param {HexString} options.metadataRpc - metadata that is needed for substrate to sign
108
+ * @param {TypeRegistry} options.registry - metadata that is needed for substrate to sign
109
+ */
110
+ createSignedTx(pair, signingPayload, transaction, options) {
111
+ const { registry, metadataRpc } = options;
112
+ const { signature } = registry
113
+ .createType('ExtrinsicPayload', signingPayload, {
114
+ version: Extrinsic_1.EXTRINSIC_VERSION,
115
+ })
116
+ .sign(pair);
117
+ // Serialize a signed transaction.
118
+ return this.serializeSignedTransaction(transaction, signature, metadataRpc, registry);
119
+ }
120
+ /**
121
+ * Serializes the signed transaction
122
+ *
123
+ * @param transaction Transaction to serialize
124
+ * @param signature Signature of the message
125
+ * @param metadataRpc Network metadata
126
+ * @param registry Transaction registry
127
+ * @returns string Serialized transaction
128
+ */
129
+ serializeSignedTransaction(transaction, signature, metadataRpc, registry) {
130
+ return txwrapper_polkadot_1.construct.signedTx(transaction, signature, {
131
+ metadataRpc,
132
+ registry,
133
+ });
134
+ }
135
+ /**
136
+ * Decodes the substrate address from the given format
137
+ *
138
+ * @param {string} address
139
+ * @param {number} [ss58Format]
140
+ * @returns {string}
141
+ */
142
+ decodeSubstrateAddress(address, ss58Format) {
143
+ const keypair = new _1.KeyPair({ pub: Buffer.from((0, keyring_1.decodeAddress)(address, undefined, ss58Format)).toString('hex') });
144
+ return keypair.getAddress(ss58Format);
145
+ }
146
+ /**
147
+ * Decodes the substrate address from the given format
148
+ *
149
+ * @param {string} address
150
+ * @param {number} [ss58Format]
151
+ * @returns {string}
152
+ */
153
+ encodeSubstrateAddress(address, ss58Format) {
154
+ return (0, keyring_1.encodeAddress)(address, ss58Format);
155
+ }
156
+ /**
157
+ * Retrieves the txHash of a signed txHex
158
+ *
159
+ * @param txHex signed transaction hex
160
+ * @returns {string}
161
+ */
162
+ getTxHash(txHex) {
163
+ return txwrapper_polkadot_1.construct.txHash(txHex);
164
+ }
165
+ isSigningPayload(payload) {
166
+ return payload.blockHash !== undefined;
167
+ }
168
+ isTransfer(arg) {
169
+ return arg.dest?.id !== undefined && arg.value !== undefined;
170
+ }
171
+ isTransferAll(arg) {
172
+ return arg.dest?.id !== undefined && arg.keepAlive !== undefined;
173
+ }
174
+ isAddStake(arg) {
175
+ return (arg.amountStaked !== undefined &&
176
+ arg.hotkey !== undefined &&
177
+ arg.netuid !== undefined);
178
+ }
179
+ isRemoveStake(arg) {
180
+ return (arg.amountUnstaked !== undefined &&
181
+ arg.hotkey !== undefined &&
182
+ arg.netuid !== undefined);
183
+ }
184
+ /**
185
+ * extracts and returns the signature in hex format given a raw signed transaction
186
+ *
187
+ * @param {string} rawTx signed raw transaction
188
+ * @param options registry substrate registry used to retrieve the signature
189
+ */
190
+ recoverSignatureFromRawTx(rawTx, options) {
191
+ const { registry } = options;
192
+ const methodCall = registry.createType('Extrinsic', rawTx, {
193
+ isSigned: true,
194
+ });
195
+ let signature = (0, util_1.u8aToHex)(methodCall.signature);
196
+ // remove 0x from the signature since this is how it's returned from TSS signing
197
+ if (signature.startsWith('0x')) {
198
+ signature = signature.substr(2);
199
+ }
200
+ return signature;
201
+ }
202
+ /**
203
+ * Decodes the dot address from the given format
204
+ *
205
+ * @param {string} address
206
+ * @param {number} [ss58Format]
207
+ * @returns {KeyPair}
208
+ */
209
+ decodeSubstrateAddressToKeyPair(address, ss58Format) {
210
+ return new _1.KeyPair({ pub: Buffer.from((0, keyring_1.decodeAddress)(address, undefined, ss58Format)).toString('hex') });
211
+ }
212
+ /**
213
+ * Checks whether the given input is a hex string with with 0 value
214
+ * used to check whether a given transaction is immortal or mortal
215
+ * @param hexValue
216
+ */
217
+ isZeroHex(hexValue) {
218
+ return hexValue === '0x00';
219
+ }
220
+ getMaterial(networkType) {
221
+ throw new Error('Method not implemented.');
222
+ }
223
+ }
224
+ exports.Utils = Utils;
225
+ const utils = new Utils();
226
+ exports.default = utils;
227
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvbGliL3V0aWxzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7OztBQUFBLG1EQUEwRjtBQUUxRiwrQ0FBMEU7QUFDMUUsMERBQTJEO0FBRTNELHNFQUEyRTtBQUMzRSx5Q0FBcUU7QUFDckUsdURBQXNFO0FBR3RFLHNFQUEwRDtBQUMxRCxnREFBd0I7QUFDeEIsMERBQStCO0FBQy9CLDBEQUE2QjtBQUM3Qix3QkFBNEI7QUFHNUIsTUFBYSxLQUFLO0lBQ2hCLGtCQUFrQjtJQUNsQixjQUFjLENBQUMsT0FBZTtRQUM1QixJQUFJLENBQUM7WUFDSCxJQUFBLHVCQUFhLEVBQUMsSUFBQSxZQUFLLEVBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUEsZUFBUSxFQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFBLHVCQUFhLEVBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQztZQUMzRSxPQUFPLElBQUksQ0FBQztRQUNkLENBQUM7UUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1lBQ2YsT0FBTyxLQUFLLENBQUM7UUFDZixDQUFDO0lBQ0gsQ0FBQztJQUVELGtCQUFrQjtJQUNsQixjQUFjLENBQUMsSUFBWTtRQUN6QixPQUFPLElBQUEsWUFBSyxFQUFDLElBQUksRUFBRSxHQUFHLENBQUMsQ0FBQztJQUMxQixDQUFDO0lBRUQsa0JBQWtCO0lBQ2xCLGlCQUFpQixDQUFDLEdBQVc7UUFDM0IsSUFBSSxDQUFDO1lBQ0gsTUFBTSxVQUFVLEdBQUcsSUFBQSxlQUFRLEVBQUMsR0FBRyxDQUFDLENBQUM7WUFDakMsT0FBTyxVQUFVLENBQUMsTUFBTSxLQUFLLG1CQUFJLENBQUMsSUFBSSxDQUFDLGVBQWUsR0FBRyxDQUFDLENBQUM7UUFDN0QsQ0FBQztRQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7WUFDWCxPQUFPLEtBQUssQ0FBQztRQUNmLENBQUM7SUFDSCxDQUFD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QUMsSUFBQSx1QkFBYSxFQUFDLE9BQU8sRUFBRSxTQUFTLEVBQUUsVUFBVSxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQzFHLENBQUM7SUFFRDs7OztPQUlHO0lBQ0gsU0FBUyxDQUFDLFFBQWdCO1FBQ3hCLE9BQU8sUUFBUSxLQUFLLE1BQU0sQ0FBQztJQUM3QixDQUFDO0lBRUQsV0FBVyxDQUFDLFdBQXdCO1FBQ2xDLE1BQU0sSUFBSSxLQUFLLENBQUMseUJBQXlCLENBQUMsQ0FBQztJQUM3QyxDQUFDO0NBQ0Y7QUEvT0Qsc0JBK09DO0FBRUQsTUFBTSxLQUFLLEdBQUcsSUFBSSxLQUFLLEVBQUUsQ0FBQztBQUUxQixrQkFBZSxLQUFLLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBCYXNlVXRpbHMsIGlzQmFzZTU4LCBpc1ZhbGlkRWQyNTUxOVB1YmxpY0tleSwgU2VlZCB9IGZyb20gJ0BiaXRnby1iZXRhL3Nkay1jb3JlJztcbmltcG9ydCB7IE5ldHdvcmtUeXBlIH0gZnJvbSAnQGJpdGdvLWJldGEvc3RhdGljcyc7XG5pbXBvcnQgeyBkZWNvZGVBZGRyZXNzLCBlbmNvZGVBZGRyZXNzLCBLZXlyaW5nIH0gZnJvbSAnQHBvbGthZG90L2tleXJpbmcnO1xuaW1wb3J0IHsgZGVjb2RlUGFpciB9IGZyb20gJ0Bwb2xrYWRvdC9rZXlyaW5nL3BhaXIvZGVjb2RlJztcbmltcG9ydCB7IEtleXJpbmdQYWlyIH0gZnJvbSAnQHBvbGthZG90L2tleXJpbmcvdHlwZXMnO1xuaW1wb3J0IHsgRVhUUklOU0lDX1ZFUlNJT04gfSBmcm9tICdAcG9sa2Fkb3QvdHlwZXMvZXh0cmluc2ljL3Y0L0V4dHJpbnNpYyc7XG5pbXBvcnQgeyBoZXhUb1U4YSwgaXNIZXgsIHU4YVRvSGV4LCB1OGFUb1U4YSB9IGZyb20gJ0Bwb2xrYWRvdC91dGlsJztcbmltcG9ydCB7IGJhc2U2NERlY29kZSwgc2lnbmF0dXJlVmVyaWZ5IH0gZnJvbSAnQHBvbGthZG90L3V0aWwtY3J5cHRvJztcbmltcG9ydCB7IFVuc2lnbmVkVHJhbnNhY3Rpb24gfSBmcm9tICdAc3Vic3RyYXRlL3R4d3JhcHBlci1jb3JlJztcbmltcG9ydCB7IERlY29kZWRTaWduZWRUeCwgRGVjb2RlZFNpZ25pbmdQYXlsb2FkLCBUeXBlUmVnaXN0cnkgfSBmcm9tICdAc3Vic3RyYXRlL3R4d3JhcHBlci1jb3JlL2xpYi90eXBlcyc7XG5pbXBvcnQgeyBjb25zdHJ1Y3QgfSBmcm9tICdAc3Vic3RyYXRlL3R4d3JhcHBlci1wb2xrYWRvdCc7XG5pbXBvcnQgYnM1OCBmcm9tICdiczU4JztcbmltcG9ydCBiYXNlMzIgZnJvbSAnaGktYmFzZTMyJztcbmltcG9ydCBuYWNsIGZyb20gJ3R3ZWV0bmFjbCc7XG5pbXBvcnQgeyBLZXlQYWlyIH0gZnJvbSAnLic7XG5pbXBvcnQgeyBIZXhTdHJpbmcsIE1hdGVyaWFsLCBUcmFuc2ZlckFsbEFyZ3MsIFRyYW5zZmVyQXJncywgVHhNZXRob2QsIEFkZFN0YWtlQXJncywgUmVtb3ZlU3Rha2VBcmdzIH0gZnJvbSAnLi9pZmFjZSc7XG5cbmV4cG9ydCBjbGFzcyBVdGlscyBpbXBsZW1lbnRzIEJhc2VVdGlscyB7XG4gIC8qKiBAaW5oZXJpdGRvYyAqL1xuICBpc1ZhbGlkQWRkcmVzcyhhZGRyZXNzOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICB0cnkge1xuICAgICAgZW5jb2RlQWRkcmVzcyhpc0hleChhZGRyZXNzKSA/IGhleFRvVThhKGFkZHJlc3MpIDogZGVjb2RlQWRkcmVzcyhhZGRyZXNzKSk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBAaW5oZXJpdGRvYyAqL1xuICBpc1ZhbGlkQmxvY2tJZChoYXNoOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICByZXR1cm4gaXNIZXgoaGFzaCwgMjU2KTtcbiAgfVxuXG4gIC8qKiBAaW5oZXJpdGRvYyAqL1xuICBpc1ZhbGlkUHJpdmF0ZUtleShrZXk6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBkZWNvZGVkUHJ2ID0gaGV4VG9VOGEoa2V5KTtcbiAgICAgIHJldHVybiBkZWNvZGVkUHJ2Lmxlbmd0aCA9PT0gbmFjbC5zaWduLnNlY3JldEtleUxlbmd0aCAvIDI7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBAaW5oZXJpdGRvYyAqL1xuICBpc1ZhbGlkUHVibGljS2V5KGtleTogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgbGV0IHB1YktleSA9IGtleTtcblxuICAgIC8vIGNvbnZlcnQgYmFzZTU4IHB1YiBrZXkgdG8gaGV4IGZvcm1hdFxuICAgIC8vIHRzcyBjb21tb24gcHViIGlzIGluIGJhc2U1OCBmb3JtYXQgYW5kIGRlY29kZXMgdG8gbGVuZ3RoIG9mIDMyXG4gICAgaWYgKGlzQmFzZTU4KHB1YktleSwgMzIpKSB7XG4gICAgICBjb25zdCBiYXNlNThEZWNvZGUgPSBiczU4LmRlY29kZShwdWJLZXkpO1xuICAgICAgcHViS2V5ID0gYmFzZTU4RGVjb2RlLnRvU3RyaW5nKCdoZXgnKTtcbiAgICB9XG5cbiAgICByZXR1cm4gaXNWYWxpZEVkMjU1MTlQdWJsaWNLZXkocHViS2V5KTtcbiAgfVxuXG4gIC8qKiBAaW5oZXJpdGRvYyAqL1xuICBpc1ZhbGlkU2lnbmF0dXJlKHNpZ25hdHVyZTogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgY29uc3Qgc2lnbmF0dXJlVThhID0gdThhVG9VOGEoc2lnbmF0dXJlKTtcbiAgICByZXR1cm4gWzY0LCA2NSwgNjZdLmluY2x1ZGVzKHNpZ25hdHVyZVU4YS5sZW5ndGgpO1xuICB9XG5cbiAgLyoqXG4gICAqIFZlcmlmaWVzIHRoZSBzaWduYXR1cmUgb24gYSBnaXZlbiBtZXNzYWdlXG4gICAqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBzaWduZWRNZXNzYWdlIHRoZSBzaWduZWQgbWVzc2FnZSBmb3IgdGhlIHNpZ25hdHVyZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gc2lnbmF0dXJlIHRoZSBzaWduYXR1cmUgdG8gdmVyaWZ5XG4gICAqIEBwYXJhbSB7c3RyaW5nfSBhZGRyZXNzIHRoZSBhZGRyZXNzIG9mIHRoZSBzaWduZXJcbiAgICogQHJldHVybnMge2Jvb2xlYW59IHdoZXRoZXIgdGhlIHNpZ25hdHVyZSBpcyB2YWxpZCBvciBub3RcbiAgICovXG4gIHZlcmlmeVNpZ25hdHVyZShzaWduZWRNZXNzYWdlOiBzdHJpbmcsIHNpZ25hdHVyZTogc3RyaW5nLCBhZGRyZXNzOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICBjb25zdCBwdWJsaWNLZXkgPSBkZWNvZGVBZGRyZXNzKGFkZHJlc3MpO1xuICAgIGNvbnN0IGhleFB1YmxpY0tleSA9IHU4YVRvSGV4KHB1YmxpY0tleSk7XG5cbiAgICByZXR1cm4gc2lnbmF0dXJlVmVyaWZ5KHNpZ25lZE1lc3NhZ2UsIHNpZ25hdHVyZSwgaGV4UHVibGljS2V5KS5pc1ZhbGlkO1xuICB9XG5cbiAgLyoqIEBpbmhlcml0ZG9jICovXG4gIGlzVmFsaWRUcmFuc2FjdGlvbklkKHR4SWQ6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIHJldHVybiBpc0hleCh0eElkLCAyNTYpO1xuICB9XG5cbiAgLyoqXG4gICAqIGRlY29kZVNlZWQgZGVjb2RlcyBhIHN1YnN0cmF0ZSBzZWVkXG4gICAqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBzZWVkIC0gdGhlIHNlZWQgdG8gYmUgdmFsaWRhdGVkLlxuICAgKiBAcmV0dXJucyB7U2VlZH0gLSB0aGUgb2JqZWN0IFNlZWRcbiAgICovXG4gIGRlY29kZVNlZWQoc2VlZDogc3RyaW5nKTogU2VlZCB7XG4gICAgY29uc3QgZGVjb2RlZCA9IGJhc2UzMi5kZWNvZGUuYXNCeXRlcyhzZWVkKTtcbiAgICByZXR1cm4ge1xuICAgICAgc2VlZDogQnVmZmVyLmZyb20oZGVjb2RlZCksXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBrZXlQYWlyRnJvbVNlZWQgZ2VuZXJhdGVzIGFuIG9iamVjdCB3aXRoIHNlY3JldEtleSBhbmQgcHVibGljS2V5IHVzaW5nIHRoZSBzdWJzdHJhdGUgc2RrXG4gICAqIEBwYXJhbSBzZWVkIDMyIGJ5dGVzIGxvbmcgc2VlZFxuICAgKiBAcmV0dXJucyBLZXlQYWlyXG4gICAqL1xuICBrZXlQYWlyRnJvbVNlZWQoc2VlZDogVWludDhBcnJheSk6IEtleVBhaXIge1xuICAgIGNvbnN0IGtleXJpbmcgPSBuZXcgS2V5cmluZyh7IHR5cGU6ICdlZDI1NTE5JyB9KTtcbiAgICBjb25zdCBrZXlyaW5nUGFpciA9IGtleXJpbmcuYWRkRnJvbVNlZWQoc2VlZCk7XG4gICAgY29uc3QgcGFpckpzb24gPSBrZXlyaW5nUGFpci50b0pzb24oKTtcbiAgICBjb25zdCBkZWNvZGVkS2V5UGFpciA9IGRlY29kZVBhaXIoJycsIGJhc2U2NERlY29kZShwYWlySnNvbi5lbmNvZGVkKSwgcGFpckpzb24uZW5jb2RpbmcudHlwZSk7XG4gICAgcmV0dXJuIG5ldyBLZXlQYWlyKHsgcHJ2OiBCdWZmZXIuZnJvbShkZWNvZGVkS2V5UGFpci5zZWNyZXRLZXkpLnRvU3RyaW5nKCdoZXgnKSB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTaWduaW5nIGZ1bmN0aW9uLiBJbXBsZW1lbnQgdGhpcyBvbiB0aGUgT0ZGTElORSBzaWduaW5nIGRldmljZS5cbiAgICpcbiAgICogQHBhcmFtIHtLZXlyaW5nUGFpcn0gcGFpciAtIFRoZSBzaWduaW5nIHBhaXIuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBzaWduaW5nUGF5bG9hZCAtIFBheWxvYWQgdG8gc2lnbi5cbiAgICogQHBhcmFtIHtVbnNpZ25lZFRyYW5zYWN0aW9ufSB0cmFuc2FjdGlvbiAtIHJhdyB0cmFuc2FjdGlvbiB0byBzaWduXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zXG4gICAqIEBwYXJhbSB7SGV4U3RyaW5nfSBvcHRpb25zLm1ldGFkYXRhUnBjIC0gbWV0YWRhdGEgdGhhdCBpcyBuZWVkZWQgZm9yIHN1YnN0cmF0ZSB0byBzaWduXG4gICAqIEBwYXJhbSB7VHlwZVJlZ2lzdHJ5fSBvcHRpb25zLnJlZ2lzdHJ5IC0gbWV0YWRhdGEgdGhhdCBpcyBuZWVkZWQgZm9yIHN1YnN0cmF0ZSB0byBzaWduXG4gICAqL1xuICBjcmVhdGVTaWduZWRUeChcbiAgICBwYWlyOiBLZXlyaW5nUGFpcixcbiAgICBzaWduaW5nUGF5bG9hZDogc3RyaW5nLFxuICAgIHRyYW5zYWN0aW9uOiBVbnNpZ25lZFRyYW5zYWN0aW9uLFxuICAgIG9wdGlvbnM6IHsgbWV0YWRhdGFScGM6IEhleFN0cmluZzsgcmVnaXN0cnk6IFR5cGVSZWdpc3RyeSB9XG4gICk6IHN0cmluZyB7XG4gICAgY29uc3QgeyByZWdpc3RyeSwgbWV0YWRhdGFScGMgfSA9IG9wdGlvbnM7XG4gICAgY29uc3QgeyBzaWduYXR1cmUgfSA9IHJlZ2lzdHJ5XG4gICAgICAuY3JlYXRlVHlwZSgnRXh0cmluc2ljUGF5bG9hZCcsIHNpZ25pbmdQYXlsb2FkLCB7XG4gICAgICAgIHZlcnNpb246IEVYVFJJTlNJQ19WRVJTSU9OLFxuICAgICAgfSlcbiAgICAgIC5zaWduKHBhaXIpO1xuXG4gICAgLy8gU2VyaWFsaXplIGEgc2lnbmVkIHRyYW5zYWN0aW9uLlxuICAgIHJldHVybiB0aGlzLnNlcmlhbGl6ZVNpZ25lZFRyYW5zYWN0aW9uKHRyYW5zYWN0aW9uLCBzaWduYXR1cmUsIG1ldGFkYXRhUnBjLCByZWdpc3RyeSk7XG4gIH1cblxuICAvKipcbiAgICogU2VyaWFsaXplcyB0aGUgc2lnbmVkIHRyYW5zYWN0aW9uXG4gICAqXG4gICAqIEBwYXJhbSB0cmFuc2FjdGlvbiBUcmFuc2FjdGlvbiB0byBzZXJpYWxpemVcbiAgICogQHBhcmFtIHNpZ25hdHVyZSBTaWduYXR1cmUgb2YgdGhlIG1lc3NhZ2VcbiAgICogQHBhcmFtIG1ldGFkYXRhUnBjIE5ldHdvcmsgbWV0YWRhdGFcbiAgICogQHBhcmFtIHJlZ2lzdHJ5IFRyYW5zYWN0aW9uIHJlZ2lzdHJ5XG4gICAqIEByZXR1cm5zIHN0cmluZyBTZXJpYWxpemVkIHRyYW5zYWN0aW9uXG4gICAqL1xuICBzZXJpYWxpemVTaWduZWRUcmFuc2FjdGlvbih0cmFuc2FjdGlvbiwgc2lnbmF0dXJlLCBtZXRhZGF0YVJwYzogYDB4JHtzdHJpbmd9YCwgcmVnaXN0cnkpOiBzdHJpbmcge1xuICAgIHJldHVybiBjb25zdHJ1Y3Quc2lnbmVkVHgodHJhbnNhY3Rpb24sIHNpZ25hdHVyZSwge1xuICAgICAgbWV0YWRhdGFScGMsXG4gICAgICByZWdpc3RyeSxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBEZWNvZGVzIHRoZSBzdWJzdHJhdGUgYWRkcmVzcyBmcm9tIHRoZSBnaXZlbiBmb3JtYXRcbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IGFkZHJlc3NcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtzczU4Rm9ybWF0XVxuICAgKiBAcmV0dXJucyB7c3RyaW5nfVxuICAgKi9cbiAgZGVjb2RlU3Vic3RyYXRlQWRkcmVzcyhhZGRyZXNzOiBzdHJpbmcsIHNzNThGb3JtYXQ6IG51bWJlcik6IHN0cmluZyB7XG4gICAgY29uc3Qga2V5cGFpciA9IG5ldyBLZXlQYWlyKHsgcHViOiBCdWZmZXIuZnJvbShkZWNvZGVBZGRyZXNzKGFkZHJlc3MsIHVuZGVmaW5lZCwgc3M1OEZvcm1hdCkpLnRvU3RyaW5nKCdoZXgnKSB9KTtcbiAgICByZXR1cm4ga2V5cGFpci5nZXRBZGRyZXNzKHNzNThGb3JtYXQpO1xuICB9XG5cbiAgLyoqXG4gICAqIERlY29kZXMgdGhlIHN1YnN0cmF0ZSBhZGRyZXNzIGZyb20gdGhlIGdpdmVuIGZvcm1hdFxuICAgKlxuICAgKiBAcGFyYW0ge3N0cmluZ30gYWRkcmVzc1xuICAgKiBAcGFyYW0ge251bWJlcn0gW3NzNThGb3JtYXRdXG4gICAqIEByZXR1cm5zIHtzdHJpbmd9XG4gICAqL1xuICBlbmNvZGVTdWJzdHJhdGVBZGRyZXNzKGFkZHJlc3M6IHN0cmluZywgc3M1OEZvcm1hdD86IG51bWJlcik6IHN0cmluZyB7XG4gICAgcmV0dXJuIGVuY29kZUFkZHJlc3MoYWRkcmVzcywgc3M1OEZvcm1hdCk7XG4gIH1cblxuICAvKipcbiAgICogUmV0cmlldmVzIHRoZSB0eEhhc2ggb2YgYSBzaWduZWQgdHhIZXhcbiAgICpcbiAgICogQHBhcmFtIHR4SGV4IHNpZ25lZCB0cmFuc2FjdGlvbiBoZXhcbiAgICogQHJldHVybnMge3N0cmluZ31cbiAgICovXG4gIGdldFR4SGFzaCh0eEhleDogc3RyaW5nKTogc3RyaW5nIHtcbiAgICByZXR1cm4gY29uc3RydWN0LnR4SGFzaCh0eEhleCk7XG4gIH1cblxuICBpc1NpZ25pbmdQYXlsb2FkKHBheWxvYWQ6IERlY29kZWRTaWduaW5nUGF5bG9hZCB8IERlY29kZWRTaWduZWRUeCk6IHBheWxvYWQgaXMgRGVjb2RlZFNpZ25pbmdQYXlsb2FkIHtcbiAgICByZXR1cm4gKHBheWxvYWQgYXMgRGVjb2RlZFNpZ25pbmdQYXlsb2FkKS5ibG9ja0hhc2ggIT09IHVuZGVmaW5lZDtcbiAgfVxuXG4gIGlzVHJhbnNmZXIoYXJnOiBUeE1ldGhvZFsnYXJncyddKTogYXJnIGlzIFRyYW5zZmVyQXJncyB7XG4gICAgcmV0dXJuIChhcmcgYXMgVHJhbnNmZXJBcmdzKS5kZXN0Py5pZCAhPT0gdW5kZWZpbmVkICYmIChhcmcgYXMgVHJhbnNmZXJBcmdzKS52YWx1ZSAhPT0gdW5kZWZpbmVkO1xuICB9XG5cbiAgaXNUcmFuc2ZlckFsbChhcmc6IFR4TWV0aG9kWydhcmdzJ10pOiBhcmcgaXMgVHJhbnNmZXJBbGxBcmdzIHtcbiAgICByZXR1cm4gKGFyZyBhcyBUcmFuc2ZlckFsbEFyZ3MpLmRlc3Q/LmlkICE9PSB1bmRlZmluZWQgJiYgKGFyZyBhcyBUcmFuc2ZlckFsbEFyZ3MpLmtlZXBBbGl2ZSAhPT0gdW5kZWZpbmVkO1xuICB9XG5cbiAgaXNBZGRTdGFrZShhcmc6IFR4TWV0aG9kWydhcmdzJ10pOiBhcmcgaXMgQWRkU3Rha2VBcmdzIHtcbiAgICByZXR1cm4gKFxuICAgICAgKGFyZyBhcyBBZGRTdGFrZUFyZ3MpLmFtb3VudFN0YWtlZCAhPT0gdW5kZWZpbmVkICYmXG4gICAgICAoYXJnIGFzIEFkZFN0YWtlQXJncykuaG90a2V5ICE9PSB1bmRlZmluZWQgJiZcbiAgICAgIChhcmcgYXMgQWRkU3Rha2VBcmdzKS5uZXR1aWQgIT09IHVuZGVmaW5lZFxuICAgICk7XG4gIH1cblxuICBpc1JlbW92ZVN0YWtlKGFyZzogVHhNZXRob2RbJ2FyZ3MnXSk6IGFyZyBpcyBSZW1vdmVTdGFrZUFyZ3Mge1xuICAgIHJldHVybiAoXG4gICAgICAoYXJnIGFzIFJlbW92ZVN0YWtlQXJncykuYW1vdW50VW5zdGFrZWQgIT09IHVuZGVmaW5lZCAmJlxuICAgICAgKGFyZyBhcyBSZW1vdmVTdGFrZUFyZ3MpLmhvdGtleSAhPT0gdW5kZWZpbmVkICYmXG4gICAgICAoYXJnIGFzIFJlbW92ZVN0YWtlQXJncykubmV0dWlkICE9PSB1bmRlZmluZWRcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIGV4dHJhY3RzIGFuZCByZXR1cm5zIHRoZSBzaWduYXR1cmUgaW4gaGV4IGZvcm1hdCBnaXZlbiBhIHJhdyBzaWduZWQgdHJhbnNhY3Rpb25cbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IHJhd1R4IHNpZ25lZCByYXcgdHJhbnNhY3Rpb25cbiAgICogQHBhcmFtIG9wdGlvbnMgcmVnaXN0cnkgc3Vic3RyYXRlIHJlZ2lzdHJ5IHVzZWQgdG8gcmV0cmlldmUgdGhlIHNpZ25hdHVyZVxuICAgKi9cbiAgcmVjb3ZlclNpZ25hdHVyZUZyb21SYXdUeChyYXdUeDogc3RyaW5nLCBvcHRpb25zOiB7IHJlZ2lzdHJ5OiBUeXBlUmVnaXN0cnkgfSk6IHN0cmluZyB7XG4gICAgY29uc3QgeyByZWdpc3RyeSB9ID0gb3B0aW9ucztcbiAgICBjb25zdCBtZXRob2RDYWxsID0gcmVnaXN0cnkuY3JlYXRlVHlwZSgnRXh0cmluc2ljJywgcmF3VHgsIHtcbiAgICAgIGlzU2lnbmVkOiB0cnVlLFxuICAgIH0pO1xuICAgIGxldCBzaWduYXR1cmUgPSB1OGFUb0hleChtZXRob2RDYWxsLnNpZ25hdHVyZSkgYXMgc3RyaW5nO1xuXG4gICAgLy8gcmVtb3ZlIDB4IGZyb20gdGhlIHNpZ25hdHVyZSBzaW5jZSB0aGlzIGlzIGhvdyBpdCdzIHJldHVybmVkIGZyb20gVFNTIHNpZ25pbmdcbiAgICBpZiAoc2lnbmF0dXJlLnN0YXJ0c1dpdGgoJzB4JykpIHtcbiAgICAgIHNpZ25hdHVyZSA9IHNpZ25hdHVyZS5zdWJzdHIoMik7XG4gICAgfVxuICAgIHJldHVybiBzaWduYXR1cmU7XG4gIH1cblxuICAvKipcbiAgICogRGVjb2RlcyB0aGUgZG90IGFkZHJlc3MgZnJvbSB0aGUgZ2l2ZW4gZm9ybWF0XG4gICAqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBhZGRyZXNzXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbc3M1OEZvcm1hdF1cbiAgICogQHJldHVybnMge0tleVBhaXJ9XG4gICAqL1xuICBkZWNvZGVTdWJzdHJhdGVBZGRyZXNzVG9LZXlQYWlyKGFkZHJlc3M6IHN0cmluZywgc3M1OEZvcm1hdD86IG51bWJlcik6IEtleVBhaXIge1xuICAgIHJldHVybiBuZXcgS2V5UGFpcih7IHB1YjogQnVmZmVyLmZyb20oZGVjb2RlQWRkcmVzcyhhZGRyZXNzLCB1bmRlZmluZWQsIHNzNThGb3JtYXQpKS50b1N0cmluZygnaGV4JykgfSk7XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2tzIHdoZXRoZXIgdGhlIGdpdmVuIGlucHV0IGlzIGEgaGV4IHN0cmluZyB3aXRoIHdpdGggMCB2YWx1ZVxuICAgKiB1c2VkIHRvIGNoZWNrIHdoZXRoZXIgYSBnaXZlbiB0cmFuc2FjdGlvbiBpcyBpbW1vcnRhbCBvciBtb3J0YWxcbiAgICogQHBhcmFtIGhleFZhbHVlXG4gICAqL1xuICBpc1plcm9IZXgoaGV4VmFsdWU6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIHJldHVybiBoZXhWYWx1ZSA9PT0gJzB4MDAnO1xuICB9XG5cbiAgZ2V0TWF0ZXJpYWwobmV0d29ya1R5cGU6IE5ldHdvcmtUeXBlKTogTWF0ZXJpYWwge1xuICAgIHRocm93IG5ldyBFcnJvcignTWV0aG9kIG5vdCBpbXBsZW1lbnRlZC4nKTtcbiAgfVxufVxuXG5jb25zdCB1dGlscyA9IG5ldyBVdGlscygpO1xuXG5leHBvcnQgZGVmYXVsdCB1dGlscztcbiJdfQ==