@bitgo/sdk-coin-algo 2.5.7 → 2.6.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/dist/src/algo.d.ts +12 -0
- package/dist/src/algo.d.ts.map +1 -1
- package/dist/src/algo.js +77 -1
- package/dist/test/unit/verifyTransaction.d.ts +2 -0
- package/dist/test/unit/verifyTransaction.d.ts.map +1 -0
- package/dist/test/unit/verifyTransaction.js +294 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +6 -6
|
@@ -0,0 +1,294 @@
|
|
|
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
|
+
const src_1 = require("../../src");
|
|
40
|
+
const sdk_test_1 = require("@bitgo/sdk-test");
|
|
41
|
+
const sdk_api_1 = require("@bitgo/sdk-api");
|
|
42
|
+
const testData = __importStar(require("../fixtures/resources"));
|
|
43
|
+
const assert_1 = __importDefault(require("assert"));
|
|
44
|
+
describe('Algorand Verify Transaction:', function () {
|
|
45
|
+
let bitgo;
|
|
46
|
+
let basecoin;
|
|
47
|
+
before(function () {
|
|
48
|
+
bitgo = sdk_test_1.TestBitGo.decorate(sdk_api_1.BitGoAPI, { env: 'mock' });
|
|
49
|
+
bitgo.safeRegister('talgo', src_1.Talgo.createInstance);
|
|
50
|
+
bitgo.initializeTestVars();
|
|
51
|
+
basecoin = bitgo.coin('talgo');
|
|
52
|
+
});
|
|
53
|
+
describe('Parameter Validation', () => {
|
|
54
|
+
it('should throw error when txParams is missing', async function () {
|
|
55
|
+
const txPrebuild = {
|
|
56
|
+
txHex: testData.rawTx.transfer.unsigned,
|
|
57
|
+
};
|
|
58
|
+
await assert_1.default.rejects(basecoin.verifyTransaction({
|
|
59
|
+
txPrebuild,
|
|
60
|
+
wallet: {},
|
|
61
|
+
txParams: undefined,
|
|
62
|
+
}), {
|
|
63
|
+
message: 'missing txParams',
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
it('should throw error when txPrebuild is missing', async function () {
|
|
67
|
+
const txParams = {
|
|
68
|
+
recipients: [{ address: testData.accounts.account2.address, amount: '10000' }],
|
|
69
|
+
};
|
|
70
|
+
await assert_1.default.rejects(basecoin.verifyTransaction({
|
|
71
|
+
txParams,
|
|
72
|
+
wallet: {},
|
|
73
|
+
txPrebuild: undefined,
|
|
74
|
+
}), {
|
|
75
|
+
message: 'missing txPrebuild',
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
it('should throw error when txPrebuild.txHex is missing', async function () {
|
|
79
|
+
const txParams = {
|
|
80
|
+
recipients: [{ address: testData.accounts.account2.address, amount: '10000' }],
|
|
81
|
+
};
|
|
82
|
+
const txPrebuild = {};
|
|
83
|
+
await assert_1.default.rejects(basecoin.verifyTransaction({ txParams, txPrebuild, wallet: {} }), {
|
|
84
|
+
message: 'missing txHex in txPrebuild',
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
describe('Payment Transaction Validation', () => {
|
|
89
|
+
it('should validate valid payment transaction', async function () {
|
|
90
|
+
const txParams = {
|
|
91
|
+
recipients: [
|
|
92
|
+
{
|
|
93
|
+
address: testData.accounts.account2.address,
|
|
94
|
+
amount: '10000',
|
|
95
|
+
},
|
|
96
|
+
],
|
|
97
|
+
};
|
|
98
|
+
const txPrebuild = {
|
|
99
|
+
txHex: testData.rawTx.transfer.unsigned,
|
|
100
|
+
};
|
|
101
|
+
const result = await basecoin.verifyTransaction({ txParams, txPrebuild, wallet: {} });
|
|
102
|
+
assert_1.default.strictEqual(result, true);
|
|
103
|
+
});
|
|
104
|
+
it('should fail with amount mismatch', async function () {
|
|
105
|
+
const txParams = {
|
|
106
|
+
recipients: [
|
|
107
|
+
{
|
|
108
|
+
address: testData.accounts.account2.address,
|
|
109
|
+
amount: '20000', // Different amount than in the transaction
|
|
110
|
+
},
|
|
111
|
+
],
|
|
112
|
+
};
|
|
113
|
+
const txPrebuild = {
|
|
114
|
+
txHex: testData.rawTx.transfer.unsigned,
|
|
115
|
+
};
|
|
116
|
+
await assert_1.default.rejects(basecoin.verifyTransaction({ txParams, txPrebuild, wallet: {} }), {
|
|
117
|
+
message: 'transaction amount in txPrebuild does not match the value given by client',
|
|
118
|
+
});
|
|
119
|
+
});
|
|
120
|
+
it('should fail with address mismatch', async function () {
|
|
121
|
+
const txParams = {
|
|
122
|
+
recipients: [
|
|
123
|
+
{
|
|
124
|
+
address: testData.accounts.account3.address, // Different address than in transaction
|
|
125
|
+
amount: '10000',
|
|
126
|
+
},
|
|
127
|
+
],
|
|
128
|
+
};
|
|
129
|
+
const txPrebuild = {
|
|
130
|
+
txHex: testData.rawTx.transfer.unsigned,
|
|
131
|
+
};
|
|
132
|
+
await assert_1.default.rejects(basecoin.verifyTransaction({ txParams, txPrebuild, wallet: {} }), {
|
|
133
|
+
message: 'destination address does not match with the recipient address',
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
it('should fail with multiple recipients', async function () {
|
|
137
|
+
const txParams = {
|
|
138
|
+
recipients: [
|
|
139
|
+
{
|
|
140
|
+
address: testData.accounts.account2.address,
|
|
141
|
+
amount: '5000',
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
address: testData.accounts.account3.address,
|
|
145
|
+
amount: '5000',
|
|
146
|
+
},
|
|
147
|
+
],
|
|
148
|
+
};
|
|
149
|
+
const txPrebuild = {
|
|
150
|
+
txHex: testData.rawTx.transfer.unsigned,
|
|
151
|
+
};
|
|
152
|
+
await assert_1.default.rejects(basecoin.verifyTransaction({ txParams, txPrebuild, wallet: {} }), {
|
|
153
|
+
message: 'Algorand transactions can only have one recipient',
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
it('should validate transaction without recipients in txParams', async function () {
|
|
157
|
+
const txParams = {
|
|
158
|
+
// No recipients specified
|
|
159
|
+
};
|
|
160
|
+
const txPrebuild = {
|
|
161
|
+
txHex: testData.rawTx.transfer.unsigned,
|
|
162
|
+
};
|
|
163
|
+
const result = await basecoin.verifyTransaction({ txParams, txPrebuild, wallet: {} });
|
|
164
|
+
assert_1.default.strictEqual(result, true);
|
|
165
|
+
});
|
|
166
|
+
});
|
|
167
|
+
describe('Asset Transfer Transaction Validation', () => {
|
|
168
|
+
it('should validate valid asset transfer transaction', async function () {
|
|
169
|
+
const txParams = {
|
|
170
|
+
recipients: [
|
|
171
|
+
{
|
|
172
|
+
address: testData.accounts.account2.address,
|
|
173
|
+
amount: '1000',
|
|
174
|
+
},
|
|
175
|
+
],
|
|
176
|
+
};
|
|
177
|
+
const txPrebuild = {
|
|
178
|
+
txHex: testData.rawTx.assetTransfer.unsigned,
|
|
179
|
+
};
|
|
180
|
+
const result = await basecoin.verifyTransaction({ txParams, txPrebuild, wallet: {} });
|
|
181
|
+
assert_1.default.strictEqual(result, true);
|
|
182
|
+
});
|
|
183
|
+
it('should validate token enable transaction', async function () {
|
|
184
|
+
const txParams = {
|
|
185
|
+
type: 'enabletoken',
|
|
186
|
+
recipients: [
|
|
187
|
+
{
|
|
188
|
+
address: testData.accounts.account1.address,
|
|
189
|
+
amount: '0',
|
|
190
|
+
},
|
|
191
|
+
],
|
|
192
|
+
};
|
|
193
|
+
const txPrebuild = {
|
|
194
|
+
// Using existing asset transfer for test - in real scenario this would be an opt-in transaction
|
|
195
|
+
txHex: testData.rawTx.assetTransfer.unsigned,
|
|
196
|
+
};
|
|
197
|
+
const result = await basecoin.verifyTransaction({ txParams, txPrebuild, wallet: {} });
|
|
198
|
+
assert_1.default.strictEqual(result, true);
|
|
199
|
+
});
|
|
200
|
+
});
|
|
201
|
+
describe('Transaction Structure Validation', () => {
|
|
202
|
+
it('should handle malformed transaction hex gracefully', async function () {
|
|
203
|
+
const txParams = {
|
|
204
|
+
recipients: [{ address: testData.accounts.account2.address, amount: '10000' }],
|
|
205
|
+
};
|
|
206
|
+
const txPrebuild = {
|
|
207
|
+
txHex: 'invalid_hex_data',
|
|
208
|
+
};
|
|
209
|
+
await assert_1.default.rejects(basecoin.verifyTransaction({ txParams, txPrebuild, wallet: {} }));
|
|
210
|
+
});
|
|
211
|
+
it('should validate transaction with memo', async function () {
|
|
212
|
+
const txParams = {
|
|
213
|
+
recipients: [
|
|
214
|
+
{
|
|
215
|
+
address: testData.accounts.account2.address,
|
|
216
|
+
amount: '10000',
|
|
217
|
+
},
|
|
218
|
+
],
|
|
219
|
+
};
|
|
220
|
+
const txPrebuild = {
|
|
221
|
+
txHex: testData.rawTx.transfer.unsigned, // This transaction includes a memo
|
|
222
|
+
};
|
|
223
|
+
const result = await basecoin.verifyTransaction({ txParams, txPrebuild, wallet: {} });
|
|
224
|
+
assert_1.default.strictEqual(result, true);
|
|
225
|
+
});
|
|
226
|
+
});
|
|
227
|
+
describe('Edge Cases', () => {
|
|
228
|
+
it('should handle zero amount transactions', async function () {
|
|
229
|
+
const txParams = {
|
|
230
|
+
recipients: [
|
|
231
|
+
{
|
|
232
|
+
address: testData.accounts.account1.address,
|
|
233
|
+
amount: '0',
|
|
234
|
+
},
|
|
235
|
+
],
|
|
236
|
+
};
|
|
237
|
+
const txPrebuild = {
|
|
238
|
+
// This would need to be a valid 0-amount transaction hex
|
|
239
|
+
txHex: testData.rawTx.transfer.unsigned,
|
|
240
|
+
};
|
|
241
|
+
// Note: This might fail if the test data doesn't match the expected amount
|
|
242
|
+
// In a real scenario, we'd need proper test data for 0-amount transactions
|
|
243
|
+
try {
|
|
244
|
+
const result = await basecoin.verifyTransaction({ txParams, txPrebuild, wallet: {} });
|
|
245
|
+
assert_1.default.strictEqual(result, true);
|
|
246
|
+
}
|
|
247
|
+
catch (error) {
|
|
248
|
+
// Expected if amounts don't match
|
|
249
|
+
assert_1.default.ok(error.message.includes('amount'));
|
|
250
|
+
}
|
|
251
|
+
});
|
|
252
|
+
it('should handle close remainder transactions', async function () {
|
|
253
|
+
const txParams = {
|
|
254
|
+
recipients: [
|
|
255
|
+
{
|
|
256
|
+
address: testData.accounts.account3.address,
|
|
257
|
+
amount: '10000',
|
|
258
|
+
},
|
|
259
|
+
],
|
|
260
|
+
};
|
|
261
|
+
const txPrebuild = {
|
|
262
|
+
txHex: testData.rawTx.transfer.unsigned,
|
|
263
|
+
};
|
|
264
|
+
// This test validates that transactions with closeRemainderTo field are handled
|
|
265
|
+
try {
|
|
266
|
+
const result = await basecoin.verifyTransaction({ txParams, txPrebuild, wallet: {} });
|
|
267
|
+
assert_1.default.strictEqual(result, true);
|
|
268
|
+
}
|
|
269
|
+
catch (error) {
|
|
270
|
+
// Expected if addresses don't match
|
|
271
|
+
assert_1.default.ok(error.message.includes('address'));
|
|
272
|
+
}
|
|
273
|
+
});
|
|
274
|
+
});
|
|
275
|
+
describe('Network Validation', () => {
|
|
276
|
+
it('should validate transactions for different networks', async function () {
|
|
277
|
+
// Test that transactions work regardless of genesis hash/ID
|
|
278
|
+
const txParams = {
|
|
279
|
+
recipients: [
|
|
280
|
+
{
|
|
281
|
+
address: testData.accounts.account2.address,
|
|
282
|
+
amount: '10000',
|
|
283
|
+
},
|
|
284
|
+
],
|
|
285
|
+
};
|
|
286
|
+
const txPrebuild = {
|
|
287
|
+
txHex: testData.rawTx.transfer.unsigned,
|
|
288
|
+
};
|
|
289
|
+
const result = await basecoin.verifyTransaction({ txParams, txPrebuild, wallet: {} });
|
|
290
|
+
assert_1.default.strictEqual(result, true);
|
|
291
|
+
});
|
|
292
|
+
});
|
|
293
|
+
});
|
|
294
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmVyaWZ5VHJhbnNhY3Rpb24uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90ZXN0L3VuaXQvdmVyaWZ5VHJhbnNhY3Rpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSxtQ0FBa0M7QUFDbEMsOENBQTBEO0FBQzFELDRDQUEwQztBQUMxQyxnRUFBa0Q7QUFDbEQsb0RBQTRCO0FBRTVCLFFBQVEsQ0FBQyw4QkFBOEIsRUFBRTtJQUN2QyxJQUFJLEtBQW1CLENBQUM7SUFDeEIsSUFBSSxRQUFlLENBQUM7SUFFcEIsTUFBTSxDQUFDO1FBQ0wsS0FBSyxHQUFHLG9CQUFTLENBQUMsUUFBUSxDQUFDLGtCQUFRLEVBQUUsRUFBRSxHQUFHLEVBQUUsTUFBTSxFQUFFLENBQUMsQ0FBQztRQUN0RCxLQUFLLENBQUMsWUFBWSxDQUFDLE9BQU8sRUFBRSxXQUFLLENBQUMsY0FBYyxDQUFDLENBQUM7UUFDbEQsS0FBSyxDQUFDLGtCQUFrQixFQUFFLENBQUM7UUFDM0IsUUFBUSxHQUFHLEtBQUssQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFVLENBQUM7SUFDMUMsQ0FBQyxDQUFDLENBQUM7SUFFSCxRQUFRLENBQUMsc0JBQXNCLEVBQUUsR0FBRyxFQUFFO1FBQ3BDLEVBQUUsQ0FBQyw2Q0FBNkMsRUFBRSxLQUFLO1lBQ3JELE1BQU0sVUFBVSxHQUFHO2dCQUNqQixLQUFLLEVBQUUsUUFBUSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsUUFBUTthQUN4QyxDQUFDO1lBRUYsTUFBTSxnQkFBTSxDQUFDLE9BQU8sQ0FDbEIsUUFBUSxDQUFDLGlCQUFpQixDQUFDO2dCQUN6QixVQUFVO2dCQUNWLE1BQU0sRUFBRSxFQUFTO2dCQUNqQixRQUFRLEVBQUUsU0FBZ0I7YUFDM0IsQ0FBQyxFQUNGO2dCQUNFLE9BQU8sRUFBRSxrQkFBa0I7YUFDNUIsQ0FDRixDQUFDO1FBQ0osQ0FB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USxDQUFDLFFBQVE7YUFDeEMsQ0FBQztZQUVGLE1BQU0sTUFBTSxHQUFHLE1BQU0sUUFBUSxDQUFDLGlCQUFpQixDQUFDLEVBQUUsUUFBUSxFQUFFLFVBQVUsRUFBRSxNQUFNLEVBQUUsRUFBUyxFQUFFLENBQUMsQ0FBQztZQUM3RixnQkFBTSxDQUFDLFdBQVcsQ0FBQyxNQUFNLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFDbkMsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztBQUNMLENBQUMsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgVGFsZ28gfSBmcm9tICcuLi8uLi9zcmMnO1xuaW1wb3J0IHsgVGVzdEJpdEdvLCBUZXN0Qml0R29BUEkgfSBmcm9tICdAYml0Z28vc2RrLXRlc3QnO1xuaW1wb3J0IHsgQml0R29BUEkgfSBmcm9tICdAYml0Z28vc2RrLWFwaSc7XG5pbXBvcnQgKiBhcyB0ZXN0RGF0YSBmcm9tICcuLi9maXh0dXJlcy9yZXNvdXJjZXMnO1xuaW1wb3J0IGFzc2VydCBmcm9tICdhc3NlcnQnO1xuXG5kZXNjcmliZSgnQWxnb3JhbmQgVmVyaWZ5IFRyYW5zYWN0aW9uOicsIGZ1bmN0aW9uICgpIHtcbiAgbGV0IGJpdGdvOiBUZXN0Qml0R29BUEk7XG4gIGxldCBiYXNlY29pbjogVGFsZ287XG5cbiAgYmVmb3JlKGZ1bmN0aW9uICgpIHtcbiAgICBiaXRnbyA9IFRlc3RCaXRHby5kZWNvcmF0ZShCaXRHb0FQSSwgeyBlbnY6ICdtb2NrJyB9KTtcbiAgICBiaXRnby5zYWZlUmVnaXN0ZXIoJ3RhbGdvJywgVGFsZ28uY3JlYXRlSW5zdGFuY2UpO1xuICAgIGJpdGdvLmluaXRpYWxpemVUZXN0VmFycygpO1xuICAgIGJhc2Vjb2luID0gYml0Z28uY29pbigndGFsZ28nKSBhcyBUYWxnbztcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ1BhcmFtZXRlciBWYWxpZGF0aW9uJywgKCkgPT4ge1xuICAgIGl0KCdzaG91bGQgdGhyb3cgZXJyb3Igd2hlbiB0eFBhcmFtcyBpcyBtaXNzaW5nJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgdHhQcmVidWlsZCA9IHtcbiAgICAgICAgdHhIZXg6IHRlc3REYXRhLnJhd1R4LnRyYW5zZmVyLnVuc2lnbmVkLFxuICAgICAgfTtcblxuICAgICAgYXdhaXQgYXNzZXJ0LnJlamVjdHMoXG4gICAgICAgIGJhc2Vjb2luLnZlcmlmeVRyYW5zYWN0aW9uKHtcbiAgICAgICAgICB0eFByZWJ1aWxkLFxuICAgICAgICAgIHdhbGxldDoge30gYXMgYW55LFxuICAgICAgICAgIHR4UGFyYW1zOiB1bmRlZmluZWQgYXMgYW55LFxuICAgICAgICB9KSxcbiAgICAgICAge1xuICAgICAgICAgIG1lc3NhZ2U6ICdtaXNzaW5nIHR4UGFyYW1zJyxcbiAgICAgICAgfVxuICAgICAgKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdGhyb3cgZXJyb3Igd2hlbiB0eFByZWJ1aWxkIGlzIG1pc3NpbmcnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB0eFBhcmFtcyA9IHtcbiAgICAgICAgcmVjaXBpZW50czogW3sgYWRkcmVzczogdGVzdERhdGEuYWNjb3VudHMuYWNjb3VudDIuYWRkcmVzcywgYW1vdW50OiAnMTAwMDAnIH1dLFxuICAgICAgfTtcblxuICAgICAgYXdhaXQgYXNzZXJ0LnJlamVjdHMoXG4gICAgICAgIGJhc2Vjb2luLnZlcmlmeVRyYW5zYWN0aW9uKHtcbiAgICAgICAgICB0eFBhcmFtcyxcbiAgICAgICAgICB3YWxsZXQ6IHt9IGFzIGFueSxcbiAgICAgICAgICB0eFByZWJ1aWxkOiB1bmRlZmluZWQgYXMgYW55LFxuICAgICAgICB9KSxcbiAgICAgICAge1xuICAgICAgICAgIG1lc3NhZ2U6ICdtaXNzaW5nIHR4UHJlYnVpbGQnLFxuICAgICAgICB9XG4gICAgICApO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0aHJvdyBlcnJvciB3aGVuIHR4UHJlYnVpbGQudHhIZXggaXMgbWlzc2luZycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHR4UGFyYW1zID0ge1xuICAgICAgICByZWNpcGllbnRzOiBbeyBhZGRyZXNzOiB0ZXN0RGF0YS5hY2NvdW50cy5hY2NvdW50Mi5hZGRyZXNzLCBhbW91bnQ6ICcxMDAwMCcgfV0sXG4gICAgICB9O1xuICAgICAgY29uc3QgdHhQcmVidWlsZCA9IHt9O1xuXG4gICAgICBhd2FpdCBhc3NlcnQucmVqZWN0cyhiYXNlY29pbi52ZXJpZnlUcmFuc2FjdGlvbih7IHR4UGFyYW1zLCB0eFByZWJ1aWxkLCB3YWxsZXQ6IHt9IGFzIGFueSB9KSwge1xuICAgICAgICBtZXNzYWdlOiAnbWlzc2luZyB0eEhleCBpbiB0eFByZWJ1aWxkJyxcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnUGF5bWVudCBUcmFuc2FjdGlvbiBWYWxpZGF0aW9uJywgKCkgPT4ge1xuICAgIGl0KCdzaG91bGQgdmFsaWRhdGUgdmFsaWQgcGF5bWVudCB0cmFuc2FjdGlvbicsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHR4UGFyYW1zID0ge1xuICAgICAgICByZWNpcGllbnRzOiBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgYWRkcmVzczogdGVzdERhdGEuYWNjb3VudHMuYWNjb3VudDIuYWRkcmVzcyxcbiAgICAgICAgICAgIGFtb3VudDogJzEwMDAwJyxcbiAgICAgICAgICB9LFxuICAgICAgICBdLFxuICAgICAgfTtcbiAgICAgIGNvbnN0IHR4UHJlYnVpbGQgPSB7XG4gICAgICAgIHR4SGV4OiB0ZXN0RGF0YS5yYXdUeC50cmFuc2Zlci51bnNpZ25lZCxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGJhc2Vjb2luLnZlcmlmeVRyYW5zYWN0aW9uKHsgdHhQYXJhbXMsIHR4UHJlYnVpbGQsIHdhbGxldDoge30gYXMgYW55IH0pO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHJlc3VsdCwgdHJ1ZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGZhaWwgd2l0aCBhbW91bnQgbWlzbWF0Y2gnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB0eFBhcmFtcyA9IHtcbiAgICAgICAgcmVjaXBpZW50czogW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIGFkZHJlc3M6IHRlc3REYXRhLmFjY291bnRzLmFjY291bnQyLmFkZHJlc3MsXG4gICAgICAgICAgICBhbW91bnQ6ICcyMDAwMCcsIC8vIERpZmZlcmVudCBhbW91bnQgdGhhbiBpbiB0aGUgdHJhbnNhY3Rpb25cbiAgICAgICAgICB9LFxuICAgICAgICBdLFxuICAgICAgfTtcbiAgICAgIGNvbnN0IHR4UHJlYnVpbGQgPSB7XG4gICAgICAgIHR4SGV4OiB0ZXN0RGF0YS5yYXdUeC50cmFuc2Zlci51bnNpZ25lZCxcbiAgICAgIH07XG5cbiAgICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKGJhc2Vjb2luLnZlcmlmeVRyYW5zYWN0aW9uKHsgdHhQYXJhbXMsIHR4UHJlYnVpbGQsIHdhbGxldDoge30gYXMgYW55IH0pLCB7XG4gICAgICAgIG1lc3NhZ2U6ICd0cmFuc2FjdGlvbiBhbW91bnQgaW4gdHhQcmVidWlsZCBkb2VzIG5vdCBtYXRjaCB0aGUgdmFsdWUgZ2l2ZW4gYnkgY2xpZW50JyxcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBmYWlsIHdpdGggYWRkcmVzcyBtaXNtYXRjaCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHR4UGFyYW1zID0ge1xuICAgICAgICByZWNpcGllbnRzOiBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgYWRkcmVzczogdGVzdERhdGEuYWNjb3VudHMuYWNjb3VudDMuYWRkcmVzcywgLy8gRGlmZmVyZW50IGFkZHJlc3MgdGhhbiBpbiB0cmFuc2FjdGlvblxuICAgICAgICAgICAgYW1vdW50OiAnMTAwMDAnLFxuICAgICAgICAgIH0sXG4gICAgICAgIF0sXG4gICAgICB9O1xuICAgICAgY29uc3QgdHhQcmVidWlsZCA9IHtcbiAgICAgICAgdHhIZXg6IHRlc3REYXRhLnJhd1R4LnRyYW5zZmVyLnVuc2lnbmVkLFxuICAgICAgfTtcblxuICAgICAgYXdhaXQgYXNzZXJ0LnJlamVjdHMoYmFzZWNvaW4udmVyaWZ5VHJhbnNhY3Rpb24oeyB0eFBhcmFtcywgdHhQcmVidWlsZCwgd2FsbGV0OiB7fSBhcyBhbnkgfSksIHtcbiAgICAgICAgbWVzc2FnZTogJ2Rlc3RpbmF0aW9uIGFkZHJlc3MgZG9lcyBub3QgbWF0Y2ggd2l0aCB0aGUgcmVjaXBpZW50IGFkZHJlc3MnLFxuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGZhaWwgd2l0aCBtdWx0aXBsZSByZWNpcGllbnRzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgdHhQYXJhbXMgPSB7XG4gICAgICAgIHJlY2lwaWVudHM6IFtcbiAgICAgICAgICB7XG4gICAgICAgICAgICBhZGRyZXNzOiB0ZXN0RGF0YS5hY2NvdW50cy5hY2NvdW50Mi5hZGRyZXNzLFxuICAgICAgICAgICAgYW1vdW50OiAnNTAwMCcsXG4gICAgICAgICAgfSxcbiAgICAgICAgICB7XG4gICAgICAgICAgICBhZGRyZXNzOiB0ZXN0RGF0YS5hY2NvdW50cy5hY2NvdW50My5hZGRyZXNzLFxuICAgICAgICAgICAgYW1vdW50OiAnNTAwMCcsXG4gICAgICAgICAgfSxcbiAgICAgICAgXSxcbiAgICAgIH07XG4gICAgICBjb25zdCB0eFByZWJ1aWxkID0ge1xuICAgICAgICB0eEhleDogdGVzdERhdGEucmF3VHgudHJhbnNmZXIudW5zaWduZWQsXG4gICAgICB9O1xuXG4gICAgICBhd2FpdCBhc3NlcnQucmVqZWN0cyhiYXNlY29pbi52ZXJpZnlUcmFuc2FjdGlvbih7IHR4UGFyYW1zLCB0eFByZWJ1aWxkLCB3YWxsZXQ6IHt9IGFzIGFueSB9KSwge1xuICAgICAgICBtZXNzYWdlOiAnQWxnb3JhbmQgdHJhbnNhY3Rpb25zIGNhbiBvbmx5IGhhdmUgb25lIHJlY2lwaWVudCcsXG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdmFsaWRhdGUgdHJhbnNhY3Rpb24gd2l0aG91dCByZWNpcGllbnRzIGluIHR4UGFyYW1zJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgdHhQYXJhbXMgPSB7XG4gICAgICAgIC8vIE5vIHJlY2lwaWVudHMgc3BlY2lmaWVkXG4gICAgICB9O1xuICAgICAgY29uc3QgdHhQcmVidWlsZCA9IHtcbiAgICAgICAgdHhIZXg6IHRlc3REYXRhLnJhd1R4LnRyYW5zZmVyLnVuc2lnbmVkLFxuICAgICAgfTtcblxuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgYmFzZWNvaW4udmVyaWZ5VHJhbnNhY3Rpb24oeyB0eFBhcmFtcywgdHhQcmVidWlsZCwgd2FsbGV0OiB7fSBhcyBhbnkgfSk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwocmVzdWx0LCB0cnVlKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ0Fzc2V0IFRyYW5zZmVyIFRyYW5zYWN0aW9uIFZhbGlkYXRpb24nLCAoKSA9PiB7XG4gICAgaXQoJ3Nob3VsZCB2YWxpZGF0ZSB2YWxpZCBhc3NldCB0cmFuc2ZlciB0cmFuc2FjdGlvbicsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHR4UGFyYW1zID0ge1xuICAgICAgICByZWNpcGllbnRzOiBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgYWRkcmVzczogdGVzdERhdGEuYWNjb3VudHMuYWNjb3VudDIuYWRkcmVzcyxcbiAgICAgICAgICAgIGFtb3VudDogJzEwMDAnLFxuICAgICAgICAgIH0sXG4gICAgICAgIF0sXG4gICAgICB9O1xuICAgICAgY29uc3QgdHhQcmVidWlsZCA9IHtcbiAgICAgICAgdHhIZXg6IHRlc3REYXRhLnJhd1R4LmFzc2V0VHJhbnNmZXIudW5zaWduZWQsXG4gICAgICB9O1xuXG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBiYXNlY29pbi52ZXJpZnlUcmFuc2FjdGlvbih7IHR4UGFyYW1zLCB0eFByZWJ1aWxkLCB3YWxsZXQ6IHt9IGFzIGFueSB9KTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChyZXN1bHQsIHRydWUpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB2YWxpZGF0ZSB0b2tlbiBlbmFibGUgdHJhbnNhY3Rpb24nLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB0eFBhcmFtcyA9IHtcbiAgICAgICAgdHlwZTogJ2VuYWJsZXRva2VuJyxcbiAgICAgICAgcmVjaXBpZW50czogW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIGFkZHJlc3M6IHRlc3REYXRhLmFjY291bnRzLmFjY291bnQxLmFkZHJlc3MsXG4gICAgICAgICAgICBhbW91bnQ6ICcwJyxcbiAgICAgICAgICB9LFxuICAgICAgICBdLFxuICAgICAgfTtcbiAgICAgIGNvbnN0IHR4UHJlYnVpbGQgPSB7XG4gICAgICAgIC8vIFVzaW5nIGV4aXN0aW5nIGFzc2V0IHRyYW5zZmVyIGZvciB0ZXN0IC0gaW4gcmVhbCBzY2VuYXJpbyB0aGlzIHdvdWxkIGJlIGFuIG9wdC1pbiB0cmFuc2FjdGlvblxuICAgICAgICB0eEhleDogdGVzdERhdGEucmF3VHguYXNzZXRUcmFuc2Zlci51bnNpZ25lZCxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGJhc2Vjb2luLnZlcmlmeVRyYW5zYWN0aW9uKHsgdHhQYXJhbXMsIHR4UHJlYnVpbGQsIHdhbGxldDoge30gYXMgYW55IH0pO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHJlc3VsdCwgdHJ1ZSk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdUcmFuc2FjdGlvbiBTdHJ1Y3R1cmUgVmFsaWRhdGlvbicsICgpID0+IHtcbiAgICBpdCgnc2hvdWxkIGhhbmRsZSBtYWxmb3JtZWQgdHJhbnNhY3Rpb24gaGV4IGdyYWNlZnVsbHknLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB0eFBhcmFtcyA9IHtcbiAgICAgICAgcmVjaXBpZW50czogW3sgYWRkcmVzczogdGVzdERhdGEuYWNjb3VudHMuYWNjb3VudDIuYWRkcmVzcywgYW1vdW50OiAnMTAwMDAnIH1dLFxuICAgICAgfTtcbiAgICAgIGNvbnN0IHR4UHJlYnVpbGQgPSB7XG4gICAgICAgIHR4SGV4OiAnaW52YWxpZF9oZXhfZGF0YScsXG4gICAgICB9O1xuXG4gICAgICBhd2FpdCBhc3NlcnQucmVqZWN0cyhiYXNlY29pbi52ZXJpZnlUcmFuc2FjdGlvbih7IHR4UGFyYW1zLCB0eFByZWJ1aWxkLCB3YWxsZXQ6IHt9IGFzIGFueSB9KSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHZhbGlkYXRlIHRyYW5zYWN0aW9uIHdpdGggbWVtbycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHR4UGFyYW1zID0ge1xuICAgICAgICByZWNpcGllbnRzOiBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgYWRkcmVzczogdGVzdERhdGEuYWNjb3VudHMuYWNjb3VudDIuYWRkcmVzcyxcbiAgICAgICAgICAgIGFtb3VudDogJzEwMDAwJyxcbiAgICAgICAgICB9LFxuICAgICAgICBdLFxuICAgICAgfTtcbiAgICAgIGNvbnN0IHR4UHJlYnVpbGQgPSB7XG4gICAgICAgIHR4SGV4OiB0ZXN0RGF0YS5yYXdUeC50cmFuc2Zlci51bnNpZ25lZCwgLy8gVGhpcyB0cmFuc2FjdGlvbiBpbmNsdWRlcyBhIG1lbW9cbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGJhc2Vjb2luLnZlcmlmeVRyYW5zYWN0aW9uKHsgdHhQYXJhbXMsIHR4UHJlYnVpbGQsIHdhbGxldDoge30gYXMgYW55IH0pO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHJlc3VsdCwgdHJ1ZSk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdFZGdlIENhc2VzJywgKCkgPT4ge1xuICAgIGl0KCdzaG91bGQgaGFuZGxlIHplcm8gYW1vdW50IHRyYW5zYWN0aW9ucycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHR4UGFyYW1zID0ge1xuICAgICAgICByZWNpcGllbnRzOiBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgYWRkcmVzczogdGVzdERhdGEuYWNjb3VudHMuYWNjb3VudDEuYWRkcmVzcyxcbiAgICAgICAgICAgIGFtb3VudDogJzAnLFxuICAgICAgICAgIH0sXG4gICAgICAgIF0sXG4gICAgICB9O1xuICAgICAgY29uc3QgdHhQcmVidWlsZCA9IHtcbiAgICAgICAgLy8gVGhpcyB3b3VsZCBuZWVkIHRvIGJlIGEgdmFsaWQgMC1hbW91bnQgdHJhbnNhY3Rpb24gaGV4XG4gICAgICAgIHR4SGV4OiB0ZXN0RGF0YS5yYXdUeC50cmFuc2Zlci51bnNpZ25lZCxcbiAgICAgIH07XG5cbiAgICAgIC8vIE5vdGU6IFRoaXMgbWlnaHQgZmFpbCBpZiB0aGUgdGVzdCBkYXRhIGRvZXNuJ3QgbWF0Y2ggdGhlIGV4cGVjdGVkIGFtb3VudFxuICAgICAgLy8gSW4gYSByZWFsIHNjZW5hcmlvLCB3ZSdkIG5lZWQgcHJvcGVyIHRlc3QgZGF0YSBmb3IgMC1hbW91bnQgdHJhbnNhY3Rpb25zXG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBiYXNlY29pbi52ZXJpZnlUcmFuc2FjdGlvbih7IHR4UGFyYW1zLCB0eFByZWJ1aWxkLCB3YWxsZXQ6IHt9IGFzIGFueSB9KTtcbiAgICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHJlc3VsdCwgdHJ1ZSk7XG4gICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAvLyBFeHBlY3RlZCBpZiBhbW91bnRzIGRvbid0IG1hdGNoXG4gICAgICAgIGFzc2VydC5vayhlcnJvci5tZXNzYWdlLmluY2x1ZGVzKCdhbW91bnQnKSk7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGhhbmRsZSBjbG9zZSByZW1haW5kZXIgdHJhbnNhY3Rpb25zJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgdHhQYXJhbXMgPSB7XG4gICAgICAgIHJlY2lwaWVudHM6IFtcbiAgICAgICAgICB7XG4gICAgICAgICAgICBhZGRyZXNzOiB0ZXN0RGF0YS5hY2NvdW50cy5hY2NvdW50My5hZGRyZXNzLFxuICAgICAgICAgICAgYW1vdW50OiAnMTAwMDAnLFxuICAgICAgICAgIH0sXG4gICAgICAgIF0sXG4gICAgICB9O1xuICAgICAgY29uc3QgdHhQcmVidWlsZCA9IHtcbiAgICAgICAgdHhIZXg6IHRlc3REYXRhLnJhd1R4LnRyYW5zZmVyLnVuc2lnbmVkLFxuICAgICAgfTtcblxuICAgICAgLy8gVGhpcyB0ZXN0IHZhbGlkYXRlcyB0aGF0IHRyYW5zYWN0aW9ucyB3aXRoIGNsb3NlUmVtYWluZGVyVG8gZmllbGQgYXJlIGhhbmRsZWRcbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGJhc2Vjb2luLnZlcmlmeVRyYW5zYWN0aW9uKHsgdHhQYXJhbXMsIHR4UHJlYnVpbGQsIHdhbGxldDoge30gYXMgYW55IH0pO1xuICAgICAgICBhc3NlcnQuc3RyaWN0RXF1YWwocmVzdWx0LCB0cnVlKTtcbiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgIC8vIEV4cGVjdGVkIGlmIGFkZHJlc3NlcyBkb24ndCBtYXRjaFxuICAgICAgICBhc3NlcnQub2soZXJyb3IubWVzc2FnZS5pbmNsdWRlcygnYWRkcmVzcycpKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ05ldHdvcmsgVmFsaWRhdGlvbicsICgpID0+IHtcbiAgICBpdCgnc2hvdWxkIHZhbGlkYXRlIHRyYW5zYWN0aW9ucyBmb3IgZGlmZmVyZW50IG5ldHdvcmtzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgLy8gVGVzdCB0aGF0IHRyYW5zYWN0aW9ucyB3b3JrIHJlZ2FyZGxlc3Mgb2YgZ2VuZXNpcyBoYXNoL0lEXG4gICAgICBjb25zdCB0eFBhcmFtcyA9IHtcbiAgICAgICAgcmVjaXBpZW50czogW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIGFkZHJlc3M6IHRlc3REYXRhLmFjY291bnRzLmFjY291bnQyLmFkZHJlc3MsXG4gICAgICAgICAgICBhbW91bnQ6ICcxMDAwMCcsXG4gICAgICAgICAgfSxcbiAgICAgICAgXSxcbiAgICAgIH07XG4gICAgICBjb25zdCB0eFByZWJ1aWxkID0ge1xuICAgICAgICB0eEhleDogdGVzdERhdGEucmF3VHgudHJhbnNmZXIudW5zaWduZWQsXG4gICAgICB9O1xuXG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBiYXNlY29pbi52ZXJpZnlUcmFuc2FjdGlvbih7IHR4UGFyYW1zLCB0eFByZWJ1aWxkLCB3YWxsZXQ6IHt9IGFzIGFueSB9KTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChyZXN1bHQsIHRydWUpO1xuICAgIH0pO1xuICB9KTtcbn0pO1xuIl19
|