@bitgo-beta/sdk-coin-irys 0.0.1-alpha.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/LICENSE +191 -0
- package/dist/src/index.d.ts +2 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +18 -0
- package/dist/src/lib/commitmentTransactionBuilder.d.ts +108 -0
- package/dist/src/lib/commitmentTransactionBuilder.d.ts.map +1 -0
- package/dist/src/lib/commitmentTransactionBuilder.js +221 -0
- package/dist/src/lib/iface.d.ts +86 -0
- package/dist/src/lib/iface.d.ts.map +1 -0
- package/dist/src/lib/iface.js +19 -0
- package/dist/src/lib/index.d.ts +4 -0
- package/dist/src/lib/index.d.ts.map +1 -0
- package/dist/src/lib/index.js +20 -0
- package/dist/src/lib/utils.d.ts +23 -0
- package/dist/src/lib/utils.d.ts.map +1 -0
- package/dist/src/lib/utils.js +52 -0
- package/dist/test/unit/commitmentTransactionBuilder.d.ts +2 -0
- package/dist/test/unit/commitmentTransactionBuilder.d.ts.map +1 -0
- package/dist/test/unit/commitmentTransactionBuilder.js +402 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +59 -0
|
@@ -0,0 +1,402 @@
|
|
|
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 should_1 = __importDefault(require("should"));
|
|
40
|
+
const sinon = __importStar(require("sinon"));
|
|
41
|
+
const nock_1 = __importDefault(require("nock"));
|
|
42
|
+
const commitmentTransactionBuilder_1 = require("../../src/lib/commitmentTransactionBuilder");
|
|
43
|
+
const iface_1 = require("../../src/lib/iface");
|
|
44
|
+
const utils_1 = require("../../src/lib/utils");
|
|
45
|
+
describe('IrysCommitmentTransactionBuilder', function () {
|
|
46
|
+
// Common test fixtures
|
|
47
|
+
const testAnchor = new Uint8Array(32).fill(1); // 32 bytes of 0x01
|
|
48
|
+
const testSigner = new Uint8Array(20).fill(2); // 20 bytes of 0x02
|
|
49
|
+
const testChainId = iface_1.IRYS_TESTNET_CHAIN_ID; // 1270n
|
|
50
|
+
const testFee = 1000n;
|
|
51
|
+
const testValue = 5000n;
|
|
52
|
+
const testApiUrl = 'https://testnet-node1.irys.xyz/v1';
|
|
53
|
+
let builder;
|
|
54
|
+
beforeEach(function () {
|
|
55
|
+
builder = new commitmentTransactionBuilder_1.IrysCommitmentTransactionBuilder(testApiUrl, testChainId);
|
|
56
|
+
});
|
|
57
|
+
afterEach(function () {
|
|
58
|
+
sinon.restore();
|
|
59
|
+
nock_1.default.cleanAll();
|
|
60
|
+
});
|
|
61
|
+
// === Commitment Type Encoding Tests ===
|
|
62
|
+
describe('encodeCommitmentTypeForSigning', function () {
|
|
63
|
+
it('should encode STAKE as a flat number (not array)', function () {
|
|
64
|
+
const result = commitmentTransactionBuilder_1.IrysCommitmentTransactionBuilder.encodeCommitmentTypeForSigning({
|
|
65
|
+
type: iface_1.CommitmentTypeId.STAKE,
|
|
66
|
+
});
|
|
67
|
+
result.should.equal(1);
|
|
68
|
+
Array.isArray(result).should.be.false();
|
|
69
|
+
});
|
|
70
|
+
it('should encode PLEDGE as a nested array [type, pledgeCount]', function () {
|
|
71
|
+
const result = commitmentTransactionBuilder_1.IrysCommitmentTransactionBuilder.encodeCommitmentTypeForSigning({
|
|
72
|
+
type: iface_1.CommitmentTypeId.PLEDGE,
|
|
73
|
+
pledgeCount: 42n,
|
|
74
|
+
});
|
|
75
|
+
Array.isArray(result).should.be.true();
|
|
76
|
+
result.length.should.equal(2);
|
|
77
|
+
result[0].should.equal(2);
|
|
78
|
+
result[1].should.equal(42n);
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
// === Commitment Type Broadcast Encoding Tests ===
|
|
82
|
+
describe('encodeCommitmentTypeForBroadcast', function () {
|
|
83
|
+
it('should encode STAKE as { type: "stake" }', function () {
|
|
84
|
+
const result = commitmentTransactionBuilder_1.IrysCommitmentTransactionBuilder.encodeCommitmentTypeForBroadcast({
|
|
85
|
+
type: iface_1.CommitmentTypeId.STAKE,
|
|
86
|
+
});
|
|
87
|
+
should_1.default.deepEqual(result, { type: 'stake' });
|
|
88
|
+
});
|
|
89
|
+
it('should encode PLEDGE with pledgeCountBeforeExecuting', function () {
|
|
90
|
+
const result = commitmentTransactionBuilder_1.IrysCommitmentTransactionBuilder.encodeCommitmentTypeForBroadcast({
|
|
91
|
+
type: iface_1.CommitmentTypeId.PLEDGE,
|
|
92
|
+
pledgeCount: 42n,
|
|
93
|
+
});
|
|
94
|
+
should_1.default.deepEqual(result, { type: 'pledge', pledgeCountBeforeExecuting: '42' });
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
// === RLP Encoding Tests ===
|
|
98
|
+
describe('rlpEncode', function () {
|
|
99
|
+
it('should RLP encode a STAKE transaction with correct field order', function () {
|
|
100
|
+
const fields = {
|
|
101
|
+
version: iface_1.COMMITMENT_TX_VERSION,
|
|
102
|
+
anchor: testAnchor,
|
|
103
|
+
signer: testSigner,
|
|
104
|
+
commitmentType: { type: iface_1.CommitmentTypeId.STAKE },
|
|
105
|
+
chainId: testChainId,
|
|
106
|
+
fee: testFee,
|
|
107
|
+
value: testValue,
|
|
108
|
+
};
|
|
109
|
+
const encoded = builder.rlpEncode(fields);
|
|
110
|
+
encoded.should.be.instanceOf(Uint8Array);
|
|
111
|
+
encoded.length.should.be.greaterThan(0);
|
|
112
|
+
// The encoded output should be deterministic
|
|
113
|
+
const encoded2 = builder.rlpEncode(fields);
|
|
114
|
+
Buffer.from(encoded).equals(Buffer.from(encoded2)).should.be.true();
|
|
115
|
+
});
|
|
116
|
+
it('should RLP encode a PLEDGE transaction with nested array commitment type', function () {
|
|
117
|
+
const fields = {
|
|
118
|
+
version: iface_1.COMMITMENT_TX_VERSION,
|
|
119
|
+
anchor: testAnchor,
|
|
120
|
+
signer: testSigner,
|
|
121
|
+
commitmentType: { type: iface_1.CommitmentTypeId.PLEDGE, pledgeCount: 42n },
|
|
122
|
+
chainId: testChainId,
|
|
123
|
+
fee: testFee,
|
|
124
|
+
value: testValue,
|
|
125
|
+
};
|
|
126
|
+
const encoded = builder.rlpEncode(fields);
|
|
127
|
+
encoded.should.be.instanceOf(Uint8Array);
|
|
128
|
+
encoded.length.should.be.greaterThan(0);
|
|
129
|
+
});
|
|
130
|
+
it('should produce different encodings for STAKE vs PLEDGE', function () {
|
|
131
|
+
const stakeFields = {
|
|
132
|
+
version: iface_1.COMMITMENT_TX_VERSION,
|
|
133
|
+
anchor: testAnchor,
|
|
134
|
+
signer: testSigner,
|
|
135
|
+
commitmentType: { type: iface_1.CommitmentTypeId.STAKE },
|
|
136
|
+
chainId: testChainId,
|
|
137
|
+
fee: testFee,
|
|
138
|
+
value: testValue,
|
|
139
|
+
};
|
|
140
|
+
const pledgeFields = {
|
|
141
|
+
...stakeFields,
|
|
142
|
+
commitmentType: { type: iface_1.CommitmentTypeId.PLEDGE, pledgeCount: 1n },
|
|
143
|
+
};
|
|
144
|
+
const stakeEncoded = builder.rlpEncode(stakeFields);
|
|
145
|
+
const pledgeEncoded = builder.rlpEncode(pledgeFields);
|
|
146
|
+
Buffer.from(stakeEncoded).equals(Buffer.from(pledgeEncoded)).should.be.false();
|
|
147
|
+
});
|
|
148
|
+
});
|
|
149
|
+
// === Prehash Tests ===
|
|
150
|
+
describe('computePrehash', function () {
|
|
151
|
+
it('should return a 32-byte keccak256 hash', function () {
|
|
152
|
+
const rlpEncoded = new Uint8Array([0xc0]); // minimal RLP
|
|
153
|
+
const prehash = builder.computePrehash(rlpEncoded);
|
|
154
|
+
prehash.should.be.instanceOf(Uint8Array);
|
|
155
|
+
prehash.length.should.equal(32);
|
|
156
|
+
});
|
|
157
|
+
it('should produce deterministic output', function () {
|
|
158
|
+
const rlpEncoded = new Uint8Array([0xc8, 0x02, 0x01, 0x02, 0x03]);
|
|
159
|
+
const hash1 = builder.computePrehash(rlpEncoded);
|
|
160
|
+
const hash2 = builder.computePrehash(rlpEncoded);
|
|
161
|
+
Buffer.from(hash1).equals(Buffer.from(hash2)).should.be.true();
|
|
162
|
+
});
|
|
163
|
+
it('should produce different hashes for different inputs', function () {
|
|
164
|
+
const input1 = new Uint8Array([0x01]);
|
|
165
|
+
const input2 = new Uint8Array([0x02]);
|
|
166
|
+
const hash1 = builder.computePrehash(input1);
|
|
167
|
+
const hash2 = builder.computePrehash(input2);
|
|
168
|
+
Buffer.from(hash1).equals(Buffer.from(hash2)).should.be.false();
|
|
169
|
+
});
|
|
170
|
+
});
|
|
171
|
+
// === Build Tests ===
|
|
172
|
+
describe('build', function () {
|
|
173
|
+
it('should build a STAKE transaction with manually set anchor', async function () {
|
|
174
|
+
builder
|
|
175
|
+
.setCommitmentType({ type: iface_1.CommitmentTypeId.STAKE })
|
|
176
|
+
.setFee(testFee)
|
|
177
|
+
.setValue(testValue)
|
|
178
|
+
.setSigner(testSigner)
|
|
179
|
+
.setAnchor(testAnchor);
|
|
180
|
+
const result = await builder.build();
|
|
181
|
+
result.prehash.should.be.instanceOf(Uint8Array);
|
|
182
|
+
result.prehash.length.should.equal(32);
|
|
183
|
+
result.rlpEncoded.should.be.instanceOf(Uint8Array);
|
|
184
|
+
result.rlpEncoded.length.should.be.greaterThan(0);
|
|
185
|
+
result.fields.version.should.equal(iface_1.COMMITMENT_TX_VERSION);
|
|
186
|
+
result.fields.chainId.should.equal(testChainId);
|
|
187
|
+
});
|
|
188
|
+
it('should build a PLEDGE transaction with manually set anchor', async function () {
|
|
189
|
+
builder
|
|
190
|
+
.setCommitmentType({ type: iface_1.CommitmentTypeId.PLEDGE, pledgeCount: 5n })
|
|
191
|
+
.setFee(testFee)
|
|
192
|
+
.setValue(testValue)
|
|
193
|
+
.setSigner(testSigner)
|
|
194
|
+
.setAnchor(testAnchor);
|
|
195
|
+
const result = await builder.build();
|
|
196
|
+
result.prehash.length.should.equal(32);
|
|
197
|
+
result.fields.commitmentType.should.deepEqual({ type: iface_1.CommitmentTypeId.PLEDGE, pledgeCount: 5n });
|
|
198
|
+
});
|
|
199
|
+
it('should fetch anchor from API when not manually set', async function () {
|
|
200
|
+
const mockAnchorBase58 = (0, utils_1.encodeBase58)(testAnchor);
|
|
201
|
+
const scope = (0, nock_1.default)('https://testnet-node1.irys.xyz')
|
|
202
|
+
.get('/v1/anchor')
|
|
203
|
+
.reply(200, { blockHash: mockAnchorBase58 });
|
|
204
|
+
builder
|
|
205
|
+
.setCommitmentType({ type: iface_1.CommitmentTypeId.STAKE })
|
|
206
|
+
.setFee(testFee)
|
|
207
|
+
.setValue(testValue)
|
|
208
|
+
.setSigner(testSigner);
|
|
209
|
+
const result = await builder.build();
|
|
210
|
+
result.prehash.length.should.equal(32);
|
|
211
|
+
Buffer.from(result.fields.anchor).equals(Buffer.from(testAnchor)).should.be.true();
|
|
212
|
+
scope.done();
|
|
213
|
+
});
|
|
214
|
+
it('should throw if commitment type is not set', async function () {
|
|
215
|
+
builder.setFee(testFee).setValue(testValue).setSigner(testSigner).setAnchor(testAnchor);
|
|
216
|
+
await builder.build().should.be.rejectedWith('Commitment type is required');
|
|
217
|
+
});
|
|
218
|
+
it('should throw if fee is not set', async function () {
|
|
219
|
+
builder
|
|
220
|
+
.setCommitmentType({ type: iface_1.CommitmentTypeId.STAKE })
|
|
221
|
+
.setValue(testValue)
|
|
222
|
+
.setSigner(testSigner)
|
|
223
|
+
.setAnchor(testAnchor);
|
|
224
|
+
await builder.build().should.be.rejectedWith('Fee is required');
|
|
225
|
+
});
|
|
226
|
+
it('should throw if value is not set', async function () {
|
|
227
|
+
builder
|
|
228
|
+
.setCommitmentType({ type: iface_1.CommitmentTypeId.STAKE })
|
|
229
|
+
.setFee(testFee)
|
|
230
|
+
.setSigner(testSigner)
|
|
231
|
+
.setAnchor(testAnchor);
|
|
232
|
+
await builder.build().should.be.rejectedWith('Value is required');
|
|
233
|
+
});
|
|
234
|
+
it('should throw if signer is not set', async function () {
|
|
235
|
+
builder
|
|
236
|
+
.setCommitmentType({ type: iface_1.CommitmentTypeId.STAKE })
|
|
237
|
+
.setFee(testFee)
|
|
238
|
+
.setValue(testValue)
|
|
239
|
+
.setAnchor(testAnchor);
|
|
240
|
+
await builder.build().should.be.rejectedWith('Signer is required');
|
|
241
|
+
});
|
|
242
|
+
});
|
|
243
|
+
// === Validation Tests ===
|
|
244
|
+
describe('input validation', function () {
|
|
245
|
+
it('should reject signer with wrong length', function () {
|
|
246
|
+
(() => builder.setSigner(new Uint8Array(19))).should.throw(/Signer must be 20 bytes/);
|
|
247
|
+
(() => builder.setSigner(new Uint8Array(21))).should.throw(/Signer must be 20 bytes/);
|
|
248
|
+
});
|
|
249
|
+
it('should reject anchor with wrong length', function () {
|
|
250
|
+
(() => builder.setAnchor(new Uint8Array(31))).should.throw(/Anchor must be 32 bytes/);
|
|
251
|
+
(() => builder.setAnchor(new Uint8Array(33))).should.throw(/Anchor must be 32 bytes/);
|
|
252
|
+
});
|
|
253
|
+
});
|
|
254
|
+
// === Transaction ID Tests ===
|
|
255
|
+
describe('computeTxId', function () {
|
|
256
|
+
it('should compute base58(keccak256(signature))', function () {
|
|
257
|
+
const fakeSignature = new Uint8Array(65).fill(0xab);
|
|
258
|
+
const txId = commitmentTransactionBuilder_1.IrysCommitmentTransactionBuilder.computeTxId(fakeSignature);
|
|
259
|
+
txId.should.be.a.String();
|
|
260
|
+
txId.length.should.be.greaterThan(0);
|
|
261
|
+
});
|
|
262
|
+
it('should produce deterministic output', function () {
|
|
263
|
+
const sig = new Uint8Array(65).fill(0xcd);
|
|
264
|
+
const id1 = commitmentTransactionBuilder_1.IrysCommitmentTransactionBuilder.computeTxId(sig);
|
|
265
|
+
const id2 = commitmentTransactionBuilder_1.IrysCommitmentTransactionBuilder.computeTxId(sig);
|
|
266
|
+
id1.should.equal(id2);
|
|
267
|
+
});
|
|
268
|
+
it('should reject non-65-byte signatures', function () {
|
|
269
|
+
(() => commitmentTransactionBuilder_1.IrysCommitmentTransactionBuilder.computeTxId(new Uint8Array(64))).should.throw(/Signature must be 65 bytes/);
|
|
270
|
+
});
|
|
271
|
+
});
|
|
272
|
+
// === Broadcast Payload Tests ===
|
|
273
|
+
describe('createBroadcastPayload', function () {
|
|
274
|
+
it('should create valid JSON payload for STAKE', function () {
|
|
275
|
+
const fields = {
|
|
276
|
+
version: iface_1.COMMITMENT_TX_VERSION,
|
|
277
|
+
anchor: testAnchor,
|
|
278
|
+
signer: testSigner,
|
|
279
|
+
commitmentType: { type: iface_1.CommitmentTypeId.STAKE },
|
|
280
|
+
chainId: testChainId,
|
|
281
|
+
fee: testFee,
|
|
282
|
+
value: testValue,
|
|
283
|
+
};
|
|
284
|
+
const signature = new Uint8Array(65).fill(0xab);
|
|
285
|
+
const payload = commitmentTransactionBuilder_1.IrysCommitmentTransactionBuilder.createBroadcastPayload(fields, signature);
|
|
286
|
+
payload.version.should.equal(2);
|
|
287
|
+
payload.anchor.should.be.a.String();
|
|
288
|
+
payload.signer.should.be.a.String();
|
|
289
|
+
should_1.default.deepEqual(payload.commitmentType, { type: 'stake' });
|
|
290
|
+
payload.chainId.should.equal('1270');
|
|
291
|
+
payload.fee.should.equal('1000');
|
|
292
|
+
payload.value.should.equal('5000');
|
|
293
|
+
payload.id.should.be.a.String();
|
|
294
|
+
payload.signature.should.be.a.String();
|
|
295
|
+
});
|
|
296
|
+
it('should create valid JSON payload for PLEDGE with pledgeCountBeforeExecuting', function () {
|
|
297
|
+
const fields = {
|
|
298
|
+
version: iface_1.COMMITMENT_TX_VERSION,
|
|
299
|
+
anchor: testAnchor,
|
|
300
|
+
signer: testSigner,
|
|
301
|
+
commitmentType: { type: iface_1.CommitmentTypeId.PLEDGE, pledgeCount: 42n },
|
|
302
|
+
chainId: testChainId,
|
|
303
|
+
fee: testFee,
|
|
304
|
+
value: testValue,
|
|
305
|
+
};
|
|
306
|
+
const signature = new Uint8Array(65).fill(0xcd);
|
|
307
|
+
const payload = commitmentTransactionBuilder_1.IrysCommitmentTransactionBuilder.createBroadcastPayload(fields, signature);
|
|
308
|
+
should_1.default.deepEqual(payload.commitmentType, { type: 'pledge', pledgeCountBeforeExecuting: '42' });
|
|
309
|
+
});
|
|
310
|
+
});
|
|
311
|
+
// === Known-Good Test Vectors (from successful testnet transactions) ===
|
|
312
|
+
//
|
|
313
|
+
// These vectors were captured from actual STAKE and PLEDGE transactions
|
|
314
|
+
// submitted to the Irys testnet using coins-sandbox/eth/irys/stake.ts.
|
|
315
|
+
// They verify our RLP encoding + prehash match the protocol exactly.
|
|
316
|
+
describe('known-good test vectors', function () {
|
|
317
|
+
const testnetSigner = '0x22f9C9f1845D9b6C22b96Ef35E46E265aC4Af30c';
|
|
318
|
+
const testnetSignerBytes = Uint8Array.from(Buffer.from(testnetSigner.slice(2), 'hex'));
|
|
319
|
+
const testnetChainId = 1270n;
|
|
320
|
+
it('should match known STAKE RLP encoding and prehash', async function () {
|
|
321
|
+
// From stake_pledge.txt - successful STAKE transaction
|
|
322
|
+
// TX ID: 4XhUTrkhxr1RmUQbXUVRwbNZ6pKEYrAVo5ymdMY41fS5
|
|
323
|
+
const anchorBase58 = '8JR2rD5DejnM2NuVSqqGa68dfye6ZKruT9rdh2Cn4B8y';
|
|
324
|
+
const anchorBytes = (0, utils_1.decodeBase58)(anchorBase58);
|
|
325
|
+
const stakeBuilder = new commitmentTransactionBuilder_1.IrysCommitmentTransactionBuilder(testApiUrl, testnetChainId);
|
|
326
|
+
stakeBuilder
|
|
327
|
+
.setCommitmentType({ type: iface_1.CommitmentTypeId.STAKE })
|
|
328
|
+
.setFee(100n)
|
|
329
|
+
.setValue(20000000000000000000000n) // 20000 IRYS
|
|
330
|
+
.setSigner(testnetSignerBytes)
|
|
331
|
+
.setAnchor(anchorBytes);
|
|
332
|
+
const result = await stakeBuilder.build();
|
|
333
|
+
const expectedRlp = '0xf84702a06c77daebc2db4e572e4f296983d1413fc10d4852e0fabfdb8323c9c69a2b85' +
|
|
334
|
+
'9e9422f9c9f1845d9b6c22b96ef35e46e265ac4af30c018204f6648a043c33c1937564800000';
|
|
335
|
+
const actualRlp = '0x' + Buffer.from(result.rlpEncoded).toString('hex');
|
|
336
|
+
actualRlp.should.equal(expectedRlp);
|
|
337
|
+
const expectedPrehash = '0xe6fe57810c12785e3ce5fa64e2eb4da120b89ec0e469213715916abf36358d01';
|
|
338
|
+
const actualPrehash = '0x' + Buffer.from(result.prehash).toString('hex');
|
|
339
|
+
actualPrehash.should.equal(expectedPrehash);
|
|
340
|
+
});
|
|
341
|
+
it('should match known PLEDGE RLP encoding and prehash', async function () {
|
|
342
|
+
// From stake_pledge.txt - successful PLEDGE transaction
|
|
343
|
+
// TX ID: EsdiesC58S8eeY1SHM5jTfy84zYxFMUdKF89Ytr6PyNb
|
|
344
|
+
const anchorBase58 = 'jUShJPUACW4bxUSvZji65Q96MaqKDh7AFFALKnkapBn';
|
|
345
|
+
const anchorBytes = (0, utils_1.decodeBase58)(anchorBase58);
|
|
346
|
+
const pledgeBuilder = new commitmentTransactionBuilder_1.IrysCommitmentTransactionBuilder(testApiUrl, testnetChainId);
|
|
347
|
+
pledgeBuilder
|
|
348
|
+
.setCommitmentType({ type: iface_1.CommitmentTypeId.PLEDGE, pledgeCount: 0n })
|
|
349
|
+
.setFee(100n)
|
|
350
|
+
.setValue(950000000000000000000n) // 950 IRYS
|
|
351
|
+
.setSigner(testnetSignerBytes)
|
|
352
|
+
.setAnchor(anchorBytes);
|
|
353
|
+
const result = await pledgeBuilder.build();
|
|
354
|
+
const expectedRlp = '0xf84802a00ae16c8476bbde2f28b2e4629d393dfe6fa7affcf0a0c4654f8246a9ba78970594' +
|
|
355
|
+
'22f9c9f1845d9b6c22b96ef35e46e265ac4af30cc202808204f66489337fe5feaf2d180000';
|
|
356
|
+
const actualRlp = '0x' + Buffer.from(result.rlpEncoded).toString('hex');
|
|
357
|
+
actualRlp.should.equal(expectedRlp);
|
|
358
|
+
const expectedPrehash = '0xfe07c2f3c6e50d9c9e2cff57f6d7015b4528f425b6132f567e26bba745228102';
|
|
359
|
+
const actualPrehash = '0x' + Buffer.from(result.prehash).toString('hex');
|
|
360
|
+
actualPrehash.should.equal(expectedPrehash);
|
|
361
|
+
});
|
|
362
|
+
});
|
|
363
|
+
// === Edge Case Tests ===
|
|
364
|
+
describe('edge cases', function () {
|
|
365
|
+
it('should handle zero fee and value', async function () {
|
|
366
|
+
builder
|
|
367
|
+
.setCommitmentType({ type: iface_1.CommitmentTypeId.STAKE })
|
|
368
|
+
.setFee(0n)
|
|
369
|
+
.setValue(0n)
|
|
370
|
+
.setSigner(testSigner)
|
|
371
|
+
.setAnchor(testAnchor);
|
|
372
|
+
const result = await builder.build();
|
|
373
|
+
result.prehash.length.should.equal(32);
|
|
374
|
+
});
|
|
375
|
+
});
|
|
376
|
+
// === Anchor Fetch Tests ===
|
|
377
|
+
describe('fetchAnchor', function () {
|
|
378
|
+
it('should fetch and decode base58 anchor from API', async function () {
|
|
379
|
+
const mockAnchorBase58 = (0, utils_1.encodeBase58)(testAnchor);
|
|
380
|
+
const scope = (0, nock_1.default)('https://testnet-node1.irys.xyz')
|
|
381
|
+
.get('/v1/anchor')
|
|
382
|
+
.reply(200, { blockHash: mockAnchorBase58 });
|
|
383
|
+
const anchor = await builder.fetchAnchor();
|
|
384
|
+
anchor.should.be.instanceOf(Uint8Array);
|
|
385
|
+
anchor.length.should.equal(32);
|
|
386
|
+
Buffer.from(anchor).equals(Buffer.from(testAnchor)).should.be.true();
|
|
387
|
+
scope.done();
|
|
388
|
+
});
|
|
389
|
+
it('should throw on non-200 response', async function () {
|
|
390
|
+
const scope = (0, nock_1.default)('https://testnet-node1.irys.xyz').get('/v1/anchor').reply(500, 'Internal Server Error');
|
|
391
|
+
await builder.fetchAnchor().should.be.rejectedWith(/Internal Server Error/);
|
|
392
|
+
scope.done();
|
|
393
|
+
});
|
|
394
|
+
it('should throw if anchor decodes to wrong length', async function () {
|
|
395
|
+
const shortAnchor = (0, utils_1.encodeBase58)(new Uint8Array(16)); // 16 bytes instead of 32
|
|
396
|
+
const scope = (0, nock_1.default)('https://testnet-node1.irys.xyz').get('/v1/anchor').reply(200, { blockHash: shortAnchor });
|
|
397
|
+
await builder.fetchAnchor().should.be.rejectedWith(/Expected 32 bytes/);
|
|
398
|
+
scope.done();
|
|
399
|
+
});
|
|
400
|
+
});
|
|
401
|
+
});
|
|
402
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29tbWl0bWVudFRyYW5zYWN0aW9uQnVpbGRlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3Rlc3QvdW5pdC9jb21taXRtZW50VHJhbnNhY3Rpb25CdWlsZGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsb0RBQTRCO0FBQzVCLDZDQUErQjtBQUMvQixnREFBd0I7QUFDeEIsNkZBQThGO0FBQzlGLCtDQUFxRztBQUNyRywrQ0FBaUU7QUFFakUsUUFBUSxDQUFDLGtDQUFrQyxFQUFFO0lBQzNDLHVCQUF1QjtJQUN2QixNQUFNLFVBQVUsR0FBRyxJQUFJLFVBQVUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxtQkFBbUI7SUFDbEUsTUFBTSxVQUFVLEdBQUcsSUFBSSxVQUFVLENBQUMsRUFBRSxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsbUJBQW1CO0lBQ2xFLE1BQU0sV0FBVyxHQUFHLDZCQUFxQixDQUFDLENBQUMsUUFBUTtJQUNuRCxNQUFNLE9BQU8sR0FBRyxLQUFLLENBQUM7SUFDdEIsTUFBTSxTQUFTLEdBQUcsS0FBSyxDQUFDO0lBQ3hCLE1BQU0sVUFBVSxHQUFHLG1DQUFtQyxDQUFDO0lBRXZELElBQUksT0FBeUMsQ0FBQztJQUU5QyxVQUFVLENBQUM7UUFDVCxPQUFPLEdBQUcsSUFBSSwrREFBZ0MsQ0FBQyxVQUFVLEVBQUUsV0FBVyxDQUFDLENBQUM7SUFDMUUsQ0FBQyxDQUFDLENBQUM7SUFFSCxTQUFTLENBQUM7UUFDUixLQUFLLENBQUMsT0FBTyxFQUFFLENBQUM7UUFDaEIsY0FBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO0lBQ2xCLENBQUMsQ0FBQyxDQUFDO0lBRUgseUNBQXlDO0lBRXpDLFFBQVEsQ0FBQyxnQ0FBZ0MsRUFBRTtRQUN6QyxFQUFFLENBQUMsa0RB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QUUsS0FBSztZQUMxQyxNQUFNLEtBQUssR0FBRyxJQUFBLGNBQUksRUFBQyxnQ0FBZ0MsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxZQUFZLENBQUMsQ0FBQyxLQUFLLENBQUMsR0FBRyxFQUFFLHVCQUF1QixDQUFDLENBQUM7WUFFM0csTUFBTSxPQUFPLENBQUMsV0FBVyxFQUFFLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxZQUFZLENBQUMsdUJBQXVCLENBQUMsQ0FBQztZQUM1RSxLQUFLLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDZixDQUFDLENBQUMsQ0FBQztRQUVILEVBQUUsQ0FBQyxnREFBZ0QsRUFBRSxLQUFLO1lBQ3hELE1BQU0sV0FBVyxHQUFHLElBQUEsb0JBQVksRUFBQyxJQUFJLFVBQVUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMseUJBQXlCO1lBQy9FLE1BQU0sS0FBSyxHQUFHLElBQUEsY0FBSSxFQUFDLGdDQUFnQyxDQUFDLENBQUMsR0FBRyxDQUFDLFlBQVksQ0FBQyxDQUFDLEtBQUssQ0FBQyxHQUFHLEVBQUUsRUFBRSxTQUFTLEVBQUUsV0FBVyxFQUFFLENBQUMsQ0FBQztZQUU5RyxNQUFNLE9BQU8sQ0FBQyxXQUFXLEVBQUUsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLFlBQVksQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDO1lBQ3hFLEtBQUssQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUNmLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBzaG91bGQgZnJvbSAnc2hvdWxkJztcbmltcG9ydCAqIGFzIHNpbm9uIGZyb20gJ3Npbm9uJztcbmltcG9ydCBub2NrIGZyb20gJ25vY2snO1xuaW1wb3J0IHsgSXJ5c0NvbW1pdG1lbnRUcmFuc2FjdGlvbkJ1aWxkZXIgfSBmcm9tICcuLi8uLi9zcmMvbGliL2NvbW1pdG1lbnRUcmFuc2FjdGlvbkJ1aWxkZXInO1xuaW1wb3J0IHsgQ29tbWl0bWVudFR5cGVJZCwgQ09NTUlUTUVOVF9UWF9WRVJTSU9OLCBJUllTX1RFU1RORVRfQ0hBSU5fSUQgfSBmcm9tICcuLi8uLi9zcmMvbGliL2lmYWNlJztcbmltcG9ydCB7IGVuY29kZUJhc2U1OCwgZGVjb2RlQmFzZTU4IH0gZnJvbSAnLi4vLi4vc3JjL2xpYi91dGlscyc7XG5cbmRlc2NyaWJlKCdJcnlzQ29tbWl0bWVudFRyYW5zYWN0aW9uQnVpbGRlcicsIGZ1bmN0aW9uICgpIHtcbiAgLy8gQ29tbW9uIHRlc3QgZml4dHVyZXNcbiAgY29uc3QgdGVzdEFuY2hvciA9IG5ldyBVaW50OEFycmF5KDMyKS5maWxsKDEpOyAvLyAzMiBieXRlcyBvZiAweDAxXG4gIGNvbnN0IHRlc3RTaWduZXIgPSBuZXcgVWludDhBcnJheSgyMCkuZmlsbCgyKTsgLy8gMjAgYnl0ZXMgb2YgMHgwMlxuICBjb25zdCB0ZXN0Q2hhaW5JZCA9IElSWVNfVEVTVE5FVF9DSEFJTl9JRDsgLy8gMTI3MG5cbiAgY29uc3QgdGVzdEZlZSA9IDEwMDBuO1xuICBjb25zdCB0ZXN0VmFsdWUgPSA1MDAwbjtcbiAgY29uc3QgdGVzdEFwaVVybCA9ICdodHRwczovL3Rlc3RuZXQtbm9kZTEuaXJ5cy54eXovdjEnO1xuXG4gIGxldCBidWlsZGVyOiBJcnlzQ29tbWl0bWVudFRyYW5zYWN0aW9uQnVpbGRlcjtcblxuICBiZWZvcmVFYWNoKGZ1bmN0aW9uICgpIHtcbiAgICBidWlsZGVyID0gbmV3IElyeXNDb21taXRtZW50VHJhbnNhY3Rpb25CdWlsZGVyKHRlc3RBcGlVcmwsIHRlc3RDaGFpbklkKTtcbiAgfSk7XG5cbiAgYWZ0ZXJFYWNoKGZ1bmN0aW9uICgpIHtcbiAgICBzaW5vbi5yZXN0b3JlKCk7XG4gICAgbm9jay5jbGVhbkFsbCgpO1xuICB9KTtcblxuICAvLyA9PT0gQ29tbWl0bWVudCBUeXBlIEVuY29kaW5nIFRlc3RzID09PVxuXG4gIGRlc2NyaWJlKCdlbmNvZGVDb21taXRtZW50VHlwZUZvclNpZ25pbmcnLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ3Nob3VsZCBlbmNvZGUgU1RBS0UgYXMgYSBmbGF0IG51bWJlciAobm90IGFycmF5KScsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IElyeXNDb21taXRtZW50VHJhbnNhY3Rpb25CdWlsZGVyLmVuY29kZUNvbW1pdG1lbnRUeXBlRm9yU2lnbmluZyh7XG4gICAgICAgIHR5cGU6IENvbW1pdG1lbnRUeXBlSWQuU1RBS0UsXG4gICAgICB9KTtcbiAgICAgIHJlc3VsdC5zaG91bGQuZXF1YWwoMSk7XG4gICAgICBBcnJheS5pc0FycmF5KHJlc3VsdCkuc2hvdWxkLmJlLmZhbHNlKCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGVuY29kZSBQTEVER0UgYXMgYSBuZXN0ZWQgYXJyYXkgW3R5cGUsIHBsZWRnZUNvdW50XScsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IElyeXNDb21taXRtZW50VHJhbnNhY3Rpb25CdWlsZGVyLmVuY29kZUNvbW1pdG1lbnRUeXBlRm9yU2lnbmluZyh7XG4gICAgICAgIHR5cGU6IENvbW1pdG1lbnRUeXBlSWQuUExFREdFLFxuICAgICAgICBwbGVkZ2VDb3VudDogNDJuLFxuICAgICAgfSk7XG4gICAgICBBcnJheS5pc0FycmF5KHJlc3VsdCkuc2hvdWxkLmJlLnRydWUoKTtcbiAgICAgIChyZXN1bHQgYXMgYW55W10pLmxlbmd0aC5zaG91bGQuZXF1YWwoMik7XG4gICAgICAocmVzdWx0IGFzIGFueVtdKVswXS5zaG91bGQuZXF1YWwoMik7XG4gICAgICAocmVzdWx0IGFzIGFueVtdKVsxXS5zaG91bGQuZXF1YWwoNDJuKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgLy8gPT09IENvbW1pdG1lbnQgVHlwZSBCcm9hZGNhc3QgRW5jb2RpbmcgVGVzdHMgPT09XG5cbiAgZGVzY3JpYmUoJ2VuY29kZUNvbW1pdG1lbnRUeXBlRm9yQnJvYWRjYXN0JywgZnVuY3Rpb24gKCkge1xuICAgIGl0KCdzaG91bGQgZW5jb2RlIFNUQUtFIGFzIHsgdHlwZTogXCJzdGFrZVwiIH0nLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCByZXN1bHQgPSBJcnlzQ29tbWl0bWVudFRyYW5zYWN0aW9uQnVpbGRlci5lbmNvZGVDb21taXRtZW50VHlwZUZvckJyb2FkY2FzdCh7XG4gICAgICAgIHR5cGU6IENvbW1pdG1lbnRUeXBlSWQuU1RBS0UsXG4gICAgICB9KTtcbiAgICAgIHNob3VsZC5kZWVwRXF1YWwocmVzdWx0LCB7IHR5cGU6ICdzdGFrZScgfSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGVuY29kZSBQTEVER0Ugd2l0aCBwbGVkZ2VDb3VudEJlZm9yZUV4ZWN1dGluZycsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IElyeXNDb21taXRtZW50VHJhbnNhY3Rpb25CdWlsZGVyLmVuY29kZUNvbW1pdG1lbnRUeXBlRm9yQnJvYWRjYXN0KHtcbiAgICAgICAgdHlwZTogQ29tbWl0bWVudFR5cGVJZC5QTEVER0UsXG4gICAgICAgIHBsZWRnZUNvdW50OiA0Mm4sXG4gICAgICB9KTtcbiAgICAgIHNob3VsZC5kZWVwRXF1YWwocmVzdWx0LCB7IHR5cGU6ICdwbGVkZ2UnLCBwbGVkZ2VDb3VudEJlZm9yZUV4ZWN1dGluZzogJzQyJyB9KTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgLy8gPT09IFJMUCBFbmNvZGluZyBUZXN0cyA9PT1cblxuICBkZXNjcmliZSgncmxwRW5jb2RlJywgZnVuY3Rpb24gKCkge1xuICAgIGl0KCdzaG91bGQgUkxQIGVuY29kZSBhIFNUQUtFIHRyYW5zYWN0aW9uIHdpdGggY29ycmVjdCBmaWVsZCBvcmRlcicsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGZpZWxkcyA9IHtcbiAgICAgICAgdmVyc2lvbjogQ09NTUlUTUVOVF9UWF9WRVJTSU9OLFxuICAgICAgICBhbmNob3I6IHRlc3RBbmNob3IsXG4gICAgICAgIHNpZ25lcjogdGVzdFNpZ25lcixcbiAgICAgICAgY29tbWl0bWVudFR5cGU6IHsgdHlwZTogQ29tbWl0bWVudFR5cGVJZC5TVEFLRSBhcyBjb25zdCB9LFxuICAgICAgICBjaGFpbklkOiB0ZXN0Q2hhaW5JZCxcbiAgICAgICAgZmVlOiB0ZXN0RmVlLFxuICAgICAgICB2YWx1ZTogdGVzdFZhbHVlLFxuICAgICAgfTtcblxuICAgICAgY29uc3QgZW5jb2RlZCA9IGJ1aWxkZXIucmxwRW5jb2RlKGZpZWxkcyk7XG4gICAgICBlbmNvZGVkLnNob3VsZC5iZS5pbnN0YW5jZU9mKFVpbnQ4QXJyYXkpO1xuICAgICAgZW5jb2RlZC5sZW5ndGguc2hvdWxkLmJlLmdyZWF0ZXJUaGFuKDApO1xuXG4gICAgICAvLyBUaGUgZW5jb2RlZCBvdXRwdXQgc2hvdWxkIGJlIGRldGVybWluaXN0aWNcbiAgICAgIGNvbnN0IGVuY29kZWQyID0gYnVpbGRlci5ybHBFbmNvZGUoZmllbGRzKTtcbiAgICAgIEJ1ZmZlci5mcm9tKGVuY29kZWQpLmVxdWFscyhCdWZmZXIuZnJvbShlbmNvZGVkMikpLnNob3VsZC5iZS50cnVlKCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIFJMUCBlbmNvZGUgYSBQTEVER0UgdHJhbnNhY3Rpb24gd2l0aCBuZXN0ZWQgYXJyYXkgY29tbWl0bWVudCB0eXBlJywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgZmllbGRzID0ge1xuICAgICAgICB2ZXJzaW9uOiBDT01NSVRNRU5UX1RYX1ZFUlNJT04sXG4gICAgICAgIGFuY2hvcjogdGVzdEFuY2hvcixcbiAgICAgICAgc2lnbmVyOiB0ZXN0U2lnbmVyLFxuICAgICAgICBjb21taXRtZW50VHlwZTogeyB0eXBlOiBDb21taXRtZW50VHlwZUlkLlBMRURHRSBhcyBjb25zdCwgcGxlZGdlQ291bnQ6IDQybiB9LFxuICAgICAgICBjaGFpbklkOiB0ZXN0Q2hhaW5JZCxcbiAgICAgICAgZmVlOiB0ZXN0RmVlLFxuICAgICAgICB2YWx1ZTogdGVzdFZhbHVlLFxuICAgICAgfTtcblxuICAgICAgY29uc3QgZW5jb2RlZCA9IGJ1aWxkZXIucmxwRW5jb2RlKGZpZWxkcyk7XG4gICAgICBlbmNvZGVkLnNob3VsZC5iZS5pbnN0YW5jZU9mKFVpbnQ4QXJyYXkpO1xuICAgICAgZW5jb2RlZC5sZW5ndGguc2hvdWxkLmJlLmdyZWF0ZXJUaGFuKDApO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBwcm9kdWNlIGRpZmZlcmVudCBlbmNvZGluZ3MgZm9yIFNUQUtFIHZzIFBMRURHRScsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHN0YWtlRmllbGRzID0ge1xuICAgICAgICB2ZXJzaW9uOiBDT01NSVRNRU5UX1RYX1ZFUlNJT04sXG4gICAgICAgIGFuY2hvcjogdGVzdEFuY2hvcixcbiAgICAgICAgc2lnbmVyOiB0ZXN0U2lnbmVyLFxuICAgICAgICBjb21taXRtZW50VHlwZTogeyB0eXBlOiBDb21taXRtZW50VHlwZUlkLlNUQUtFIGFzIGNvbnN0IH0sXG4gICAgICAgIGNoYWluSWQ6IHRlc3RDaGFpbklkLFxuICAgICAgICBmZWU6IHRlc3RGZWUsXG4gICAgICAgIHZhbHVlOiB0ZXN0VmFsdWUsXG4gICAgICB9O1xuXG4gICAgICBjb25zdCBwbGVkZ2VGaWVsZHMgPSB7XG4gICAgICAgIC4uLnN0YWtlRmllbGRzLFxuICAgICAgICBjb21taXRtZW50VHlwZTogeyB0eXBlOiBDb21taXRtZW50VHlwZUlkLlBMRURHRSBhcyBjb25zdCwgcGxlZGdlQ291bnQ6IDFuIH0sXG4gICAgICB9O1xuXG4gICAgICBjb25zdCBzdGFrZUVuY29kZWQgPSBidWlsZGVyLnJscEVuY29kZShzdGFrZUZpZWxkcyk7XG4gICAgICBjb25zdCBwbGVkZ2VFbmNvZGVkID0gYnVpbGRlci5ybHBFbmNvZGUocGxlZGdlRmllbGRzKTtcbiAgICAgIEJ1ZmZlci5mcm9tKHN0YWtlRW5jb2RlZCkuZXF1YWxzKEJ1ZmZlci5mcm9tKHBsZWRnZUVuY29kZWQpKS5zaG91bGQuYmUuZmFsc2UoKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgLy8gPT09IFByZWhhc2ggVGVzdHMgPT09XG5cbiAgZGVzY3JpYmUoJ2NvbXB1dGVQcmVoYXNoJywgZnVuY3Rpb24gKCkge1xuICAgIGl0KCdzaG91bGQgcmV0dXJuIGEgMzItYnl0ZSBrZWNjYWsyNTYgaGFzaCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHJscEVuY29kZWQgPSBuZXcgVWludDhBcnJheShbMHhjMF0pOyAvLyBtaW5pbWFsIFJMUFxuICAgICAgY29uc3QgcHJlaGFzaCA9IGJ1aWxkZXIuY29tcHV0ZVByZWhhc2gocmxwRW5jb2RlZCk7XG4gICAgICBwcmVoYXNoLnNob3VsZC5iZS5pbnN0YW5jZU9mKFVpbnQ4QXJyYXkpO1xuICAgICAgcHJlaGFzaC5sZW5ndGguc2hvdWxkLmVxdWFsKDMyKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcHJvZHVjZSBkZXRlcm1pbmlzdGljIG91dHB1dCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHJscEVuY29kZWQgPSBuZXcgVWludDhBcnJheShbMHhjOCwgMHgwMiwgMHgwMSwgMHgwMiwgMHgwM10pO1xuICAgICAgY29uc3QgaGFzaDEgPSBidWlsZGVyLmNvbXB1dGVQcmVoYXNoKHJscEVuY29kZWQpO1xuICAgICAgY29uc3QgaGFzaDIgPSBidWlsZGVyLmNvbXB1dGVQcmVoYXNoKHJscEVuY29kZWQpO1xuICAgICAgQnVmZmVyLmZyb20oaGFzaDEpLmVxdWFscyhCdWZmZXIuZnJvbShoYXNoMikpLnNob3VsZC5iZS50cnVlKCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHByb2R1Y2UgZGlmZmVyZW50IGhhc2hlcyBmb3IgZGlmZmVyZW50IGlucHV0cycsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGlucHV0MSA9IG5ldyBVaW50OEFycmF5KFsweDAxXSk7XG4gICAgICBjb25zdCBpbnB1dDIgPSBuZXcgVWludDhBcnJheShbMHgwMl0pO1xuICAgICAgY29uc3QgaGFzaDEgPSBidWlsZGVyLmNvbXB1dGVQcmVoYXNoKGlucHV0MSk7XG4gICAgICBjb25zdCBoYXNoMiA9IGJ1aWxkZXIuY29tcHV0ZVByZWhhc2goaW5wdXQyKTtcbiAgICAgIEJ1ZmZlci5mcm9tKGhhc2gxKS5lcXVhbHMoQnVmZmVyLmZyb20oaGFzaDIpKS5zaG91bGQuYmUuZmFsc2UoKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgLy8gPT09IEJ1aWxkIFRlc3RzID09PVxuXG4gIGRlc2NyaWJlKCdidWlsZCcsIGZ1bmN0aW9uICgpIHtcbiAgICBpdCgnc2hvdWxkIGJ1aWxkIGEgU1RBS0UgdHJhbnNhY3Rpb24gd2l0aCBtYW51YWxseSBzZXQgYW5jaG9yJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgYnVpbGRlclxuICAgICAgICAuc2V0Q29tbWl0bWVudFR5cGUoeyB0eXBlOiBDb21taXRtZW50VHlwZUlkLlNUQUtFIH0pXG4gICAgICAgIC5zZXRGZWUodGVzdEZlZSlcbiAgICAgICAgLnNldFZhbHVlKHRlc3RWYWx1ZSlcbiAgICAgICAgLnNldFNpZ25lcih0ZXN0U2lnbmVyKVxuICAgICAgICAuc2V0QW5jaG9yKHRlc3RBbmNob3IpO1xuXG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBidWlsZGVyLmJ1aWxkKCk7XG4gICAgICByZXN1bHQucHJlaGFzaC5zaG91bGQuYmUuaW5zdGFuY2VPZihVaW50OEFycmF5KTtcbiAgICAgIHJlc3VsdC5wcmVoYXNoLmxlbmd0aC5zaG91bGQuZXF1YWwoMzIpO1xuICAgICAgcmVzdWx0LnJscEVuY29kZWQuc2hvdWxkLmJlLmluc3RhbmNlT2YoVWludDhBcnJheSk7XG4gICAgICByZXN1bHQucmxwRW5jb2RlZC5sZW5ndGguc2hvdWxkLmJlLmdyZWF0ZXJUaGFuKDApO1xuICAgICAgcmVzdWx0LmZpZWxkcy52ZXJzaW9uLnNob3VsZC5lcXVhbChDT01NSVRNRU5UX1RYX1ZFUlNJT04pO1xuICAgICAgcmVzdWx0LmZpZWxkcy5jaGFpbklkLnNob3VsZC5lcXVhbCh0ZXN0Q2hhaW5JZCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGJ1aWxkIGEgUExFREdFIHRyYW5zYWN0aW9uIHdpdGggbWFudWFsbHkgc2V0IGFuY2hvcicsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGJ1aWxkZXJcbiAgICAgICAgLnNldENvbW1pdG1lbnRUeXBlKHsgdHlwZTogQ29tbWl0bWVudFR5cGVJZC5QTEVER0UsIHBsZWRnZUNvdW50OiA1biB9KVxuICAgICAgICAuc2V0RmVlKHRlc3RGZWUpXG4gICAgICAgIC5zZXRWYWx1ZSh0ZXN0VmFsdWUpXG4gICAgICAgIC5zZXRTaWduZXIodGVzdFNpZ25lcilcbiAgICAgICAgLnNldEFuY2hvcih0ZXN0QW5jaG9yKTtcblxuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgYnVpbGRlci5idWlsZCgpO1xuICAgICAgcmVzdWx0LnByZWhhc2gubGVuZ3RoLnNob3VsZC5lcXVhbCgzMik7XG4gICAgICByZXN1bHQuZmllbGRzLmNvbW1pdG1lbnRUeXBlLnNob3VsZC5kZWVwRXF1YWwoeyB0eXBlOiBDb21taXRtZW50VHlwZUlkLlBMRURHRSwgcGxlZGdlQ291bnQ6IDVuIH0pO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBmZXRjaCBhbmNob3IgZnJvbSBBUEkgd2hlbiBub3QgbWFudWFsbHkgc2V0JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgbW9ja0FuY2hvckJhc2U1OCA9IGVuY29kZUJhc2U1OCh0ZXN0QW5jaG9yKTtcbiAgICAgIGNvbnN0IHNjb3BlID0gbm9jaygnaHR0cHM6Ly90ZXN0bmV0LW5vZGUxLmlyeXMueHl6JylcbiAgICAgICAgLmdldCgnL3YxL2FuY2hvcicpXG4gICAgICAgIC5yZXBseSgyMDAsIHsgYmxvY2tIYXNoOiBtb2NrQW5jaG9yQmFzZTU4IH0pO1xuXG4gICAgICBidWlsZGVyXG4gICAgICAgIC5zZXRDb21taXRtZW50VHlwZSh7IHR5cGU6IENvbW1pdG1lbnRUeXBlSWQuU1RBS0UgfSlcbiAgICAgICAgLnNldEZlZSh0ZXN0RmVlKVxuICAgICAgICAuc2V0VmFsdWUodGVzdFZhbHVlKVxuICAgICAgICAuc2V0U2lnbmVyKHRlc3RTaWduZXIpO1xuXG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBidWlsZGVyLmJ1aWxkKCk7XG4gICAgICByZXN1bHQucHJlaGFzaC5sZW5ndGguc2hvdWxkLmVxdWFsKDMyKTtcbiAgICAgIEJ1ZmZlci5mcm9tKHJlc3VsdC5maWVsZHMuYW5jaG9yKS5lcXVhbHMoQnVmZmVyLmZyb20odGVzdEFuY2hvcikpLnNob3VsZC5iZS50cnVlKCk7XG4gICAgICBzY29wZS5kb25lKCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHRocm93IGlmIGNvbW1pdG1lbnQgdHlwZSBpcyBub3Qgc2V0JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgYnVpbGRlci5zZXRGZWUodGVzdEZlZSkuc2V0VmFsdWUodGVzdFZhbHVlKS5zZXRTaWduZXIodGVzdFNpZ25lcikuc2V0QW5jaG9yKHRlc3RBbmNob3IpO1xuXG4gICAgICBhd2FpdCBidWlsZGVyLmJ1aWxkKCkuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgnQ29tbWl0bWVudCB0eXBlIGlzIHJlcXVpcmVkJyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHRocm93IGlmIGZlZSBpcyBub3Qgc2V0JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgYnVpbGRlclxuICAgICAgICAuc2V0Q29tbWl0bWVudFR5cGUoeyB0eXBlOiBDb21taXRtZW50VHlwZUlkLlNUQUtFIH0pXG4gICAgICAgIC5zZXRWYWx1ZSh0ZXN0VmFsdWUpXG4gICAgICAgIC5zZXRTaWduZXIodGVzdFNpZ25lcilcbiAgICAgICAgLnNldEFuY2hvcih0ZXN0QW5jaG9yKTtcblxuICAgICAgYXdhaXQgYnVpbGRlci5idWlsZCgpLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoJ0ZlZSBpcyByZXF1aXJlZCcpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0aHJvdyBpZiB2YWx1ZSBpcyBub3Qgc2V0JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgYnVpbGRlclxuICAgICAgICAuc2V0Q29tbWl0bWVudFR5cGUoeyB0eXBlOiBDb21taXRtZW50VHlwZUlkLlNUQUtFIH0pXG4gICAgICAgIC5zZXRGZWUodGVzdEZlZSlcbiAgICAgICAgLnNldFNpZ25lcih0ZXN0U2lnbmVyKVxuICAgICAgICAuc2V0QW5jaG9yKHRlc3RBbmNob3IpO1xuXG4gICAgICBhd2FpdCBidWlsZGVyLmJ1aWxkKCkuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgnVmFsdWUgaXMgcmVxdWlyZWQnKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdGhyb3cgaWYgc2lnbmVyIGlzIG5vdCBzZXQnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBidWlsZGVyXG4gICAgICAgIC5zZXRDb21taXRtZW50VHlwZSh7IHR5cGU6IENvbW1pdG1lbnRUeXBlSWQuU1RBS0UgfSlcbiAgICAgICAgLnNldEZlZSh0ZXN0RmVlKVxuICAgICAgICAuc2V0VmFsdWUodGVzdFZhbHVlKVxuICAgICAgICAuc2V0QW5jaG9yKHRlc3RBbmNob3IpO1xuXG4gICAgICBhd2FpdCBidWlsZGVyLmJ1aWxkKCkuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgnU2lnbmVyIGlzIHJlcXVpcmVkJyk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIC8vID09PSBWYWxpZGF0aW9uIFRlc3RzID09PVxuXG4gIGRlc2NyaWJlKCdpbnB1dCB2YWxpZGF0aW9uJywgZnVuY3Rpb24gKCkge1xuICAgIGl0KCdzaG91bGQgcmVqZWN0IHNpZ25lciB3aXRoIHdyb25nIGxlbmd0aCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgICgoKSA9PiBidWlsZGVyLnNldFNpZ25lcihuZXcgVWludDhBcnJheSgxOSkpKS5zaG91bGQudGhyb3coL1NpZ25lciBtdXN0IGJlIDIwIGJ5dGVzLyk7XG4gICAgICAoKCkgPT4gYnVpbGRlci5zZXRTaWduZXIobmV3IFVpbnQ4QXJyYXkoMjEpKSkuc2hvdWxkLnRocm93KC9TaWduZXIgbXVzdCBiZSAyMCBieXRlcy8pO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCByZWplY3QgYW5jaG9yIHdpdGggd3JvbmcgbGVuZ3RoJywgZnVuY3Rpb24gKCkge1xuICAgICAgKCgpID0+IGJ1aWxkZXIuc2V0QW5jaG9yKG5ldyBVaW50OEFycmF5KDMxKSkpLnNob3VsZC50aHJvdygvQW5jaG9yIG11c3QgYmUgMzIgYnl0ZXMvKTtcbiAgICAgICgoKSA9PiBidWlsZGVyLnNldEFuY2hvcihuZXcgVWludDhBcnJheSgzMykpKS5zaG91bGQudGhyb3coL0FuY2hvciBtdXN0IGJlIDMyIGJ5dGVzLyk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIC8vID09PSBUcmFuc2FjdGlvbiBJRCBUZXN0cyA9PT1cblxuICBkZXNjcmliZSgnY29tcHV0ZVR4SWQnLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ3Nob3VsZCBjb21wdXRlIGJhc2U1OChrZWNjYWsyNTYoc2lnbmF0dXJlKSknLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBmYWtlU2lnbmF0dXJlID0gbmV3IFVpbnQ4QXJyYXkoNjUpLmZpbGwoMHhhYik7XG4gICAgICBjb25zdCB0eElkID0gSXJ5c0NvbW1pdG1lbnRUcmFuc2FjdGlvbkJ1aWxkZXIuY29tcHV0ZVR4SWQoZmFrZVNpZ25hdHVyZSk7XG4gICAgICB0eElkLnNob3VsZC5iZS5hLlN0cmluZygpO1xuICAgICAgdHhJZC5sZW5ndGguc2hvdWxkLmJlLmdyZWF0ZXJUaGFuKDApO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBwcm9kdWNlIGRldGVybWluaXN0aWMgb3V0cHV0JywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgc2lnID0gbmV3IFVpbnQ4QXJyYXkoNjUpLmZpbGwoMHhjZCk7XG4gICAgICBjb25zdCBpZDEgPSBJcnlzQ29tbWl0bWVudFRyYW5zYWN0aW9uQnVpbGRlci5jb21wdXRlVHhJZChzaWcpO1xuICAgICAgY29uc3QgaWQyID0gSXJ5c0NvbW1pdG1lbnRUcmFuc2FjdGlvbkJ1aWxkZXIuY29tcHV0ZVR4SWQoc2lnKTtcbiAgICAgIGlkMS5zaG91bGQuZXF1YWwoaWQyKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmVqZWN0IG5vbi02NS1ieXRlIHNpZ25hdHVyZXMnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAoKCkgPT4gSXJ5c0NvbW1pdG1lbnRUcmFuc2FjdGlvbkJ1aWxkZXIuY29tcHV0ZVR4SWQobmV3IFVpbnQ4QXJyYXkoNjQpKSkuc2hvdWxkLnRocm93KFxuICAgICAgICAvU2lnbmF0dXJlIG11c3QgYmUgNjUgYnl0ZXMvXG4gICAgICApO1xuICAgIH0pO1xuICB9KTtcblxuICAvLyA9PT0gQnJvYWRjYXN0IFBheWxvYWQgVGVzdHMgPT09XG5cbiAgZGVzY3JpYmUoJ2NyZWF0ZUJyb2FkY2FzdFBheWxvYWQnLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ3Nob3VsZCBjcmVhdGUgdmFsaWQgSlNPTiBwYXlsb2FkIGZvciBTVEFLRScsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGZpZWxkcyA9IHtcbiAgICAgICAgdmVyc2lvbjogQ09NTUlUTUVOVF9UWF9WRVJTSU9OLFxuICAgICAgICBhbmNob3I6IHRlc3RBbmNob3IsXG4gICAgICAgIHNpZ25lcjogdGVzdFNpZ25lcixcbiAgICAgICAgY29tbWl0bWVudFR5cGU6IHsgdHlwZTogQ29tbWl0bWVudFR5cGVJZC5TVEFLRSBhcyBjb25zdCB9LFxuICAgICAgICBjaGFpbklkOiB0ZXN0Q2hhaW5JZCxcbiAgICAgICAgZmVlOiB0ZXN0RmVlLFxuICAgICAgICB2YWx1ZTogdGVzdFZhbHVlLFxuICAgICAgfTtcbiAgICAgIGNvbnN0IHNpZ25hdHVyZSA9IG5ldyBVaW50OEFycmF5KDY1KS5maWxsKDB4YWIpO1xuXG4gICAgICBjb25zdCBwYXlsb2FkID0gSXJ5c0NvbW1pdG1lbnRUcmFuc2FjdGlvbkJ1aWxkZXIuY3JlYXRlQnJvYWRjYXN0UGF5bG9hZChmaWVsZHMsIHNpZ25hdHVyZSk7XG5cbiAgICAgIHBheWxvYWQudmVyc2lvbi5zaG91bGQuZXF1YWwoMik7XG4gICAgICBwYXlsb2FkLmFuY2hvci5zaG91bGQuYmUuYS5TdHJpbmcoKTtcbiAgICAgIHBheWxvYWQuc2lnbmVyLnNob3VsZC5iZS5hLlN0cmluZygpO1xuICAgICAgc2hvdWxkLmRlZXBFcXVhbChwYXlsb2FkLmNvbW1pdG1lbnRUeXBlLCB7IHR5cGU6ICdzdGFrZScgfSk7XG4gICAgICBwYXlsb2FkLmNoYWluSWQuc2hvdWxkLmVxdWFsKCcxMjcwJyk7XG4gICAgICBwYXlsb2FkLmZlZS5zaG91bGQuZXF1YWwoJzEwMDAnKTtcbiAgICAgIHBheWxvYWQudmFsdWUuc2hvdWxkLmVxdWFsKCc1MDAwJyk7XG4gICAgICBwYXlsb2FkLmlkLnNob3VsZC5iZS5hLlN0cmluZygpO1xuICAgICAgcGF5bG9hZC5zaWduYXR1cmUuc2hvdWxkLmJlLmEuU3RyaW5nKCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGNyZWF0ZSB2YWxpZCBKU09OIHBheWxvYWQgZm9yIFBMRURHRSB3aXRoIHBsZWRnZUNvdW50QmVmb3JlRXhlY3V0aW5nJywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgZmllbGRzID0ge1xuICAgICAgICB2ZXJzaW9uOiBDT01NSVRNRU5UX1RYX1ZFUlNJT04sXG4gICAgICAgIGFuY2hvcjogdGVzdEFuY2hvcixcbiAgICAgICAgc2lnbmVyOiB0ZXN0U2lnbmVyLFxuICAgICAgICBjb21taXRtZW50VHlwZTogeyB0eXBlOiBDb21taXRtZW50VHlwZUlkLlBMRURHRSBhcyBjb25zdCwgcGxlZGdlQ291bnQ6IDQybiB9LFxuICAgICAgICBjaGFpbklkOiB0ZXN0Q2hhaW5JZCxcbiAgICAgICAgZmVlOiB0ZXN0RmVlLFxuICAgICAgICB2YWx1ZTogdGVzdFZhbHVlLFxuICAgICAgfTtcbiAgICAgIGNvbnN0IHNpZ25hdHVyZSA9IG5ldyBVaW50OEFycmF5KDY1KS5maWxsKDB4Y2QpO1xuXG4gICAgICBjb25zdCBwYXlsb2FkID0gSXJ5c0NvbW1pdG1lbnRUcmFuc2FjdGlvbkJ1aWxkZXIuY3JlYXRlQnJvYWRjYXN0UGF5bG9hZChmaWVsZHMsIHNpZ25hdHVyZSk7XG5cbiAgICAgIHNob3VsZC5kZWVwRXF1YWwocGF5bG9hZC5jb21taXRtZW50VHlwZSwgeyB0eXBlOiAncGxlZGdlJywgcGxlZGdlQ291bnRCZWZvcmVFeGVjdXRpbmc6ICc0MicgfSk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIC8vID09PSBLbm93bi1Hb29kIFRlc3QgVmVjdG9ycyAoZnJvbSBzdWNjZXNzZnVsIHRlc3RuZXQgdHJhbnNhY3Rpb25zKSA9PT1cbiAgLy9cbiAgLy8gVGhlc2UgdmVjdG9ycyB3ZXJlIGNhcHR1cmVkIGZyb20gYWN0dWFsIFNUQUtFIGFuZCBQTEVER0UgdHJhbnNhY3Rpb25zXG4gIC8vIHN1Ym1pdHRlZCB0byB0aGUgSXJ5cyB0ZXN0bmV0IHVzaW5nIGNvaW5zLXNhbmRib3gvZXRoL2lyeXMvc3Rha2UudHMuXG4gIC8vIFRoZXkgdmVyaWZ5IG91ciBSTFAgZW5jb2RpbmcgKyBwcmVoYXNoIG1hdGNoIHRoZSBwcm90b2NvbCBleGFjdGx5LlxuXG4gIGRlc2NyaWJlKCdrbm93bi1nb29kIHRlc3QgdmVjdG9ycycsIGZ1bmN0aW9uICgpIHtcbiAgICBjb25zdCB0ZXN0bmV0U2lnbmVyID0gJzB4MjJmOUM5ZjE4NDVEOWI2QzIyYjk2RWYzNUU0NkUyNjVhQzRBZjMwYyc7XG4gICAgY29uc3QgdGVzdG5ldFNpZ25lckJ5dGVzID0gVWludDhBcnJheS5mcm9tKEJ1ZmZlci5mcm9tKHRlc3RuZXRTaWduZXIuc2xpY2UoMiksICdoZXgnKSk7XG4gICAgY29uc3QgdGVzdG5ldENoYWluSWQgPSAxMjcwbjtcblxuICAgIGl0KCdzaG91bGQgbWF0Y2gga25vd24gU1RBS0UgUkxQIGVuY29kaW5nIGFuZCBwcmVoYXNoJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgLy8gRnJvbSBzdGFrZV9wbGVkZ2UudHh0IC0gc3VjY2Vzc2Z1bCBTVEFLRSB0cmFuc2FjdGlvblxuICAgICAgLy8gVFggSUQ6IDRYaFVUcmtoeHIxUm1VUWJYVVZSd2JOWjZwS0VZckFWbzV5bWRNWTQxZlM1XG4gICAgICBjb25zdCBhbmNob3JCYXNlNTggPSAnOEpSMnJENURlam5NMk51VlNxcUdhNjhkZnllNlpLcnVUOXJkaDJDbjRCOHknO1xuICAgICAgY29uc3QgYW5jaG9yQnl0ZXMgPSBkZWNvZGVCYXNlNTgoYW5jaG9yQmFzZTU4KTtcblxuICAgICAgY29uc3Qgc3Rha2VCdWlsZGVyID0gbmV3IElyeXNDb21taXRtZW50VHJhbnNhY3Rpb25CdWlsZGVyKHRlc3RBcGlVcmwsIHRlc3RuZXRDaGFpbklkKTtcblxuICAgICAgc3Rha2VCdWlsZGVyXG4gICAgICAgIC5zZXRDb21taXRtZW50VHlwZSh7IHR5cGU6IENvbW1pdG1lbnRUeXBlSWQuU1RBS0UgfSlcbiAgICAgICAgLnNldEZlZSgxMDBuKVxuICAgICAgICAuc2V0VmFsdWUoMjAwMDAwMDAwMDAwMDAwMDAwMDAwMDBuKSAvLyAyMDAwMCBJUllTXG4gICAgICAgIC5zZXRTaWduZXIodGVzdG5ldFNpZ25lckJ5dGVzKVxuICAgICAgICAuc2V0QW5jaG9yKGFuY2hvckJ5dGVzKTtcblxuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgc3Rha2VCdWlsZGVyLmJ1aWxkKCk7XG5cbiAgICAgIGNvbnN0IGV4cGVjdGVkUmxwID1cbiAgICAgICAgJzB4Zjg0NzAyYTA2Yzc3ZGFlYmMyZGI0ZTU3MmU0ZjI5Njk4M2QxNDEzZmMxMGQ0ODUyZTBmYWJmZGI4MzIzYzljNjlhMmI4NScgK1xuICAgICAgICAnOWU5NDIyZjljOWYxODQ1ZDliNmMyMmI5NmVmMzVlNDZlMjY1YWM0YWYzMGMwMTgyMDRmNjY0OGEwNDNjMzNjMTkzNzU2NDgwMDAwMCc7XG4gICAgICBjb25zdCBhY3R1YWxSbHAgPSAnMHgnICsgQnVmZmVyLmZyb20ocmVzdWx0LnJscEVuY29kZWQpLnRvU3RyaW5nKCdoZXgnKTtcbiAgICAgIGFjdHVhbFJscC5zaG91bGQuZXF1YWwoZXhwZWN0ZWRSbHApO1xuXG4gICAgICBjb25zdCBleHBlY3RlZFByZWhhc2ggPSAnMHhlNmZlNTc4MTBjMTI3ODVlM2NlNWZhNjRlMmViNGRhMTIwYjg5ZWMwZTQ2OTIxMzcxNTkxNmFiZjM2MzU4ZDAxJztcbiAgICAgIGNvbnN0IGFjdHVhbFByZWhhc2ggPSAnMHgnICsgQnVmZmVyLmZyb20ocmVzdWx0LnByZWhhc2gpLnRvU3RyaW5nKCdoZXgnKTtcbiAgICAgIGFjdHVhbFByZWhhc2guc2hvdWxkLmVxdWFsKGV4cGVjdGVkUHJlaGFzaCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIG1hdGNoIGtub3duIFBMRURHRSBSTFAgZW5jb2RpbmcgYW5kIHByZWhhc2gnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAvLyBGcm9tIHN0YWtlX3BsZWRnZS50eHQgLSBzdWNjZXNzZnVsIFBMRURHRSB0cmFuc2FjdGlvblxuICAgICAgLy8gVFggSUQ6IEVzZGllc0M1OFM4ZWVZMVNITTVqVGZ5ODR6WXhGTVVkS0Y4OVl0cjZQeU5iXG4gICAgICBjb25zdCBhbmNob3JCYXNlNTggPSAnalVTaEpQVUFDVzRieFVTdlpqaTY1UTk2TWFxS0RoN0FGRkFMS25rYXBCbic7XG4gICAgICBjb25zdCBhbmNob3JCeXRlcyA9IGRlY29kZUJhc2U1OChhbmNob3JCYXNlNTgpO1xuXG4gICAgICBjb25zdCBwbGVkZ2VCdWlsZGVyID0gbmV3IElyeXNDb21taXRtZW50VHJhbnNhY3Rpb25CdWlsZGVyKHRlc3RBcGlVcmwsIHRlc3RuZXRDaGFpbklkKTtcblxuICAgICAgcGxlZGdlQnVpbGRlclxuICAgICAgICAuc2V0Q29tbWl0bWVudFR5cGUoeyB0eXBlOiBDb21taXRtZW50VHlwZUlkLlBMRURHRSwgcGxlZGdlQ291bnQ6IDBuIH0pXG4gICAgICAgIC5zZXRGZWUoMTAwbilcbiAgICAgICAgLnNldFZhbHVlKDk1MDAwMDAwMDAwMDAwMDAwMDAwMG4pIC8vIDk1MCBJUllTXG4gICAgICAgIC5zZXRTaWduZXIodGVzdG5ldFNpZ25lckJ5dGVzKVxuICAgICAgICAuc2V0QW5jaG9yKGFuY2hvckJ5dGVzKTtcblxuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgcGxlZGdlQnVpbGRlci5idWlsZCgpO1xuXG4gICAgICBjb25zdCBleHBlY3RlZFJscCA9XG4gICAgICAgICcweGY4NDgwMmEwMGFlMTZjODQ3NmJiZGUyZjI4YjJlNDYyOWQzOTNkZmU2ZmE3YWZmY2YwYTBjNDY1NGY4MjQ2YTliYTc4OTcwNTk0JyArXG4gICAgICAgICcyMmY5YzlmMTg0NWQ5YjZjMjJiOTZlZjM1ZTQ2ZTI2NWFjNGFmMzBjYzIwMjgwODIwNGY2NjQ4OTMzN2ZlNWZlYWYyZDE4MDAwMCc7XG4gICAgICBjb25zdCBhY3R1YWxSbHAgPSAnMHgnICsgQnVmZmVyLmZyb20ocmVzdWx0LnJscEVuY29kZWQpLnRvU3RyaW5nKCdoZXgnKTtcbiAgICAgIGFjdHVhbFJscC5zaG91bGQuZXF1YWwoZXhwZWN0ZWRSbHApO1xuXG4gICAgICBjb25zdCBleHBlY3RlZFByZWhhc2ggPSAnMHhmZTA3YzJmM2M2ZTUwZDljOWUyY2ZmNTdmNmQ3MDE1YjQ1MjhmNDI1YjYxMzJmNTY3ZTI2YmJhNzQ1MjI4MTAyJztcbiAgICAgIGNvbnN0IGFjdHVhbFByZWhhc2ggPSAnMHgnICsgQnVmZmVyLmZyb20ocmVzdWx0LnByZWhhc2gpLnRvU3RyaW5nKCdoZXgnKTtcbiAgICAgIGFjdHVhbFByZWhhc2guc2hvdWxkLmVxdWFsKGV4cGVjdGVkUHJlaGFzaCk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIC8vID09PSBFZGdlIENhc2UgVGVzdHMgPT09XG5cbiAgZGVzY3JpYmUoJ2VkZ2UgY2FzZXMnLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ3Nob3VsZCBoYW5kbGUgemVybyBmZWUgYW5kIHZhbHVlJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgYnVpbGRlclxuICAgICAgICAuc2V0Q29tbWl0bWVudFR5cGUoeyB0eXBlOiBDb21taXRtZW50VHlwZUlkLlNUQUtFIH0pXG4gICAgICAgIC5zZXRGZWUoMG4pXG4gICAgICAgIC5zZXRWYWx1ZSgwbilcbiAgICAgICAgLnNldFNpZ25lcih0ZXN0U2lnbmVyKVxuICAgICAgICAuc2V0QW5jaG9yKHRlc3RBbmNob3IpO1xuXG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBidWlsZGVyLmJ1aWxkKCk7XG4gICAgICByZXN1bHQucHJlaGFzaC5sZW5ndGguc2hvdWxkLmVxdWFsKDMyKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgLy8gPT09IEFuY2hvciBGZXRjaCBUZXN0cyA9PT1cblxuICBkZXNjcmliZSgnZmV0Y2hBbmNob3InLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ3Nob3VsZCBmZXRjaCBhbmQgZGVjb2RlIGJhc2U1OCBhbmNob3IgZnJvbSBBUEknLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBtb2NrQW5jaG9yQmFzZTU4ID0gZW5jb2RlQmFzZTU4KHRlc3RBbmNob3IpO1xuICAgICAgY29uc3Qgc2NvcGUgPSBub2NrKCdodHRwczovL3Rlc3RuZXQtbm9kZTEuaXJ5cy54eXonKVxuICAgICAgICAuZ2V0KCcvdjEvYW5jaG9yJylcbiAgICAgICAgLnJlcGx5KDIwMCwgeyBibG9ja0hhc2g6IG1vY2tBbmNob3JCYXNlNTggfSk7XG5cbiAgICAgIGNvbnN0IGFuY2hvciA9IGF3YWl0IGJ1aWxkZXIuZmV0Y2hBbmNob3IoKTtcbiAgICAgIGFuY2hvci5zaG91bGQuYmUuaW5zdGFuY2VPZihVaW50OEFycmF5KTtcbiAgICAgIGFuY2hvci5sZW5ndGguc2hvdWxkLmVxdWFsKDMyKTtcbiAgICAgIEJ1ZmZlci5mcm9tKGFuY2hvcikuZXF1YWxzKEJ1ZmZlci5mcm9tKHRlc3RBbmNob3IpKS5zaG91bGQuYmUudHJ1ZSgpO1xuICAgICAgc2NvcGUuZG9uZSgpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0aHJvdyBvbiBub24tMjAwIHJlc3BvbnNlJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgc2NvcGUgPSBub2NrKCdodHRwczovL3Rlc3RuZXQtbm9kZTEuaXJ5cy54eXonKS5nZXQoJy92MS9hbmNob3InKS5yZXBseSg1MDAsICdJbnRlcm5hbCBTZXJ2ZXIgRXJyb3InKTtcblxuICAgICAgYXdhaXQgYnVpbGRlci5mZXRjaEFuY2hvcigpLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoL0ludGVybmFsIFNlcnZlciBFcnJvci8pO1xuICAgICAgc2NvcGUuZG9uZSgpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0aHJvdyBpZiBhbmNob3IgZGVjb2RlcyB0byB3cm9uZyBsZW5ndGgnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBzaG9ydEFuY2hvciA9IGVuY29kZUJhc2U1OChuZXcgVWludDhBcnJheSgxNikpOyAvLyAxNiBieXRlcyBpbnN0ZWFkIG9mIDMyXG4gICAgICBjb25zdCBzY29wZSA9IG5vY2soJ2h0dHBzOi8vdGVzdG5ldC1ub2RlMS5pcnlzLnh5eicpLmdldCgnL3YxL2FuY2hvcicpLnJlcGx5KDIwMCwgeyBibG9ja0hhc2g6IHNob3J0QW5jaG9yIH0pO1xuXG4gICAgICBhd2FpdCBidWlsZGVyLmZldGNoQW5jaG9yKCkuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgvRXhwZWN0ZWQgMzIgYnl0ZXMvKTtcbiAgICAgIHNjb3BlLmRvbmUoKTtcbiAgICB9KTtcbiAgfSk7XG59KTtcbiJdfQ==
|