@bitgo/sdk-api 1.75.4 → 1.76.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.
@@ -0,0 +1,136 @@
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
+ require("should");
7
+ const nock_1 = __importDefault(require("nock"));
8
+ const bitgoAPI_1 = require("../../src/bitgoAPI");
9
+ const node_assert_1 = __importDefault(require("node:assert"));
10
+ const TEST_TOKEN = 'v2x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdefab';
11
+ const TEST_URI = 'https://app.example.local';
12
+ /**
13
+ * Mock strategy that records calls and returns predictable values.
14
+ */
15
+ class MockHmacAuthStrategy {
16
+ constructor() {
17
+ this.calculateRequestHeadersCalls = [];
18
+ this.verifyResponseCalls = [];
19
+ this.calculateHMACCalls = [];
20
+ }
21
+ async calculateRequestHeaders(params) {
22
+ this.calculateRequestHeadersCalls.push(params);
23
+ return {
24
+ hmac: 'mock-hmac-value',
25
+ timestamp: 1672531200000,
26
+ tokenHash: 'mock-token-hash',
27
+ };
28
+ }
29
+ async verifyResponse(params) {
30
+ this.verifyResponseCalls.push(params);
31
+ return {
32
+ isValid: true,
33
+ expectedHmac: 'mock-hmac-value',
34
+ signatureSubject: 'mock-subject',
35
+ isInResponseValidityWindow: true,
36
+ verificationTime: Date.now(),
37
+ };
38
+ }
39
+ async calculateHMAC(key, message) {
40
+ this.calculateHMACCalls.push({ key, message });
41
+ return 'mock-hmac-password';
42
+ }
43
+ }
44
+ describe('BitGoAPI HMAC Strategy Injection', function () {
45
+ afterEach(function () {
46
+ nock_1.default.cleanAll();
47
+ });
48
+ describe('constructor', function () {
49
+ it('should accept a custom hmacAuthStrategy', function () {
50
+ const strategy = new MockHmacAuthStrategy();
51
+ const bitgo = new bitgoAPI_1.BitGoAPI({
52
+ env: 'custom',
53
+ customRootURI: TEST_URI,
54
+ hmacAuthStrategy: strategy,
55
+ });
56
+ bitgo.should.be.ok();
57
+ });
58
+ it('should default to DefaultHmacAuthStrategy when none is provided', function () {
59
+ const bitgo = new bitgoAPI_1.BitGoAPI({
60
+ env: 'custom',
61
+ customRootURI: TEST_URI,
62
+ });
63
+ bitgo.should.be.ok();
64
+ });
65
+ });
66
+ describe('request signing via strategy', function () {
67
+ it('should use the custom strategy for HMAC header calculation', async function () {
68
+ const strategy = new MockHmacAuthStrategy();
69
+ const bitgo = new bitgoAPI_1.BitGoAPI({
70
+ env: 'custom',
71
+ customRootURI: TEST_URI,
72
+ accessToken: TEST_TOKEN,
73
+ hmacAuthStrategy: strategy,
74
+ });
75
+ const scope = (0, nock_1.default)(TEST_URI)
76
+ .get('/api/v2/wallet')
77
+ .matchHeader('HMAC', 'mock-hmac-value')
78
+ .matchHeader('Authorization', 'Bearer mock-token-hash')
79
+ .matchHeader('Auth-Timestamp', '1672531200000')
80
+ .reply(200, { wallets: [] }, {
81
+ hmac: 'response-hmac',
82
+ timestamp: Date.now().toString(),
83
+ });
84
+ await bitgo.get(bitgo.url('/wallet', 2)).result();
85
+ strategy.calculateRequestHeadersCalls.length.should.equal(1);
86
+ const call = strategy.calculateRequestHeadersCalls[0];
87
+ call.token.should.equal(TEST_TOKEN);
88
+ call.method.should.equal('get');
89
+ scope.isDone().should.be.true();
90
+ });
91
+ it('should use the custom strategy for response verification', async function () {
92
+ const strategy = new MockHmacAuthStrategy();
93
+ const bitgo = new bitgoAPI_1.BitGoAPI({
94
+ env: 'custom',
95
+ customRootURI: TEST_URI,
96
+ accessToken: TEST_TOKEN,
97
+ hmacAuthStrategy: strategy,
98
+ });
99
+ (0, nock_1.default)(TEST_URI).get('/api/v2/wallet').reply(200, { wallets: [] }, {
100
+ hmac: 'server-response-hmac',
101
+ timestamp: Date.now().toString(),
102
+ });
103
+ await bitgo.get(bitgo.url('/wallet', 2)).result();
104
+ strategy.verifyResponseCalls.length.should.equal(1);
105
+ const call = strategy.verifyResponseCalls[0];
106
+ call.hmac.should.equal('server-response-hmac');
107
+ (0, node_assert_1.default)(call.statusCode, 'statusCode is required');
108
+ call.statusCode.should.equal(200);
109
+ });
110
+ });
111
+ describe('password HMAC via strategy', function () {
112
+ it('should use the custom strategy for password hashing in preprocessAuthenticationParams', async function () {
113
+ const strategy = new MockHmacAuthStrategy();
114
+ const bitgo = new bitgoAPI_1.BitGoAPI({
115
+ env: 'custom',
116
+ customRootURI: TEST_URI,
117
+ hmacAuthStrategy: strategy,
118
+ });
119
+ (0, nock_1.default)(TEST_URI)
120
+ .post('/api/auth/v1/session')
121
+ .reply(200, { access_token: TEST_TOKEN, user: { username: 'test@test.com' } }, {
122
+ hmac: 'resp-hmac',
123
+ timestamp: Date.now().toString(),
124
+ });
125
+ await bitgo.authenticate({
126
+ username: 'test@test.com',
127
+ password: 'mypassword',
128
+ });
129
+ strategy.calculateHMACCalls.length.should.be.greaterThan(0);
130
+ const hmacCall = strategy.calculateHMACCalls[0];
131
+ hmacCall.key.should.equal('test@test.com');
132
+ hmacCall.message.should.equal('mypassword');
133
+ });
134
+ });
135
+ });
136
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaG1hY1N0cmF0ZWd5LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vdGVzdC91bml0L2htYWNTdHJhdGVneS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLGtCQUFnQjtBQUNoQixnREFBd0I7QUFDeEIsaURBQThDO0FBUTlDLDhEQUFpQztBQUVqQyxNQUFNLFVBQVUsR0FBRyx1RUFBdUUsQ0FBQztBQUMzRixNQUFNLFFBQVEsR0FBRywyQkFBMkIsQ0FBQztBQUU3Qzs7R0FFRztBQUNILE1BQU0sb0JBQW9CO0lBQTFCO1FBQ1MsaUNBQTRCLEdBQXFDLEVBQUUsQ0FBQztRQUNwRSx3QkFBbUIsR0FBNEIsRUFBRSxDQUFDO1FBQ2xELHVCQUFrQixHQUE0QyxFQUFFLENBQUM7SUEwQjFFLENBQUM7SUF4QkMsS0FBSyxDQUFDLHVCQUF1QixDQUFDLE1BQXNDO1FBQ2xFLElBQUksQ0FBQyw0QkFBNEIsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDL0MsT0FBTztZQUNMLElBQUksRUFBRSxpQkFBaUI7WUFDdkIsU0FBUyxFQUFFLGFBQWE7WUFDeEIsU0FBUyxFQUFFLGlCQUFpQjtTQUM3QixDQUFDO0lBQ0osQ0FBQztJQUVELEtBQUssQ0FBQyxjQUFjLENBQUMsTUFBNkI7UUFDaEQsSUFBSSxDQUFDLG1CQUFtQixDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUN0QyxPQUFPO1lBQ0wsT0FBTyxFQUFFLElBQUk7WUFDYixZQUFZLEVBQUUsaUJBQWlCO1lBQy9CLGdCQUFnQixFQUFFLGNBQWM7WUFDaEMsMEJBQTBCLEVBQUUsSUFBSTtZQUNoQyxnQkFBZ0IsRUFBRSxJQUFJLENBQUMsR0FBRyxFQUFFO1NBQzdCLENBQUM7SUFDSixDQUFDO0lBRUQsS0FBSyxDQUFDLGFBQWEsQ0FBQyxHQUFXLEVBQUUsT0FBZTtRQUM5QyxJQUFJLENBQUMsa0JBQWtCLENBQUMsSUFBSSxDQUFDLEVBQUUsR0FBRyxFQUFF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UUFBUTtnQkFDYixhQUFhLEVBQUUsUUFBUTtnQkFDdkIsZ0JBQWdCLEVBQUUsUUFBUTthQUMzQixDQUFDLENBQUM7WUFFSCxJQUFBLGNBQUksRUFBQyxRQUFRLENBQUM7aUJBQ1gsSUFBSSxDQUFDLHNCQUFzQixDQUFDO2lCQUM1QixLQUFLLENBQ0osR0FBRyxFQUNILEVBQUUsWUFBWSxFQUFFLFVBQVUsRUFBRSxJQUFJLEVBQUUsRUFBRSxRQUFRLEVBQUUsZUFBZSxFQUFFLEVBQUUsRUFDakU7Z0JBQ0UsSUFBSSxFQUFFLFdBQVc7Z0JBQ2pCLFNBQVMsRUFBRSxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUMsUUFBUSxFQUFFO2FBQ2pDLENBQ0YsQ0FBQztZQUVKLE1BQU0sS0FBSyxDQUFDLFlBQVksQ0FBQztnQkFDdkIsUUFBUSxFQUFFLGVBQWU7Z0JBQ3pCLFFBQVEsRUFBRSxZQUFZO2FBQ3ZCLENBQUMsQ0FBQztZQUVILFFBQVEsQ0FBQyxrQkFBa0IsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDNUQsTUFBTSxRQUFRLEdBQUcsUUFBUSxDQUFDLGtCQUFrQixDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ2hELFFBQVEsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxlQUFlLENBQUMsQ0FBQztZQUMzQyxRQUFRLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDOUMsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztBQUNMLENBQUMsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICdzaG91bGQnO1xuaW1wb3J0IG5vY2sgZnJvbSAnbm9jayc7XG5pbXBvcnQgeyBCaXRHb0FQSSB9IGZyb20gJy4uLy4uL3NyYy9iaXRnb0FQSSc7XG5pbXBvcnQgdHlwZSB7XG4gIElIbWFjQXV0aFN0cmF0ZWd5LFxuICBDYWxjdWxhdGVSZXF1ZXN0SGVhZGVyc09wdGlvbnMsXG4gIFJlcXVlc3RIZWFkZXJzLFxuICBWZXJpZnlSZXNwb25zZU9wdGlvbnMsXG4gIFZlcmlmeVJlc3BvbnNlSW5mbyxcbn0gZnJvbSAnQGJpdGdvL3Nkay1obWFjJztcbmltcG9ydCBhc3NlcnQgZnJvbSAnbm9kZTphc3NlcnQnO1xuXG5jb25zdCBURVNUX1RPS0VOID0gJ3YyeDEyMzQ1Njc4OTBhYmNkZWYxMjM0NTY3ODkwYWJjZGVmMTIzNDU2Nzg5MGFiY2RlZjEyMzQ1Njc4OTBhYmNkZWZhYic7XG5jb25zdCBURVNUX1VSSSA9ICdodHRwczovL2FwcC5leGFtcGxlLmxvY2FsJztcblxuLyoqXG4gKiBNb2NrIHN0cmF0ZWd5IHRoYXQgcmVjb3JkcyBjYWxscyBhbmQgcmV0dXJucyBwcmVkaWN0YWJsZSB2YWx1ZXMuXG4gKi9cbmNsYXNzIE1vY2tIbWFjQXV0aFN0cmF0ZWd5IGltcGxlbWVudHMgSUhtYWNBdXRoU3RyYXRlZ3kge1xuICBwdWJsaWMgY2FsY3VsYXRlUmVxdWVzdEhlYWRlcnNDYWxsczogQ2FsY3VsYXRlUmVxdWVzdEhlYWRlcnNPcHRpb25zW10gPSBbXTtcbiAgcHVibGljIHZlcmlmeVJlc3BvbnNlQ2FsbHM6IFZlcmlmeVJlc3BvbnNlT3B0aW9uc1tdID0gW107XG4gIHB1YmxpYyBjYWxjdWxhdGVITUFDQ2FsbHM6IEFycmF5PHsga2V5OiBzdHJpbmc7IG1lc3NhZ2U6IHN0cmluZyB9PiA9IFtdO1xuXG4gIGFzeW5jIGNhbGN1bGF0ZVJlcXVlc3RIZWFkZXJzKHBhcmFtczogQ2FsY3VsYXRlUmVxdWVzdEhlYWRlcnNPcHRpb25zKTogUHJvbWlzZTxSZXF1ZXN0SGVhZGVycz4ge1xuICAgIHRoaXMuY2FsY3VsYXRlUmVxdWVzdEhlYWRlcnNDYWxscy5wdXNoKHBhcmFtcyk7XG4gICAgcmV0dXJuIHtcbiAgICAgIGhtYWM6ICdtb2NrLWhtYWMtdmFsdWUnLFxuICAgICAgdGltZXN0YW1wOiAxNjcyNTMxMjAwMDAwLFxuICAgICAgdG9rZW5IYXNoOiAnbW9jay10b2tlbi1oYXNoJyxcbiAgICB9O1xuICB9XG5cbiAgYXN5bmMgdmVyaWZ5UmVzcG9uc2UocGFyYW1zOiBWZXJpZnlSZXNwb25zZU9wdGlvbnMpOiBQcm9taXNlPFZlcmlmeVJlc3BvbnNlSW5mbz4ge1xuICAgIHRoaXMudmVyaWZ5UmVzcG9uc2VDYWxscy5wdXNoKHBhcmFtcyk7XG4gICAgcmV0dXJuIHtcbiAgICAgIGlzVmFsaWQ6IHRydWUsXG4gICAgICBleHBlY3RlZEhtYWM6ICdtb2NrLWhtYWMtdmFsdWUnLFxuICAgICAgc2lnbmF0dXJlU3ViamVjdDogJ21vY2stc3ViamVjdCcsXG4gICAgICBpc0luUmVzcG9uc2VWYWxpZGl0eVdpbmRvdzogdHJ1ZSxcbiAgICAgIHZlcmlmaWNhdGlvblRpbWU6IERhdGUubm93KCksXG4gICAgfTtcbiAgfVxuXG4gIGFzeW5jIGNhbGN1bGF0ZUhNQUMoa2V5OiBzdHJpbmcsIG1lc3NhZ2U6IHN0cmluZyk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgdGhpcy5jYWxjdWxhdGVITUFDQ2FsbHMucHVzaCh7IGtleSwgbWVzc2FnZSB9KTtcbiAgICByZXR1cm4gJ21vY2staG1hYy1wYXNzd29yZCc7XG4gIH1cbn1cblxuZGVzY3JpYmUoJ0JpdEdvQVBJIEhNQUMgU3RyYXRlZ3kgSW5qZWN0aW9uJywgZnVuY3Rpb24gKCkge1xuICBhZnRlckVhY2goZnVuY3Rpb24gKCkge1xuICAgIG5vY2suY2xlYW5BbGwoKTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ2NvbnN0cnVjdG9yJywgZnVuY3Rpb24gKCkge1xuICAgIGl0KCdzaG91bGQgYWNjZXB0IGEgY3VzdG9tIGhtYWNBdXRoU3RyYXRlZ3knLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBzdHJhdGVneSA9IG5ldyBNb2NrSG1hY0F1dGhTdHJhdGVneSgpO1xuICAgICAgY29uc3QgYml0Z28gPSBuZXcgQml0R29BUEkoe1xuICAgICAgICBlbnY6ICdjdXN0b20nLFxuICAgICAgICBjdXN0b21Sb290VVJJOiBURVNUX1VSSSxcbiAgICAgICAgaG1hY0F1dGhTdHJhdGVneTogc3RyYXRlZ3ksXG4gICAgICB9KTtcblxuICAgICAgYml0Z28uc2hvdWxkLmJlLm9rKCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGRlZmF1bHQgdG8gRGVmYXVsdEhtYWNBdXRoU3RyYXRlZ3kgd2hlbiBub25lIGlzIHByb3ZpZGVkJywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgYml0Z28gPSBuZXcgQml0R29BUEkoe1xuICAgICAgICBlbnY6ICdjdXN0b20nLFxuICAgICAgICBjdXN0b21Sb290VVJJOiBURVNUX1VSSSxcbiAgICAgIH0pO1xuXG4gICAgICBiaXRnby5zaG91bGQuYmUub2soKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ3JlcXVlc3Qgc2lnbmluZyB2aWEgc3RyYXRlZ3knLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ3Nob3VsZCB1c2UgdGhlIGN1c3RvbSBzdHJhdGVneSBmb3IgSE1BQyBoZWFkZXIgY2FsY3VsYXRpb24nLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBzdHJhdGVneSA9IG5ldyBNb2NrSG1hY0F1dGhTdHJhdGVneSgpO1xuICAgICAgY29uc3QgYml0Z28gPSBuZXcgQml0R29BUEkoe1xuICAgICAgICBlbnY6ICdjdXN0b20nLFxuICAgICAgICBjdXN0b21Sb290VVJJOiBURVNUX1VSSSxcbiAgICAgICAgYWNjZXNzVG9rZW46IFRFU1RfVE9LRU4sXG4gICAgICAgIGhtYWNBdXRoU3RyYXRlZ3k6IHN0cmF0ZWd5LFxuICAgICAgfSk7XG5cbiAgICAgIGNvbnN0IHNjb3BlID0gbm9jayhURVNUX1VSSSlcbiAgICAgICAgLmdldCgnL2FwaS92Mi93YWxsZXQnKVxuICAgICAgICAubWF0Y2hIZWFkZXIoJ0hNQUMnLCAnbW9jay1obWFjLXZhbHVlJylcbiAgICAgICAgLm1hdGNoSGVhZGVyKCdBdXRob3JpemF0aW9uJywgJ0JlYXJlciBtb2NrLXRva2VuLWhhc2gnKVxuICAgICAgICAubWF0Y2hIZWFkZXIoJ0F1dGgtVGltZXN0YW1wJywgJzE2NzI1MzEyMDAwMDAnKVxuICAgICAgICAucmVwbHkoXG4gICAgICAgICAgMjAwLFxuICAgICAgICAgIHsgd2FsbGV0czogW10gfSxcbiAgICAgICAgICB7XG4gICAgICAgICAgICBobWFjOiAncmVzcG9uc2UtaG1hYycsXG4gICAgICAgICAgICB0aW1lc3RhbXA6IERhdGUubm93KCkudG9TdHJpbmcoKSxcbiAgICAgICAgICB9XG4gICAgICAgICk7XG5cbiAgICAgIGF3YWl0IGJpdGdvLmdldChiaXRnby51cmwoJy93YWxsZXQnLCAyKSkucmVzdWx0KCk7XG5cbiAgICAgIHN0cmF0ZWd5LmNhbGN1bGF0ZVJlcXVlc3RIZWFkZXJzQ2FsbHMubGVuZ3RoLnNob3VsZC5lcXVhbCgxKTtcbiAgICAgIGNvbnN0IGNhbGwgPSBzdHJhdGVneS5jYWxjdWxhdGVSZXF1ZXN0SGVhZGVyc0NhbGxzWzBdO1xuICAgICAgY2FsbC50b2tlbi5zaG91bGQuZXF1YWwoVEVTVF9UT0tFTik7XG4gICAgICBjYWxsLm1ldGhvZC5zaG91bGQuZXF1YWwoJ2dldCcpO1xuXG4gICAgICBzY29wZS5pc0RvbmUoKS5zaG91bGQuYmUudHJ1ZSgpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB1c2UgdGhlIGN1c3RvbSBzdHJhdGVneSBmb3IgcmVzcG9uc2UgdmVyaWZpY2F0aW9uJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgc3RyYXRlZ3kgPSBuZXcgTW9ja0htYWNBdXRoU3RyYXRlZ3koKTtcbiAgICAgIGNvbnN0IGJpdGdvID0gbmV3IEJpdEdvQVBJKHtcbiAgICAgICAgZW52OiAnY3VzdG9tJyxcbiAgICAgICAgY3VzdG9tUm9vdFVSSTogVEVTVF9VUkksXG4gICAgICAgIGFjY2Vzc1Rva2VuOiBURVNUX1RPS0VOLFxuICAgICAgICBobWFjQXV0aFN0cmF0ZWd5OiBzdHJhdGVneSxcbiAgICAgIH0pO1xuXG4gICAgICBub2NrKFRFU1RfVVJJKS5nZXQoJy9hcGkvdjIvd2FsbGV0JykucmVwbHkoXG4gICAgICAgIDIwMCxcbiAgICAgICAgeyB3YWxsZXRzOiBbXSB9LFxuICAgICAgICB7XG4gICAgICAgICAgaG1hYzogJ3NlcnZlci1yZXNwb25zZS1obWFjJyxcbiAgICAgICAgICB0aW1lc3RhbXA6IERhdGUubm93KCkudG9TdHJpbmcoKSxcbiAgICAgICAgfVxuICAgICAgKTtcblxuICAgICAgYXdhaXQgYml0Z28uZ2V0KGJpdGdvLnVybCgnL3dhbGxldCcsIDIpKS5yZXN1bHQoKTtcblxuICAgICAgc3RyYXRlZ3kudmVyaWZ5UmVzcG9uc2VDYWxscy5sZW5ndGguc2hvdWxkLmVxdWFsKDEpO1xuICAgICAgY29uc3QgY2FsbCA9IHN0cmF0ZWd5LnZlcmlmeVJlc3BvbnNlQ2FsbHNbMF07XG4gICAgICBjYWxsLmhtYWMuc2hvdWxkLmVxdWFsKCdzZXJ2ZXItcmVzcG9uc2UtaG1hYycpO1xuICAgICAgYXNzZXJ0KGNhbGwuc3RhdHVzQ29kZSwgJ3N0YXR1c0NvZGUgaXMgcmVxdWlyZWQnKTtcbiAgICAgIGNhbGwuc3RhdHVzQ29kZS5zaG91bGQuZXF1YWwoMjAwKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ3Bhc3N3b3JkIEhNQUMgdmlhIHN0cmF0ZWd5JywgZnVuY3Rpb24gKCkge1xuICAgIGl0KCdzaG91bGQgdXNlIHRoZSBjdXN0b20gc3RyYXRlZ3kgZm9yIHBhc3N3b3JkIGhhc2hpbmcgaW4gcHJlcHJvY2Vzc0F1dGhlbnRpY2F0aW9uUGFyYW1zJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgc3RyYXRlZ3kgPSBuZXcgTW9ja0htYWNBdXRoU3RyYXRlZ3koKTtcbiAgICAgIGNvbnN0IGJpdGdvID0gbmV3IEJpdEdvQVBJKHtcbiAgICAgICAgZW52OiAnY3VzdG9tJyxcbiAgICAgICAgY3VzdG9tUm9vdFVSSTogVEVTVF9VUkksXG4gICAgICAgIGhtYWNBdXRoU3RyYXRlZ3k6IHN0cmF0ZWd5LFxuICAgICAgfSk7XG5cbiAgICAgIG5vY2soVEVTVF9VUkkpXG4gICAgICAgIC5wb3N0KCcvYXBpL2F1dGgvdjEvc2Vzc2lvbicpXG4gICAgICAgIC5yZXBseShcbiAgICAgICAgICAyMDAsXG4gICAgICAgICAgeyBhY2Nlc3NfdG9rZW46IFRFU1RfVE9LRU4sIHVzZXI6IHsgdXNlcm5hbWU6ICd0ZXN0QHRlc3QuY29tJyB9IH0sXG4gICAgICAgICAge1xuICAgICAgICAgICAgaG1hYzogJ3Jlc3AtaG1hYycsXG4gICAgICAgICAgICB0aW1lc3RhbXA6IERhdGUubm93KCkudG9TdHJpbmcoKSxcbiAgICAgICAgICB9XG4gICAgICAgICk7XG5cbiAgICAgIGF3YWl0IGJpdGdvLmF1dGhlbnRpY2F0ZSh7XG4gICAgICAgIHVzZXJuYW1lOiAndGVzdEB0ZXN0LmNvbScsXG4gICAgICAgIHBhc3N3b3JkOiAnbXlwYXNzd29yZCcsXG4gICAgICB9KTtcblxuICAgICAgc3RyYXRlZ3kuY2FsY3VsYXRlSE1BQ0NhbGxzLmxlbmd0aC5zaG91bGQuYmUuZ3JlYXRlclRoYW4oMCk7XG4gICAgICBjb25zdCBobWFjQ2FsbCA9IHN0cmF0ZWd5LmNhbGN1bGF0ZUhNQUNDYWxsc1swXTtcbiAgICAgIGhtYWNDYWxsLmtleS5zaG91bGQuZXF1YWwoJ3Rlc3RAdGVzdC5jb20nKTtcbiAgICAgIGhtYWNDYWxsLm1lc3NhZ2Uuc2hvdWxkLmVxdWFsKCdteXBhc3N3b3JkJyk7XG4gICAgfSk7XG4gIH0pO1xufSk7XG4iXX0=