@bitgo/sdk-coin-ton 3.18.0 → 3.19.1
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/lib/explainTransactionWasm.d.ts +22 -0
- package/dist/src/lib/explainTransactionWasm.d.ts.map +1 -0
- package/dist/src/lib/explainTransactionWasm.js +61 -0
- package/dist/src/lib/index.d.ts +1 -0
- package/dist/src/lib/index.d.ts.map +1 -1
- package/dist/src/lib/index.js +4 -2
- package/dist/src/lib/utils.d.ts.map +1 -1
- package/dist/src/lib/utils.js +3 -2
- package/dist/src/ton.d.ts.map +1 -1
- package/dist/src/ton.js +45 -1
- package/dist/test/unit/explainTransactionWasm.d.ts +2 -0
- package/dist/test/unit/explainTransactionWasm.d.ts.map +1 -0
- package/dist/test/unit/explainTransactionWasm.js +147 -0
- package/dist/test/unit/ton.js +2 -2
- package/dist/test/unit/wasmCrossCompatibility.d.ts +2 -0
- package/dist/test/unit/wasmCrossCompatibility.d.ts.map +1 -0
- package/dist/test/unit/wasmCrossCompatibility.js +176 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +9 -8
|
@@ -0,0 +1,176 @@
|
|
|
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 statics_1 = require("@bitgo/statics");
|
|
41
|
+
const sdk_core_1 = require("@bitgo/sdk-core");
|
|
42
|
+
const wasm_ton_1 = require("@bitgo/wasm-ton");
|
|
43
|
+
const transactionBuilderFactory_1 = require("../../src/lib/transactionBuilderFactory");
|
|
44
|
+
const testData = __importStar(require("../resources/ton"));
|
|
45
|
+
/**
|
|
46
|
+
* Cross-compatibility tests between WASM (@bitgo/wasm-ton) and legacy
|
|
47
|
+
* (tonweb-based) transaction building/parsing for TON.
|
|
48
|
+
*
|
|
49
|
+
* Direction 1: WASM parses legacy-built transactions (covered by explainTransactionWasm.ts)
|
|
50
|
+
* Direction 2: Legacy parses WASM-built transactions (this file)
|
|
51
|
+
*/
|
|
52
|
+
describe('TON WASM Cross-Compatibility', function () {
|
|
53
|
+
const coin = statics_1.coins.get('tton');
|
|
54
|
+
const factory = new transactionBuilderFactory_1.TransactionBuilderFactory(coin);
|
|
55
|
+
// Use sender from test fixtures
|
|
56
|
+
const senderAddress = testData.sender.address;
|
|
57
|
+
const senderPublicKey = testData.sender.publicKey;
|
|
58
|
+
const recipientAddress = testData.addresses.validAddresses[0];
|
|
59
|
+
function createWasmContext(overrides = {}) {
|
|
60
|
+
return {
|
|
61
|
+
sender: senderAddress,
|
|
62
|
+
seqno: 6,
|
|
63
|
+
expireTime: 1695997582n,
|
|
64
|
+
publicKey: senderPublicKey,
|
|
65
|
+
...overrides,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
// =========================================================================
|
|
69
|
+
// WASM -> Legacy: Legacy can parse WASM-built transactions
|
|
70
|
+
// =========================================================================
|
|
71
|
+
describe('Legacy parses WASM-built transactions', function () {
|
|
72
|
+
it('should parse a WASM-built payment transaction via legacy factory.from()', async function () {
|
|
73
|
+
const amount = 10000000n; // 0.01 TON
|
|
74
|
+
const memo = 'test';
|
|
75
|
+
// Build with WASM
|
|
76
|
+
const wasmTx = (0, wasm_ton_1.buildTransaction)({
|
|
77
|
+
type: 'payment',
|
|
78
|
+
to: recipientAddress,
|
|
79
|
+
amount,
|
|
80
|
+
bounceable: false,
|
|
81
|
+
memo,
|
|
82
|
+
}, createWasmContext());
|
|
83
|
+
// Convert to base64 (the format legacy expects)
|
|
84
|
+
const bocBytes = wasmTx.toBroadcastFormat();
|
|
85
|
+
const base64Tx = Buffer.from(bocBytes).toString('base64');
|
|
86
|
+
// Parse with legacy
|
|
87
|
+
const legacyBuilder = factory.from(base64Tx);
|
|
88
|
+
const legacyTx = await legacyBuilder.build();
|
|
89
|
+
const json = legacyTx.toJson();
|
|
90
|
+
// Verify the legacy builder can extract the correct fields
|
|
91
|
+
legacyTx.type.should.equal(sdk_core_1.TransactionType.Send);
|
|
92
|
+
json.seqno.should.equal(6);
|
|
93
|
+
json.expirationTime.should.equal(1695997582);
|
|
94
|
+
json.amount.should.equal(amount.toString());
|
|
95
|
+
should_1.default.exist(json.sender);
|
|
96
|
+
should_1.default.exist(json.destination);
|
|
97
|
+
});
|
|
98
|
+
it('should parse a WASM-built payment without memo via legacy', async function () {
|
|
99
|
+
const amount = 50000000n; // 0.05 TON
|
|
100
|
+
const wasmTx = (0, wasm_ton_1.buildTransaction)({
|
|
101
|
+
type: 'payment',
|
|
102
|
+
to: recipientAddress,
|
|
103
|
+
amount,
|
|
104
|
+
bounceable: false,
|
|
105
|
+
}, createWasmContext({ seqno: 10, expireTime: 1700000000n }));
|
|
106
|
+
const base64Tx = Buffer.from(wasmTx.toBroadcastFormat()).toString('base64');
|
|
107
|
+
const legacyBuilder = factory.from(base64Tx);
|
|
108
|
+
const legacyTx = await legacyBuilder.build();
|
|
109
|
+
const json = legacyTx.toJson();
|
|
110
|
+
legacyTx.type.should.equal(sdk_core_1.TransactionType.Send);
|
|
111
|
+
json.seqno.should.equal(10);
|
|
112
|
+
json.expirationTime.should.equal(1700000000);
|
|
113
|
+
json.amount.should.equal(amount.toString());
|
|
114
|
+
});
|
|
115
|
+
it('should round-trip: WASM build -> legacy parse -> legacy build -> WASM parse', async function () {
|
|
116
|
+
const amount = 123400000n;
|
|
117
|
+
const memo = 'hello';
|
|
118
|
+
const wasmTx = (0, wasm_ton_1.buildTransaction)({
|
|
119
|
+
type: 'payment',
|
|
120
|
+
to: recipientAddress,
|
|
121
|
+
amount,
|
|
122
|
+
bounceable: false,
|
|
123
|
+
memo,
|
|
124
|
+
}, createWasmContext({ seqno: 3, expireTime: 1234567890n }));
|
|
125
|
+
const base64Tx = Buffer.from(wasmTx.toBroadcastFormat()).toString('base64');
|
|
126
|
+
// Parse with legacy
|
|
127
|
+
const legacyBuilder = factory.from(base64Tx);
|
|
128
|
+
const legacyTx = await legacyBuilder.build();
|
|
129
|
+
// Rebuild with legacy should produce valid base64
|
|
130
|
+
const rebuiltBase64 = legacyTx.toBroadcastFormat();
|
|
131
|
+
// Parse the rebuilt transaction with WASM to confirm fields match
|
|
132
|
+
const wasmParsed = (0, wasm_ton_1.parseTransaction)(wasm_ton_1.Transaction.fromBytes(Buffer.from(rebuiltBase64, 'base64')));
|
|
133
|
+
wasmParsed.transactionType.should.equal('Transfer');
|
|
134
|
+
wasmParsed.seqno.should.equal(3);
|
|
135
|
+
wasmParsed.sendActions.length.should.be.greaterThan(0);
|
|
136
|
+
String(wasmParsed.sendActions[0].amount).should.equal(amount.toString());
|
|
137
|
+
});
|
|
138
|
+
it('should parse a WASM-built bounceable payment via legacy', async function () {
|
|
139
|
+
const amount = 10000000n;
|
|
140
|
+
const wasmTx = (0, wasm_ton_1.buildTransaction)({
|
|
141
|
+
type: 'payment',
|
|
142
|
+
to: recipientAddress,
|
|
143
|
+
amount,
|
|
144
|
+
bounceable: true,
|
|
145
|
+
}, createWasmContext());
|
|
146
|
+
const base64Tx = Buffer.from(wasmTx.toBroadcastFormat()).toString('base64');
|
|
147
|
+
const legacyBuilder = factory.from(base64Tx);
|
|
148
|
+
const legacyTx = await legacyBuilder.build();
|
|
149
|
+
const json = legacyTx.toJson();
|
|
150
|
+
legacyTx.type.should.equal(sdk_core_1.TransactionType.Send);
|
|
151
|
+
json.amount.should.equal(amount.toString());
|
|
152
|
+
});
|
|
153
|
+
});
|
|
154
|
+
// =========================================================================
|
|
155
|
+
// Both WASM and legacy agree on signed fixture data
|
|
156
|
+
// =========================================================================
|
|
157
|
+
describe('Both WASM and legacy agree on signed fixture data', function () {
|
|
158
|
+
it('should produce matching fields for signedSendTransaction', async function () {
|
|
159
|
+
const txBase64 = testData.signedSendTransaction.tx;
|
|
160
|
+
// Parse with WASM
|
|
161
|
+
const wasmTx = wasm_ton_1.Transaction.fromBytes(Buffer.from(txBase64, 'base64'));
|
|
162
|
+
const wasmParsed = (0, wasm_ton_1.parseTransaction)(wasmTx);
|
|
163
|
+
// Parse with legacy
|
|
164
|
+
const legacyBuilder = factory.from(txBase64);
|
|
165
|
+
const legacyTx = await legacyBuilder.build();
|
|
166
|
+
const json = legacyTx.toJson();
|
|
167
|
+
// Both should agree on core fields
|
|
168
|
+
wasmParsed.transactionType.should.equal('Transfer');
|
|
169
|
+
legacyTx.type.should.equal(sdk_core_1.TransactionType.Send);
|
|
170
|
+
wasmParsed.seqno.should.equal(json.seqno);
|
|
171
|
+
wasmParsed.sendActions.length.should.be.greaterThan(0);
|
|
172
|
+
String(wasmParsed.sendActions[0].amount).should.equal(json.amount);
|
|
173
|
+
});
|
|
174
|
+
});
|
|
175
|
+
});
|
|
176
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2FzbUNyb3NzQ29tcGF0aWJpbGl0eS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3Rlc3QvdW5pdC93YXNtQ3Jvc3NDb21wYXRpYmlsaXR5LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsb0RBQTRCO0FBQzVCLDRDQUF1QztBQUN2Qyw4Q0FBa0Q7QUFDbEQsOENBT3lCO0FBQ3pCLHVGQUFvRjtBQUNwRiwyREFBNkM7QUFFN0M7Ozs7OztHQU1HO0FBQ0gsUUFBUSxDQUFDLDhCQUE4QixFQUFFO0lBQ3ZDLE1BQU0sSUFBSSxHQUFHLGVBQUssQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDL0IsTUFBTSxPQUFPLEdBQUcsSUFBSSxxREFBeUIsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUVwRCxnQ0FBZ0M7SUFDaEMsTUFBTSxhQUFhLEdBQUcsUUFBUSxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUM7SUFDOUMsTUFBTSxlQUFlLEdBQUcsUUFBUSxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUM7SUFDbEQsTUFBTSxnQkFBZ0IsR0FBRyxRQUFRLENBQUMsU0FBUyxDQUFDLGNBQWMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUU5RCxTQUFTLGlCQUFpQixDQUFDLFlBQW1DLEVBQUU7UUFDOUQsT0FBTztZQUNMLE1BQU0sRUFBRSxhQUFhO1lBQ3JCLEtBQUssRUFBRSxDQUFDO1lBQ1IsVUFBVSxFQUFFLFdBQVc7WUFDdkIsU0FBUyxFQUFFLGVBQWU7WUFDMUIsR0FBRyxTQUFTO1NBQ2IsQ0FBQztJQUNKLENBQUM7SUFFRCw0RUFBNEU7SUFDNUUsMkRBQTJEO0lBQzNELDRFQUE0RTtJQUM1RSxRQUFRLENBQUMsdUNBQXVDLEVBQUU7UUFDaEQsRUFBRSxDQUFDLHlFQUF5RSxFQUFFLEtBQUs7WUFDakYsTUFBTSxNQUFNLEdBQUcsU0FBUyxDQUFDLENBQUMsV0FBVztZ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QUFrQjtZQUNsQixNQUFNLE1BQU0sR0FBRyxzQkFBa0IsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsUUFBUSxDQUFDLENBQUMsQ0FBQztZQUM3RSxNQUFNLFVBQVUsR0FBc0IsSUFBQSwyQkFBZ0IsRUFBQyxNQUFNLENBQUMsQ0FBQztZQUUvRCxvQkFBb0I7WUFDcEIsTUFBTSxhQUFhLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztZQUM3QyxNQUFNLFFBQVEsR0FBRyxNQUFNLGFBQWEsQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUM3QyxNQUFNLElBQUksR0FBRyxRQUFRLENBQUMsTUFBTSxFQUFFLENBQUM7WUFFL0IsbUNBQW1DO1lBQ25DLFVBQVUsQ0FBQyxlQUFlLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsQ0FBQztZQUNwRCxRQUFRLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsMEJBQWUsQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUNqRCxVQUFVLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQzFDLFVBQVUsQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ3ZELE1BQU0sQ0FBQyxVQUFVLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ3JFLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBzaG91bGQgZnJvbSAnc2hvdWxkJztcbmltcG9ydCB7IGNvaW5zIH0gZnJvbSAnQGJpdGdvL3N0YXRpY3MnO1xuaW1wb3J0IHsgVHJhbnNhY3Rpb25UeXBlIH0gZnJvbSAnQGJpdGdvL3Nkay1jb3JlJztcbmltcG9ydCB7XG4gIGJ1aWxkVHJhbnNhY3Rpb24sXG4gIHBhcnNlVHJhbnNhY3Rpb24sXG4gIFRyYW5zYWN0aW9uIGFzIFdhc21Ub25UcmFuc2FjdGlvbixcbiAgdHlwZSBCdWlsZENvbnRleHQsXG4gIHR5cGUgUGF5bWVudEludGVudCxcbiAgdHlwZSBQYXJzZWRUcmFuc2FjdGlvbixcbn0gZnJvbSAnQGJpdGdvL3dhc20tdG9uJztcbmltcG9ydCB7IFRyYW5zYWN0aW9uQnVpbGRlckZhY3RvcnkgfSBmcm9tICcuLi8uLi9zcmMvbGliL3RyYW5zYWN0aW9uQnVpbGRlckZhY3RvcnknO1xuaW1wb3J0ICogYXMgdGVzdERhdGEgZnJvbSAnLi4vcmVzb3VyY2VzL3Rvbic7XG5cbi8qKlxuICogQ3Jvc3MtY29tcGF0aWJpbGl0eSB0ZXN0cyBiZXR3ZWVuIFdBU00gKEBiaXRnby93YXNtLXRvbikgYW5kIGxlZ2FjeVxuICogKHRvbndlYi1iYXNlZCkgdHJhbnNhY3Rpb24gYnVpbGRpbmcvcGFyc2luZyBmb3IgVE9OLlxuICpcbiAqIERpcmVjdGlvbiAxOiBXQVNNIHBhcnNlcyBsZWdhY3ktYnVpbHQgdHJhbnNhY3Rpb25zIChjb3ZlcmVkIGJ5IGV4cGxhaW5UcmFuc2FjdGlvbldhc20udHMpXG4gKiBEaXJlY3Rpb24gMjogTGVnYWN5IHBhcnNlcyBXQVNNLWJ1aWx0IHRyYW5zYWN0aW9ucyAodGhpcyBmaWxlKVxuICovXG5kZXNjcmliZSgnVE9OIFdBU00gQ3Jvc3MtQ29tcGF0aWJpbGl0eScsIGZ1bmN0aW9uICgpIHtcbiAgY29uc3QgY29pbiA9IGNvaW5zLmdldCgndHRvbicpO1xuICBjb25zdCBmYWN0b3J5ID0gbmV3IFRyYW5zYWN0aW9uQnVpbGRlckZhY3RvcnkoY29pbik7XG5cbiAgLy8gVXNlIHNlbmRlciBmcm9tIHRlc3QgZml4dHVyZXNcbiAgY29uc3Qgc2VuZGVyQWRkcmVzcyA9IHRlc3REYXRhLnNlbmRlci5hZGRyZXNzO1xuICBjb25zdCBzZW5kZXJQdWJsaWNLZXkgPSB0ZXN0RGF0YS5zZW5kZXIucHVibGljS2V5O1xuICBjb25zdCByZWNpcGllbnRBZGRyZXNzID0gdGVzdERhdGEuYWRkcmVzc2VzLnZhbGlkQWRkcmVzc2VzWzBdO1xuXG4gIGZ1bmN0aW9uIGNyZWF0ZVdhc21Db250ZXh0KG92ZXJyaWRlczogUGFydGlhbDxCdWlsZENvbnRleHQ+ID0ge30pOiBCdWlsZENvbnRleHQge1xuICAgIHJldHVybiB7XG4gICAgICBzZW5kZXI6IHNlbmRlckFkZHJlc3MsXG4gICAgICBzZXFubzogNixcbiAgICAgIGV4cGlyZVRpbWU6IDE2OTU5OTc1ODJuLFxuICAgICAgcHVibGljS2V5OiBzZW5kZXJQdWJsaWNLZXksXG4gICAgICAuLi5vdmVycmlkZXMsXG4gICAgfTtcbiAgfVxuXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgLy8gV0FTTSAtPiBMZWdhY3k6IExlZ2FjeSBjYW4gcGFyc2UgV0FTTS1idWlsdCB0cmFuc2FjdGlvbnNcbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICBkZXNjcmliZSgnTGVnYWN5IHBhcnNlcyBXQVNNLWJ1aWx0IHRyYW5zYWN0aW9ucycsIGZ1bmN0aW9uICgpIHtcbiAgICBpdCgnc2hvdWxkIHBhcnNlIGEgV0FTTS1idWlsdCBwYXltZW50IHRyYW5zYWN0aW9uIHZpYSBsZWdhY3kgZmFjdG9yeS5mcm9tKCknLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBhbW91bnQgPSAxMDAwMDAwMG47IC8vIDAuMDEgVE9OXG4gICAgICBjb25zdCBtZW1vID0gJ3Rlc3QnO1xuXG4gICAgICAvLyBCdWlsZCB3aXRoIFdBU01cbiAgICAgIGNvbnN0IHdhc21UeCA9IGJ1aWxkVHJhbnNhY3Rpb24oXG4gICAgICAgIHtcbiAgICAgICAgICB0eXBlOiAncGF5bWVudCcsXG4gICAgICAgICAgdG86IHJlY2lwaWVudEFkZHJlc3MsXG4gICAgICAgICAgYW1vdW50LFxuICAgICAgICAgIGJvdW5jZWFibGU6IGZhbHNlLFxuICAgICAgICAgIG1lbW8sXG4gICAgICAgIH0gYXMgUGF5bWVudEludGVudCxcbiAgICAgICAgY3JlYXRlV2FzbUNvbnRleHQoKVxuICAgICAgKTtcblxuICAgICAgLy8gQ29udmVydCB0byBiYXNlNjQgKHRoZSBmb3JtYXQgbGVnYWN5IGV4cGVjdHMpXG4gICAgICBjb25zdCBib2NCeXRlcyA9IHdhc21UeC50b0Jyb2FkY2FzdEZvcm1hdCgpO1xuICAgICAgY29uc3QgYmFzZTY0VHggPSBCdWZmZXIuZnJvbShib2NCeXRlcykudG9TdHJpbmcoJ2Jhc2U2NCcpO1xuXG4gICAgICAvLyBQYXJzZSB3aXRoIGxlZ2FjeVxuICAgICAgY29uc3QgbGVnYWN5QnVpbGRlciA9IGZhY3RvcnkuZnJvbShiYXNlNjRUeCk7XG4gICAgICBjb25zdCBsZWdhY3lUeCA9IGF3YWl0IGxlZ2FjeUJ1aWxkZXIuYnVpbGQoKTtcbiAgICAgIGNvbnN0IGpzb24gPSBsZWdhY3lUeC50b0pzb24oKTtcblxuICAgICAgLy8gVmVyaWZ5IHRoZSBsZWdhY3kgYnVpbGRlciBjYW4gZXh0cmFjdCB0aGUgY29ycmVjdCBmaWVsZHNcbiAgICAgIGxlZ2FjeVR4LnR5cGUuc2hvdWxkLmVxdWFsKFRyYW5zYWN0aW9uVHlwZS5TZW5kKTtcbiAgICAgIGpzb24uc2Vxbm8uc2hvdWxkLmVxdWFsKDYpO1xuICAgICAganNvbi5leHBpcmF0aW9uVGltZS5zaG91bGQuZXF1YWwoMTY5NTk5NzU4Mik7XG4gICAgICBqc29uLmFtb3VudC5zaG91bGQuZXF1YWwoYW1vdW50LnRvU3RyaW5nKCkpO1xuICAgICAgc2hvdWxkLmV4aXN0KGpzb24uc2VuZGVyKTtcbiAgICAgIHNob3VsZC5leGlzdChqc29uLmRlc3RpbmF0aW9uKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcGFyc2UgYSBXQVNNLWJ1aWx0IHBheW1lbnQgd2l0aG91dCBtZW1vIHZpYSBsZWdhY3knLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBhbW91bnQgPSA1MDAwMDAwMG47IC8vIDAuMDUgVE9OXG5cbiAgICAgIGNvbnN0IHdhc21UeCA9IGJ1aWxkVHJhbnNhY3Rpb24oXG4gICAgICAgIHtcbiAgICAgICAgICB0eXBlOiAncGF5bWVudCcsXG4gICAgICAgICAgdG86IHJlY2lwaWVudEFkZHJlc3MsXG4gICAgICAgICAgYW1vdW50LFxuICAgICAgICAgIGJvdW5jZWFibGU6IGZhbHNlLFxuICAgICAgICB9IGFzIFBheW1lbnRJbnRlbnQsXG4gICAgICAgIGNyZWF0ZVdhc21Db250ZXh0KHsgc2Vxbm86IDEwLCBleHBpcmVUaW1lOiAxNzAwMDAwMDAwbiB9KVxuICAgICAgKTtcblxuICAgICAgY29uc3QgYmFzZTY0VHggPSBCdWZmZXIuZnJvbSh3YXNtVHgudG9Ccm9hZGNhc3RGb3JtYXQoKSkudG9TdHJpbmcoJ2Jhc2U2NCcpO1xuXG4gICAgICBjb25zdCBsZWdhY3lCdWlsZGVyID0gZmFjdG9yeS5mcm9tKGJhc2U2NFR4KTtcbiAgICAgIGNvbnN0IGxlZ2FjeVR4ID0gYXdhaXQgbGVnYWN5QnVpbGRlci5idWlsZCgpO1xuICAgICAgY29uc3QganNvbiA9IGxlZ2FjeVR4LnRvSnNvbigpO1xuXG4gICAgICBsZWdhY3lUeC50eXBlLnNob3VsZC5lcXVhbChUcmFuc2FjdGlvblR5cGUuU2VuZCk7XG4gICAgICBqc29uLnNlcW5vLnNob3VsZC5lcXVhbCgxMCk7XG4gICAgICBqc29uLmV4cGlyYXRpb25UaW1lLnNob3VsZC5lcXVhbCgxNzAwMDAwMDAwKTtcbiAgICAgIGpzb24uYW1vdW50LnNob3VsZC5lcXVhbChhbW91bnQudG9TdHJpbmcoKSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJvdW5kLXRyaXA6IFdBU00gYnVpbGQgLT4gbGVnYWN5IHBhcnNlIC0+IGxlZ2FjeSBidWlsZCAtPiBXQVNNIHBhcnNlJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgYW1vdW50ID0gMTIzNDAwMDAwbjtcbiAgICAgIGNvbnN0IG1lbW8gPSAnaGVsbG8nO1xuXG4gICAgICBjb25zdCB3YXNtVHggPSBidWlsZFRyYW5zYWN0aW9uKFxuICAgICAgICB7XG4gICAgICAgICAgdHlwZTogJ3BheW1lbnQnLFxuICAgICAgICAgIHRvOiByZWNpcGllbnRBZGRyZXNzLFxuICAgICAgICAgIGFtb3VudCxcbiAgICAgICAgICBib3VuY2VhYmxlOiBmYWxzZSxcbiAgICAgICAgICBtZW1vLFxuICAgICAgICB9IGFzIFBheW1lbnRJbnRlbnQsXG4gICAgICAgIGNyZWF0ZVdhc21Db250ZXh0KHsgc2Vxbm86IDMsIGV4cGlyZVRpbWU6IDEyMzQ1Njc4OTBuIH0pXG4gICAgICApO1xuXG4gICAgICBjb25zdCBiYXNlNjRUeCA9IEJ1ZmZlci5mcm9tKHdhc21UeC50b0Jyb2FkY2FzdEZvcm1hdCgpKS50b1N0cmluZygnYmFzZTY0Jyk7XG5cbiAgICAgIC8vIFBhcnNlIHdpdGggbGVnYWN5XG4gICAgICBjb25zdCBsZWdhY3lCdWlsZGVyID0gZmFjdG9yeS5mcm9tKGJhc2U2NFR4KTtcbiAgICAgIGNvbnN0IGxlZ2FjeVR4ID0gYXdhaXQgbGVnYWN5QnVpbGRlci5idWlsZCgpO1xuXG4gICAgICAvLyBSZWJ1aWxkIHdpdGggbGVnYWN5IHNob3VsZCBwcm9kdWNlIHZhbGlkIGJhc2U2NFxuICAgICAgY29uc3QgcmVidWlsdEJhc2U2NCA9IGxlZ2FjeVR4LnRvQnJvYWRjYXN0Rm9ybWF0KCk7XG5cbiAgICAgIC8vIFBhcnNlIHRoZSByZWJ1aWx0IHRyYW5zYWN0aW9uIHdpdGggV0FTTSB0byBjb25maXJtIGZpZWxkcyBtYXRjaFxuICAgICAgY29uc3Qgd2FzbVBhcnNlZDogUGFyc2VkVHJhbnNhY3Rpb24gPSBwYXJzZVRyYW5zYWN0aW9uKFxuICAgICAgICBXYXNtVG9uVHJhbnNhY3Rpb24uZnJvbUJ5dGVzKEJ1ZmZlci5mcm9tKHJlYnVpbHRCYXNlNjQsICdiYXNlNjQnKSlcbiAgICAgICk7XG5cbiAgICAgIHdhc21QYXJzZWQudHJhbnNhY3Rpb25UeXBlLnNob3VsZC5lcXVhbCgnVHJhbnNmZXInKTtcbiAgICAgIHdhc21QYXJzZWQuc2Vxbm8uc2hvdWxkLmVxdWFsKDMpO1xuICAgICAgd2FzbVBhcnNlZC5zZW5kQWN0aW9ucy5sZW5ndGguc2hvdWxkLmJlLmdyZWF0ZXJUaGFuKDApO1xuICAgICAgU3RyaW5nKHdhc21QYXJzZWQuc2VuZEFjdGlvbnNbMF0uYW1vdW50KS5zaG91bGQuZXF1YWwoYW1vdW50LnRvU3RyaW5nKCkpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBwYXJzZSBhIFdBU00tYnVpbHQgYm91bmNlYWJsZSBwYXltZW50IHZpYSBsZWdhY3knLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBhbW91bnQgPSAxMDAwMDAwMG47XG5cbiAgICAgIGNvbnN0IHdhc21UeCA9IGJ1aWxkVHJhbnNhY3Rpb24oXG4gICAgICAgIHtcbiAgICAgICAgICB0eXBlOiAncGF5bWVudCcsXG4gICAgICAgICAgdG86IHJlY2lwaWVudEFkZHJlc3MsXG4gICAgICAgICAgYW1vdW50LFxuICAgICAgICAgIGJvdW5jZWFibGU6IHRydWUsXG4gICAgICAgIH0gYXMgUGF5bWVudEludGVudCxcbiAgICAgICAgY3JlYXRlV2FzbUNvbnRleHQoKVxuICAgICAgKTtcblxuICAgICAgY29uc3QgYmFzZTY0VHggPSBCdWZmZXIuZnJvbSh3YXNtVHgudG9Ccm9hZGNhc3RGb3JtYXQoKSkudG9TdHJpbmcoJ2Jhc2U2NCcpO1xuXG4gICAgICBjb25zdCBsZWdhY3lCdWlsZGVyID0gZmFjdG9yeS5mcm9tKGJhc2U2NFR4KTtcbiAgICAgIGNvbnN0IGxlZ2FjeVR4ID0gYXdhaXQgbGVnYWN5QnVpbGRlci5idWlsZCgpO1xuICAgICAgY29uc3QganNvbiA9IGxlZ2FjeVR4LnRvSnNvbigpO1xuXG4gICAgICBsZWdhY3lUeC50eXBlLnNob3VsZC5lcXVhbChUcmFuc2FjdGlvblR5cGUuU2VuZCk7XG4gICAgICBqc29uLmFtb3VudC5zaG91bGQuZXF1YWwoYW1vdW50LnRvU3RyaW5nKCkpO1xuICAgIH0pO1xuICB9KTtcblxuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gIC8vIEJvdGggV0FTTSBhbmQgbGVnYWN5IGFncmVlIG9uIHNpZ25lZCBmaXh0dXJlIGRhdGFcbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICBkZXNjcmliZSgnQm90aCBXQVNNIGFuZCBsZWdhY3kgYWdyZWUgb24gc2lnbmVkIGZpeHR1cmUgZGF0YScsIGZ1bmN0aW9uICgpIHtcbiAgICBpdCgnc2hvdWxkIHByb2R1Y2UgbWF0Y2hpbmcgZmllbGRzIGZvciBzaWduZWRTZW5kVHJhbnNhY3Rpb24nLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB0eEJhc2U2NCA9IHRlc3REYXRhLnNpZ25lZFNlbmRUcmFuc2FjdGlvbi50eDtcblxuICAgICAgLy8gUGFyc2Ugd2l0aCBXQVNNXG4gICAgICBjb25zdCB3YXNtVHggPSBXYXNtVG9uVHJhbnNhY3Rpb24uZnJvbUJ5dGVzKEJ1ZmZlci5mcm9tKHR4QmFzZTY0LCAnYmFzZTY0JykpO1xuICAgICAgY29uc3Qgd2FzbVBhcnNlZDogUGFyc2VkVHJhbnNhY3Rpb24gPSBwYXJzZVRyYW5zYWN0aW9uKHdhc21UeCk7XG5cbiAgICAgIC8vIFBhcnNlIHdpdGggbGVnYWN5XG4gICAgICBjb25zdCBsZWdhY3lCdWlsZGVyID0gZmFjdG9yeS5mcm9tKHR4QmFzZTY0KTtcbiAgICAgIGNvbnN0IGxlZ2FjeVR4ID0gYXdhaXQgbGVnYWN5QnVpbGRlci5idWlsZCgpO1xuICAgICAgY29uc3QganNvbiA9IGxlZ2FjeVR4LnRvSnNvbigpO1xuXG4gICAgICAvLyBCb3RoIHNob3VsZCBhZ3JlZSBvbiBjb3JlIGZpZWxkc1xuICAgICAgd2FzbVBhcnNlZC50cmFuc2FjdGlvblR5cGUuc2hvdWxkLmVxdWFsKCdUcmFuc2ZlcicpO1xuICAgICAgbGVnYWN5VHgudHlwZS5zaG91bGQuZXF1YWwoVHJhbnNhY3Rpb25UeXBlLlNlbmQpO1xuICAgICAgd2FzbVBhcnNlZC5zZXFuby5zaG91bGQuZXF1YWwoanNvbi5zZXFubyk7XG4gICAgICB3YXNtUGFyc2VkLnNlbmRBY3Rpb25zLmxlbmd0aC5zaG91bGQuYmUuZ3JlYXRlclRoYW4oMCk7XG4gICAgICBTdHJpbmcod2FzbVBhcnNlZC5zZW5kQWN0aW9uc1swXS5hbW91bnQpLnNob3VsZC5lcXVhbChqc29uLmFtb3VudCk7XG4gICAgfSk7XG4gIH0pO1xufSk7XG4iXX0=
|