@ethersphere/bee-js 3.3.3 → 4.0.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 +24 -22
- package/README.md +0 -8
- package/dist/cjs/bee.js +71 -18
- package/dist/cjs/feed/identifier.js +35 -0
- package/dist/cjs/feed/index.js +34 -90
- package/dist/cjs/feed/retrievable.js +72 -0
- package/dist/cjs/modules/debug/status.js +3 -3
- package/dist/cjs/modules/feed.js +3 -3
- package/dist/cjs/types/index.js +2 -1
- package/dist/cjs/utils/bytes.js +15 -1
- package/dist/cjs/utils/data.browser.js +6 -10
- package/dist/cjs/utils/data.js +4 -6
- package/dist/cjs/utils/reference.js +36 -0
- package/dist/cjs/utils/type.js +36 -1
- package/dist/index.browser.min.js +1 -1
- package/dist/index.browser.min.js.map +1 -1
- package/dist/mjs/bee.js +77 -19
- package/dist/mjs/chunk/cac.js +1 -1
- package/dist/mjs/feed/identifier.js +35 -0
- package/dist/mjs/feed/index.js +39 -94
- package/dist/mjs/feed/retrievable.js +105 -0
- package/dist/mjs/modules/debug/status.js +3 -3
- package/dist/mjs/modules/feed.js +1 -1
- package/dist/mjs/types/index.js +1 -0
- package/dist/mjs/utils/bytes.js +15 -0
- package/dist/mjs/utils/data.browser.js +0 -1
- package/dist/mjs/utils/data.js +4 -5
- package/dist/mjs/utils/reference.js +32 -0
- package/dist/mjs/utils/type.js +38 -1
- package/dist/types/bee.d.ts +49 -19
- package/dist/types/chunk/cac.d.ts +4 -5
- package/dist/types/chunk/soc.d.ts +4 -4
- package/dist/types/feed/identifier.d.ts +4 -0
- package/dist/types/feed/index.d.ts +9 -16
- package/dist/types/feed/retrievable.d.ts +5 -0
- package/dist/types/modules/bytes.d.ts +3 -3
- package/dist/types/modules/bzz.d.ts +3 -3
- package/dist/types/modules/chunk.d.ts +2 -2
- package/dist/types/modules/debug/status.d.ts +3 -3
- package/dist/types/modules/feed.d.ts +12 -1
- package/dist/types/modules/stewardship.d.ts +3 -3
- package/dist/types/types/debug.d.ts +20 -3
- package/dist/types/types/index.d.ts +11 -2
- package/dist/types/utils/bytes.d.ts +7 -0
- package/dist/types/utils/data.browser.d.ts +0 -1
- package/dist/types/utils/data.d.ts +2 -2
- package/dist/types/utils/reference.d.ts +2 -0
- package/dist/types/utils/type.d.ts +2 -1
- package/package.json +33 -33
package/LICENSE
CHANGED
|
@@ -1,27 +1,29 @@
|
|
|
1
|
-
|
|
1
|
+
BSD 3-Clause License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2022, The Swarm Authors
|
|
4
|
+
All rights reserved.
|
|
2
5
|
|
|
3
6
|
Redistribution and use in source and binary forms, with or without
|
|
4
|
-
modification, are permitted provided that the following conditions are
|
|
5
|
-
|
|
7
|
+
modification, are permitted provided that the following conditions are met:
|
|
8
|
+
|
|
9
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
|
10
|
+
list of conditions and the following disclaimer.
|
|
11
|
+
|
|
12
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
13
|
+
this list of conditions and the following disclaimer in the documentation
|
|
14
|
+
and/or other materials provided with the distribution.
|
|
6
15
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
copyright notice, this list of conditions and the following disclaimer
|
|
11
|
-
in the documentation and/or other materials provided with the
|
|
12
|
-
distribution.
|
|
13
|
-
* Neither the name of Swarm nor the names of its
|
|
14
|
-
contributors may be used to endorse or promote products derived from
|
|
15
|
-
this software without specific prior written permission.
|
|
16
|
+
3. Neither the name of the copyright holder nor the names of its
|
|
17
|
+
contributors may be used to endorse or promote products derived from
|
|
18
|
+
this software without specific prior written permission.
|
|
16
19
|
|
|
17
|
-
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
20
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
21
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
22
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
23
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
24
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
25
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
26
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
27
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
28
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
27
29
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
package/README.md
CHANGED
|
@@ -90,14 +90,6 @@ console.log(data.text()) // prints 'Bee is awesome!'
|
|
|
90
90
|
|
|
91
91
|
You can find the full documentation [here](https://bee-js.ethswarm.org/docs). The API reference documentation can be found [here](https://bee-js.ethswarm.org/docs/api).
|
|
92
92
|
|
|
93
|
-
You can generate API docs locally with:
|
|
94
|
-
|
|
95
|
-
```sh
|
|
96
|
-
npm run docs
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
The generated docs can be viewed in browser by opening `./docs/index.html`
|
|
100
|
-
|
|
101
93
|
## Contribute
|
|
102
94
|
|
|
103
95
|
There are some ways you can make this module better:
|
package/dist/cjs/bee.js
CHANGED
|
@@ -56,6 +56,7 @@ const collection_node_1 = require("./utils/collection.node");
|
|
|
56
56
|
const types_1 = require("./types");
|
|
57
57
|
const http_1 = require("./utils/http");
|
|
58
58
|
const stream_1 = require("./utils/stream");
|
|
59
|
+
const retrievable_1 = require("./feed/retrievable");
|
|
59
60
|
/**
|
|
60
61
|
* The main component that abstracts operations available on the main Bee API.
|
|
61
62
|
*
|
|
@@ -121,30 +122,34 @@ class Bee {
|
|
|
121
122
|
/**
|
|
122
123
|
* Download data as a byte array
|
|
123
124
|
*
|
|
124
|
-
* @param reference Bee data reference
|
|
125
|
+
* @param reference Bee data reference in hex string (either 64 or 128 chars long) or ENS domain.
|
|
125
126
|
* @param options Options that affects the request behavior
|
|
127
|
+
* @throws TypeError if some of the input parameters is not expected type
|
|
128
|
+
* @throws BeeArgumentError if there is passed ENS domain with invalid unicode characters
|
|
126
129
|
* @see [Bee docs - Upload and download](https://docs.ethswarm.org/docs/access-the-swarm/upload-and-download)
|
|
127
130
|
* @see [Bee API reference - `GET /bytes`](https://docs.ethswarm.org/api/#tag/Bytes/paths/~1bytes~1{reference}/get)
|
|
128
131
|
*/
|
|
129
132
|
downloadData(reference, options) {
|
|
130
133
|
return __awaiter(this, void 0, void 0, function* () {
|
|
131
134
|
(0, type_2.assertRequestOptions)(options);
|
|
132
|
-
(0, type_2.
|
|
135
|
+
(0, type_2.assertReferenceOrEns)(reference);
|
|
133
136
|
return bytes.download(this.getKy(options), reference);
|
|
134
137
|
});
|
|
135
138
|
}
|
|
136
139
|
/**
|
|
137
140
|
* Download data as a Readable stream
|
|
138
141
|
*
|
|
139
|
-
* @param reference Bee data reference
|
|
142
|
+
* @param reference Bee data reference in hex string (either 64 or 128 chars long) or ENS domain.
|
|
140
143
|
* @param options Options that affects the request behavior
|
|
144
|
+
* @throws TypeError if some of the input parameters is not expected type
|
|
145
|
+
* @throws BeeArgumentError if there is passed ENS domain with invalid unicode characters
|
|
141
146
|
* @see [Bee docs - Upload and download](https://docs.ethswarm.org/docs/access-the-swarm/upload-and-download)
|
|
142
147
|
* @see [Bee API reference - `GET /bytes`](https://docs.ethswarm.org/api/#tag/Bytes/paths/~1bytes~1{reference}/get)
|
|
143
148
|
*/
|
|
144
149
|
downloadReadableData(reference, options) {
|
|
145
150
|
return __awaiter(this, void 0, void 0, function* () {
|
|
146
151
|
(0, type_2.assertRequestOptions)(options);
|
|
147
|
-
(0, type_2.
|
|
152
|
+
(0, type_2.assertReferenceOrEns)(reference);
|
|
148
153
|
return bytes.downloadReadable(this.getKy(options), reference);
|
|
149
154
|
});
|
|
150
155
|
}
|
|
@@ -179,15 +184,17 @@ class Bee {
|
|
|
179
184
|
/**
|
|
180
185
|
* Download chunk as a byte array
|
|
181
186
|
*
|
|
182
|
-
* @param reference Bee chunk reference
|
|
187
|
+
* @param reference Bee chunk reference in hex string (either 64 or 128 chars long) or ENS domain.
|
|
183
188
|
* @param options Options that affects the request behavior
|
|
189
|
+
* @throws TypeError if some of the input parameters is not expected type
|
|
190
|
+
* @throws BeeArgumentError if there is passed ENS domain with invalid unicode characters
|
|
184
191
|
* @see [Bee docs - Upload and download](https://docs.ethswarm.org/docs/access-the-swarm/upload-and-download)
|
|
185
192
|
* @see [Bee API reference - `GET /chunks`](https://docs.ethswarm.org/api/#tag/Chunk/paths/~1chunks~1{reference}/get)
|
|
186
193
|
*/
|
|
187
194
|
downloadChunk(reference, options) {
|
|
188
195
|
return __awaiter(this, void 0, void 0, function* () {
|
|
189
196
|
(0, type_2.assertRequestOptions)(options);
|
|
190
|
-
(0, type_2.
|
|
197
|
+
(0, type_2.assertReferenceOrEns)(reference);
|
|
191
198
|
return chunk.download(this.getKy(options), reference);
|
|
192
199
|
});
|
|
193
200
|
}
|
|
@@ -237,10 +244,11 @@ class Bee {
|
|
|
237
244
|
/**
|
|
238
245
|
* Download single file.
|
|
239
246
|
*
|
|
240
|
-
* @param reference Bee file reference
|
|
247
|
+
* @param reference Bee file reference in hex string (either 64 or 128 chars long) or ENS domain.
|
|
241
248
|
* @param path If reference points to manifest, then this parameter defines path to the file
|
|
242
249
|
* @param options Options that affects the request behavior
|
|
243
|
-
*
|
|
250
|
+
* @throws TypeError if some of the input parameters is not expected type
|
|
251
|
+
* @throws BeeArgumentError if there is passed ENS domain with invalid unicode characters
|
|
244
252
|
* @see Data
|
|
245
253
|
* @see [Bee docs - Upload and download](https://docs.ethswarm.org/docs/access-the-swarm/upload-and-download)
|
|
246
254
|
* @see [Bee API reference - `GET /bzz`](https://docs.ethswarm.org/api/#tag/Collection/paths/~1bzz~1{reference}~1{path}/get)
|
|
@@ -248,16 +256,18 @@ class Bee {
|
|
|
248
256
|
downloadFile(reference, path = '', options) {
|
|
249
257
|
return __awaiter(this, void 0, void 0, function* () {
|
|
250
258
|
(0, type_2.assertRequestOptions)(options);
|
|
251
|
-
(0, type_2.
|
|
259
|
+
(0, type_2.assertReferenceOrEns)(reference);
|
|
252
260
|
return bzz.downloadFile(this.getKy(options), reference, path);
|
|
253
261
|
});
|
|
254
262
|
}
|
|
255
263
|
/**
|
|
256
264
|
* Download single file as a readable stream
|
|
257
265
|
*
|
|
258
|
-
* @param reference
|
|
266
|
+
* @param reference Bee file reference in hex string (either 64 or 128 chars long) or ENS domain.
|
|
259
267
|
* @param path If reference points to manifest / collections, then this parameter defines path to the file
|
|
260
268
|
* @param options Options that affects the request behavior
|
|
269
|
+
* @throws TypeError if some of the input parameters is not expected type
|
|
270
|
+
* @throws BeeArgumentError if there is passed ENS domain with invalid unicode characters
|
|
261
271
|
*
|
|
262
272
|
* @see [Bee docs - Upload and download](https://docs.ethswarm.org/docs/access-the-swarm/upload-and-download)
|
|
263
273
|
* @see [Bee API reference - `GET /bzz`](https://docs.ethswarm.org/api/#tag/Collection/paths/~1bzz~1{reference}~1{path}/get)
|
|
@@ -265,7 +275,7 @@ class Bee {
|
|
|
265
275
|
downloadReadableFile(reference, path = '', options) {
|
|
266
276
|
return __awaiter(this, void 0, void 0, function* () {
|
|
267
277
|
(0, type_2.assertRequestOptions)(options);
|
|
268
|
-
(0, type_2.
|
|
278
|
+
(0, type_2.assertReferenceOrEns)(reference);
|
|
269
279
|
return bzz.downloadFileReadable(this.getKy(options), reference, path);
|
|
270
280
|
});
|
|
271
281
|
}
|
|
@@ -494,9 +504,10 @@ class Bee {
|
|
|
494
504
|
*
|
|
495
505
|
* **Warning! Not allowed when node is in Gateway mode!**
|
|
496
506
|
*
|
|
497
|
-
* @param reference Bee data reference
|
|
507
|
+
* @param reference Bee data reference in hex string (either 64 or 128 chars long) or ENS domain.
|
|
498
508
|
* @param options Options that affects the request behavior
|
|
499
|
-
* @throws TypeError if
|
|
509
|
+
* @throws TypeError if some of the input parameters is not expected type
|
|
510
|
+
* @throws BeeArgumentError if there is passed ENS domain with invalid unicode characters
|
|
500
511
|
*
|
|
501
512
|
* @see [Bee docs - Pinning](https://docs.ethswarm.org/docs/access-the-swarm/pinning)
|
|
502
513
|
*/
|
|
@@ -510,35 +521,77 @@ class Bee {
|
|
|
510
521
|
/**
|
|
511
522
|
* Instructs the Bee node to reupload a locally pinned data into the network.
|
|
512
523
|
*
|
|
513
|
-
* @param reference
|
|
524
|
+
* @param reference Bee data reference to be re-uploaded in hex string (either 64 or 128 chars long) or ENS domain.
|
|
514
525
|
* @param options Options that affects the request behavior
|
|
515
526
|
* @throws BeeArgumentError if the reference is not locally pinned
|
|
516
|
-
* @throws TypeError if
|
|
527
|
+
* @throws TypeError if some of the input parameters is not expected type
|
|
528
|
+
* @throws BeeArgumentError if there is passed ENS domain with invalid unicode characters
|
|
517
529
|
*
|
|
518
530
|
* @see [Bee API reference - `PUT /stewardship`](https://docs.ethswarm.org/api/#tag/Stewardship/paths/~1stewardship~1{reference}/put)
|
|
519
531
|
*/
|
|
520
532
|
reuploadPinnedData(reference, options) {
|
|
521
533
|
return __awaiter(this, void 0, void 0, function* () {
|
|
522
534
|
(0, type_2.assertRequestOptions)(options);
|
|
523
|
-
(0, type_2.
|
|
535
|
+
(0, type_2.assertReferenceOrEns)(reference);
|
|
524
536
|
yield stewardship.reupload(this.getKy(options), reference);
|
|
525
537
|
});
|
|
526
538
|
}
|
|
527
539
|
/**
|
|
528
540
|
* Checks if content specified by reference is retrievable from the network.
|
|
529
541
|
*
|
|
530
|
-
* @param reference
|
|
542
|
+
* @param reference Bee data reference to be checked in hex string (either 64 or 128 chars long) or ENS domain.
|
|
531
543
|
* @param options Options that affects the request behavior
|
|
544
|
+
* @throws TypeError if some of the input parameters is not expected type
|
|
545
|
+
* @throws BeeArgumentError if there is passed ENS domain with invalid unicode characters
|
|
532
546
|
*
|
|
533
547
|
* @see [Bee API reference - `GET /stewardship`](https://docs.ethswarm.org/api/#tag/Stewardship/paths/~1stewardship~1{reference}/get)
|
|
534
548
|
*/
|
|
535
549
|
isReferenceRetrievable(reference, options) {
|
|
536
550
|
return __awaiter(this, void 0, void 0, function* () {
|
|
537
551
|
(0, type_2.assertRequestOptions)(options);
|
|
538
|
-
(0, type_2.
|
|
552
|
+
(0, type_2.assertReferenceOrEns)(reference);
|
|
539
553
|
return stewardship.isRetrievable(this.getKy(options), reference);
|
|
540
554
|
});
|
|
541
555
|
}
|
|
556
|
+
/**
|
|
557
|
+
* Functions that validates if feed is retrievable in the network.
|
|
558
|
+
*
|
|
559
|
+
* If no index is passed then it check for "latest" update, which is a weaker guarantee as nobody can be really
|
|
560
|
+
* sure what is the "latest" update.
|
|
561
|
+
*
|
|
562
|
+
* If index is passed then it validates all previous sequence index chunks if they are available as they are required
|
|
563
|
+
* to correctly resolve the feed upto the given index update.
|
|
564
|
+
*
|
|
565
|
+
* @param type
|
|
566
|
+
* @param owner
|
|
567
|
+
* @param topic
|
|
568
|
+
* @param index
|
|
569
|
+
* @param options
|
|
570
|
+
*/
|
|
571
|
+
isFeedRetrievable(type, owner, topic, index, options) {
|
|
572
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
573
|
+
const canonicalOwner = (0, eth_1.makeEthAddress)(owner);
|
|
574
|
+
const canonicalTopic = (0, topic_1.makeTopic)(topic);
|
|
575
|
+
if (!index) {
|
|
576
|
+
try {
|
|
577
|
+
yield this.makeFeedReader(type, canonicalTopic, canonicalOwner).download();
|
|
578
|
+
return true;
|
|
579
|
+
}
|
|
580
|
+
catch (e) {
|
|
581
|
+
const err = e;
|
|
582
|
+
// Only if the error is "not-found" then we return false otherwise we re-throw the error
|
|
583
|
+
if ((err === null || err === void 0 ? void 0 : err.status) === 404) {
|
|
584
|
+
return false;
|
|
585
|
+
}
|
|
586
|
+
throw e;
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
if (type !== 'sequence') {
|
|
590
|
+
throw new error_1.BeeError('Only Sequence type of Feeds is supported at the moment');
|
|
591
|
+
}
|
|
592
|
+
return (0, retrievable_1.areAllSequentialFeedsUpdateRetrievable)(this, canonicalOwner, canonicalTopic, index, options);
|
|
593
|
+
});
|
|
594
|
+
}
|
|
542
595
|
/**
|
|
543
596
|
* Send data to recipient or target with Postal Service for Swarm.
|
|
544
597
|
*
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.makeFeedIdentifier = void 0;
|
|
4
|
+
const types_1 = require("../types");
|
|
5
|
+
const hash_1 = require("../utils/hash");
|
|
6
|
+
const hex_1 = require("../utils/hex");
|
|
7
|
+
const uint64_1 = require("../utils/uint64");
|
|
8
|
+
function isEpoch(epoch) {
|
|
9
|
+
return typeof epoch === 'object' && epoch !== null && 'time' in epoch && 'level' in epoch;
|
|
10
|
+
}
|
|
11
|
+
function hashFeedIdentifier(topic, index) {
|
|
12
|
+
return (0, hash_1.keccak256Hash)((0, hex_1.hexToBytes)(topic), index);
|
|
13
|
+
}
|
|
14
|
+
function makeSequentialFeedIdentifier(topic, index) {
|
|
15
|
+
const indexBytes = (0, uint64_1.writeUint64BigEndian)(index);
|
|
16
|
+
return hashFeedIdentifier(topic, indexBytes);
|
|
17
|
+
}
|
|
18
|
+
function makeFeedIndexBytes(s) {
|
|
19
|
+
const hex = (0, hex_1.makeHexString)(s, types_1.FEED_INDEX_HEX_LENGTH);
|
|
20
|
+
return (0, hex_1.hexToBytes)(hex);
|
|
21
|
+
}
|
|
22
|
+
function makeFeedIdentifier(topic, index) {
|
|
23
|
+
if (typeof index === 'number') {
|
|
24
|
+
return makeSequentialFeedIdentifier(topic, index);
|
|
25
|
+
}
|
|
26
|
+
else if (typeof index === 'string') {
|
|
27
|
+
const indexBytes = makeFeedIndexBytes(index);
|
|
28
|
+
return hashFeedIdentifier(topic, indexBytes);
|
|
29
|
+
}
|
|
30
|
+
else if (isEpoch(index)) {
|
|
31
|
+
throw new TypeError('epoch is not yet implemented');
|
|
32
|
+
}
|
|
33
|
+
return hashFeedIdentifier(topic, index);
|
|
34
|
+
}
|
|
35
|
+
exports.makeFeedIdentifier = makeFeedIdentifier;
|
package/dist/cjs/feed/index.js
CHANGED
|
@@ -28,11 +28,11 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
28
28
|
});
|
|
29
29
|
};
|
|
30
30
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
31
|
-
exports.makeFeedWriter = exports.makeFeedReader = exports.downloadFeedUpdate = exports.
|
|
31
|
+
exports.makeFeedWriter = exports.makeFeedReader = exports.downloadFeedUpdate = exports.getFeedUpdateChunkReference = exports.updateFeed = exports.findNextIndex = void 0;
|
|
32
32
|
const hash_1 = require("../utils/hash");
|
|
33
33
|
const serialize_1 = require("../chunk/serialize");
|
|
34
|
-
const soc_1 = require("../chunk/soc");
|
|
35
34
|
const feed_1 = require("../modules/feed");
|
|
35
|
+
const soc_1 = require("../chunk/soc");
|
|
36
36
|
const types_1 = require("../types");
|
|
37
37
|
const bytes_1 = require("../utils/bytes");
|
|
38
38
|
const error_1 = require("../utils/error");
|
|
@@ -41,59 +41,16 @@ const uint64_1 = require("../utils/uint64");
|
|
|
41
41
|
const chunkAPI = __importStar(require("../modules/chunk"));
|
|
42
42
|
const eth_1 = require("../utils/eth");
|
|
43
43
|
const type_1 = require("../utils/type");
|
|
44
|
+
const identifier_1 = require("./identifier");
|
|
45
|
+
const reference_1 = require("../utils/reference");
|
|
44
46
|
const TIMESTAMP_PAYLOAD_OFFSET = 0;
|
|
45
47
|
const TIMESTAMP_PAYLOAD_SIZE = 8;
|
|
46
48
|
const REFERENCE_PAYLOAD_OFFSET = TIMESTAMP_PAYLOAD_SIZE;
|
|
47
|
-
const REFERENCE_PAYLOAD_MIN_SIZE = 32;
|
|
48
|
-
const REFERENCE_PAYLOAD_MAX_SIZE = 64;
|
|
49
|
-
const INDEX_HEX_LENGTH = 16;
|
|
50
|
-
function isEpoch(epoch) {
|
|
51
|
-
return typeof epoch === 'object' && epoch !== null && 'time' in epoch && 'level' in epoch;
|
|
52
|
-
}
|
|
53
|
-
exports.isEpoch = isEpoch;
|
|
54
|
-
function hashFeedIdentifier(topic, index) {
|
|
55
|
-
return (0, hash_1.keccak256Hash)((0, hex_1.hexToBytes)(topic), index);
|
|
56
|
-
}
|
|
57
|
-
function makeSequentialFeedIdentifier(topic, index) {
|
|
58
|
-
const indexBytes = (0, uint64_1.writeUint64BigEndian)(index);
|
|
59
|
-
return hashFeedIdentifier(topic, indexBytes);
|
|
60
|
-
}
|
|
61
|
-
exports.makeSequentialFeedIdentifier = makeSequentialFeedIdentifier;
|
|
62
|
-
function makeFeedIndexBytes(s) {
|
|
63
|
-
const hex = (0, hex_1.makeHexString)(s, INDEX_HEX_LENGTH);
|
|
64
|
-
return (0, hex_1.hexToBytes)(hex);
|
|
65
|
-
}
|
|
66
|
-
exports.makeFeedIndexBytes = makeFeedIndexBytes;
|
|
67
|
-
function makeFeedIdentifier(topic, index) {
|
|
68
|
-
if (typeof index === 'number') {
|
|
69
|
-
return makeSequentialFeedIdentifier(topic, index);
|
|
70
|
-
}
|
|
71
|
-
else if (typeof index === 'string') {
|
|
72
|
-
const indexBytes = makeFeedIndexBytes(index);
|
|
73
|
-
return hashFeedIdentifier(topic, indexBytes);
|
|
74
|
-
}
|
|
75
|
-
else if (isEpoch(index)) {
|
|
76
|
-
throw new TypeError('epoch is not yet implemented');
|
|
77
|
-
}
|
|
78
|
-
return hashFeedIdentifier(topic, index);
|
|
79
|
-
}
|
|
80
|
-
exports.makeFeedIdentifier = makeFeedIdentifier;
|
|
81
|
-
function uploadFeedUpdate(ky, signer, topic, index, reference, postageBatchId, options) {
|
|
82
|
-
var _a;
|
|
83
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
84
|
-
const identifier = makeFeedIdentifier(topic, index);
|
|
85
|
-
const at = (_a = options === null || options === void 0 ? void 0 : options.at) !== null && _a !== void 0 ? _a : Date.now() / 1000.0;
|
|
86
|
-
const timestamp = (0, uint64_1.writeUint64BigEndian)(at);
|
|
87
|
-
const payloadBytes = (0, serialize_1.serializeBytes)(timestamp, reference);
|
|
88
|
-
return (0, soc_1.uploadSingleOwnerChunkData)(ky, signer, postageBatchId, identifier, payloadBytes, options);
|
|
89
|
-
});
|
|
90
|
-
}
|
|
91
|
-
exports.uploadFeedUpdate = uploadFeedUpdate;
|
|
92
49
|
function findNextIndex(ky, owner, topic, options) {
|
|
93
50
|
return __awaiter(this, void 0, void 0, function* () {
|
|
94
51
|
try {
|
|
95
|
-
const feedUpdate = yield (0, feed_1.
|
|
96
|
-
return (0, hex_1.makeHexString)(feedUpdate.feedIndexNext,
|
|
52
|
+
const feedUpdate = yield (0, feed_1.fetchLatestFeedUpdate)(ky, owner, topic, options);
|
|
53
|
+
return (0, hex_1.makeHexString)(feedUpdate.feedIndexNext, types_1.FEED_INDEX_HEX_LENGTH);
|
|
97
54
|
}
|
|
98
55
|
catch (e) {
|
|
99
56
|
if (e instanceof error_1.BeeResponseError && e.status === 404) {
|
|
@@ -104,37 +61,34 @@ function findNextIndex(ky, owner, topic, options) {
|
|
|
104
61
|
});
|
|
105
62
|
}
|
|
106
63
|
exports.findNextIndex = findNextIndex;
|
|
107
|
-
function updateFeed(ky, signer, topic, reference, postageBatchId, options) {
|
|
64
|
+
function updateFeed(ky, signer, topic, reference, postageBatchId, options, index = 'latest') {
|
|
65
|
+
var _a;
|
|
108
66
|
return __awaiter(this, void 0, void 0, function* () {
|
|
109
67
|
const ownerHex = (0, eth_1.makeHexEthAddress)(signer.address);
|
|
110
|
-
const nextIndex = yield findNextIndex(ky, ownerHex, topic, options);
|
|
111
|
-
|
|
68
|
+
const nextIndex = index === 'latest' ? yield findNextIndex(ky, ownerHex, topic, options) : index;
|
|
69
|
+
const identifier = (0, identifier_1.makeFeedIdentifier)(topic, nextIndex);
|
|
70
|
+
const at = (_a = options === null || options === void 0 ? void 0 : options.at) !== null && _a !== void 0 ? _a : Date.now() / 1000.0;
|
|
71
|
+
const timestamp = (0, uint64_1.writeUint64BigEndian)(at);
|
|
72
|
+
const payloadBytes = (0, serialize_1.serializeBytes)(timestamp, reference);
|
|
73
|
+
return (0, soc_1.uploadSingleOwnerChunkData)(ky, signer, postageBatchId, identifier, payloadBytes, options);
|
|
112
74
|
});
|
|
113
75
|
}
|
|
114
76
|
exports.updateFeed = updateFeed;
|
|
115
|
-
function
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
}
|
|
119
|
-
catch (e) {
|
|
120
|
-
return (0, bytes_1.bytesAtOffset)(data, offset, REFERENCE_PAYLOAD_MIN_SIZE);
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
function verifyChunkReference(data) {
|
|
124
|
-
return verifyChunkReferenceAtOffset(0, data);
|
|
77
|
+
function getFeedUpdateChunkReference(owner, topic, index) {
|
|
78
|
+
const identifier = (0, identifier_1.makeFeedIdentifier)(topic, index);
|
|
79
|
+
return (0, hash_1.keccak256Hash)(identifier, owner);
|
|
125
80
|
}
|
|
126
|
-
exports.
|
|
81
|
+
exports.getFeedUpdateChunkReference = getFeedUpdateChunkReference;
|
|
127
82
|
function downloadFeedUpdate(ky, owner, topic, index) {
|
|
128
83
|
return __awaiter(this, void 0, void 0, function* () {
|
|
129
|
-
const
|
|
130
|
-
const address = (0, hash_1.keccak256Hash)(identifier, owner);
|
|
84
|
+
const address = getFeedUpdateChunkReference(owner, topic, index);
|
|
131
85
|
const addressHex = (0, hex_1.bytesToHex)(address);
|
|
132
86
|
const data = yield chunkAPI.download(ky, addressHex);
|
|
133
87
|
const soc = (0, soc_1.makeSingleOwnerChunkFromData)(data, address);
|
|
134
88
|
const payload = soc.payload();
|
|
135
89
|
const timestampBytes = (0, bytes_1.bytesAtOffset)(payload, TIMESTAMP_PAYLOAD_OFFSET, TIMESTAMP_PAYLOAD_SIZE);
|
|
136
90
|
const timestamp = (0, uint64_1.readUint64BigEndian)(timestampBytes);
|
|
137
|
-
const reference =
|
|
91
|
+
const reference = (0, reference_1.makeBytesReference)(payload, REFERENCE_PAYLOAD_OFFSET);
|
|
138
92
|
return {
|
|
139
93
|
timestamp,
|
|
140
94
|
reference,
|
|
@@ -143,40 +97,30 @@ function downloadFeedUpdate(ky, owner, topic, index) {
|
|
|
143
97
|
}
|
|
144
98
|
exports.downloadFeedUpdate = downloadFeedUpdate;
|
|
145
99
|
function makeFeedReader(ky, type, topic, owner) {
|
|
146
|
-
const download = (options) => __awaiter(this, void 0, void 0, function* () { return (0, feed_1.fetchFeedUpdate)(ky, owner, topic, Object.assign(Object.assign({}, options), { type })); });
|
|
147
100
|
return {
|
|
148
101
|
type,
|
|
149
102
|
owner,
|
|
150
103
|
topic,
|
|
151
|
-
download
|
|
104
|
+
download(options) {
|
|
105
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
106
|
+
if (!(options === null || options === void 0 ? void 0 : options.index)) {
|
|
107
|
+
return (0, feed_1.fetchLatestFeedUpdate)(ky, owner, topic, Object.assign(Object.assign({}, options), { type }));
|
|
108
|
+
}
|
|
109
|
+
const update = yield downloadFeedUpdate(ky, (0, hex_1.hexToBytes)(owner), topic, options.index);
|
|
110
|
+
return {
|
|
111
|
+
reference: (0, hex_1.bytesToHex)(update.reference),
|
|
112
|
+
feedIndex: options.index,
|
|
113
|
+
feedIndexNext: '',
|
|
114
|
+
};
|
|
115
|
+
});
|
|
116
|
+
},
|
|
152
117
|
};
|
|
153
118
|
}
|
|
154
119
|
exports.makeFeedReader = makeFeedReader;
|
|
155
|
-
function makeChunkReference(reference) {
|
|
156
|
-
if (typeof reference === 'string') {
|
|
157
|
-
try {
|
|
158
|
-
// Non-encrypted chunk hex string reference
|
|
159
|
-
const hexReference = (0, hex_1.makeHexString)(reference, types_1.REFERENCE_HEX_LENGTH);
|
|
160
|
-
return (0, hex_1.hexToBytes)(hexReference);
|
|
161
|
-
}
|
|
162
|
-
catch (e) {
|
|
163
|
-
if (!(e instanceof TypeError)) {
|
|
164
|
-
throw e;
|
|
165
|
-
}
|
|
166
|
-
// Encrypted chunk hex string reference
|
|
167
|
-
const hexReference = (0, hex_1.makeHexString)(reference, types_1.ENCRYPTED_REFERENCE_HEX_LENGTH);
|
|
168
|
-
return (0, hex_1.hexToBytes)(hexReference);
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
else if (reference instanceof Uint8Array) {
|
|
172
|
-
return verifyChunkReference(reference);
|
|
173
|
-
}
|
|
174
|
-
throw new TypeError('invalid chunk reference');
|
|
175
|
-
}
|
|
176
120
|
function makeFeedWriter(ky, type, topic, signer) {
|
|
177
121
|
const upload = (postageBatchId, reference, options) => __awaiter(this, void 0, void 0, function* () {
|
|
178
122
|
(0, type_1.assertAddress)(postageBatchId);
|
|
179
|
-
const canonicalReference =
|
|
123
|
+
const canonicalReference = (0, reference_1.makeBytesReference)(reference);
|
|
180
124
|
return updateFeed(ky, signer, topic, canonicalReference, postageBatchId, Object.assign(Object.assign({}, options), { type }));
|
|
181
125
|
});
|
|
182
126
|
return Object.assign(Object.assign({}, makeFeedReader(ky, type, topic, (0, eth_1.makeHexEthAddress)(signer.address))), { upload });
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.areAllSequentialFeedsUpdateRetrievable = void 0;
|
|
13
|
+
const index_1 = require("./index");
|
|
14
|
+
const uint64_1 = require("../utils/uint64");
|
|
15
|
+
const hex_1 = require("../utils/hex");
|
|
16
|
+
function makeNumericIndex(index) {
|
|
17
|
+
if (index instanceof Uint8Array) {
|
|
18
|
+
return (0, uint64_1.readUint64BigEndian)(index);
|
|
19
|
+
}
|
|
20
|
+
if (typeof index === 'string') {
|
|
21
|
+
return parseInt(index);
|
|
22
|
+
}
|
|
23
|
+
if (typeof index === 'number') {
|
|
24
|
+
return index;
|
|
25
|
+
}
|
|
26
|
+
throw new TypeError('Unknown type of index!');
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Function that checks if a chunk is retrievable by actually downloading it.
|
|
30
|
+
* The /stewardship/{reference} endpoint does not support verification of chunks, but only manifest's references.
|
|
31
|
+
*
|
|
32
|
+
* @param bee
|
|
33
|
+
* @param ref
|
|
34
|
+
* @param options
|
|
35
|
+
*/
|
|
36
|
+
function isChunkRetrievable(bee, ref, options) {
|
|
37
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
38
|
+
try {
|
|
39
|
+
yield bee.downloadChunk(ref, options);
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
42
|
+
catch (e) {
|
|
43
|
+
const err = e;
|
|
44
|
+
if (err.status === 404) {
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
throw e;
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Creates array of references for all sequence updates chunk up to the given index.
|
|
53
|
+
*
|
|
54
|
+
* @param owner
|
|
55
|
+
* @param topic
|
|
56
|
+
* @param index
|
|
57
|
+
*/
|
|
58
|
+
function getAllSequenceUpdateReferences(owner, topic, index) {
|
|
59
|
+
const numIndex = makeNumericIndex(index);
|
|
60
|
+
const updateReferences = new Array(numIndex + 1);
|
|
61
|
+
for (let i = 0; i <= numIndex; i++) {
|
|
62
|
+
updateReferences[i] = (0, hex_1.bytesToHex)((0, index_1.getFeedUpdateChunkReference)(owner, topic, i));
|
|
63
|
+
}
|
|
64
|
+
return updateReferences;
|
|
65
|
+
}
|
|
66
|
+
function areAllSequentialFeedsUpdateRetrievable(bee, owner, topic, index, options) {
|
|
67
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
68
|
+
const chunkRetrievablePromises = getAllSequenceUpdateReferences(owner, topic, index).map((ref) => __awaiter(this, void 0, void 0, function* () { return isChunkRetrievable(bee, ref, options); }));
|
|
69
|
+
return (yield Promise.all(chunkRetrievablePromises)).every(result => result);
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
exports.areAllSequentialFeedsUpdateRetrievable = areAllSequentialFeedsUpdateRetrievable;
|
|
@@ -17,9 +17,9 @@ const http_1 = require("../../utils/http");
|
|
|
17
17
|
const major_js_1 = __importDefault(require("semver/functions/major.js"));
|
|
18
18
|
// Following lines bellow are automatically updated with GitHub Action when Bee version is updated
|
|
19
19
|
// so if you are changing anything about them change the `update_bee` action accordingly!
|
|
20
|
-
exports.SUPPORTED_BEE_VERSION_EXACT = '1.
|
|
21
|
-
exports.SUPPORTED_API_VERSION = '3.0.
|
|
22
|
-
exports.SUPPORTED_DEBUG_API_VERSION = '2.0.
|
|
20
|
+
exports.SUPPORTED_BEE_VERSION_EXACT = '1.6.0-6ceadd35';
|
|
21
|
+
exports.SUPPORTED_API_VERSION = '3.0.1';
|
|
22
|
+
exports.SUPPORTED_DEBUG_API_VERSION = '2.0.1';
|
|
23
23
|
exports.SUPPORTED_BEE_VERSION = exports.SUPPORTED_BEE_VERSION_EXACT.substring(0, exports.SUPPORTED_BEE_VERSION_EXACT.indexOf('-'));
|
|
24
24
|
const NODE_INFO_URL = 'node';
|
|
25
25
|
const HEALTH_URL = 'health';
|
package/dist/cjs/modules/feed.js
CHANGED
|
@@ -9,7 +9,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.
|
|
12
|
+
exports.fetchLatestFeedUpdate = exports.createFeedManifest = void 0;
|
|
13
13
|
const http_1 = require("../utils/http");
|
|
14
14
|
const headers_1 = require("../utils/headers");
|
|
15
15
|
const error_1 = require("../utils/error");
|
|
@@ -63,7 +63,7 @@ function readFeedUpdateHeaders(headers) {
|
|
|
63
63
|
* @param topic Topic in hex
|
|
64
64
|
* @param options Additional options, like index, at, type
|
|
65
65
|
*/
|
|
66
|
-
function
|
|
66
|
+
function fetchLatestFeedUpdate(ky, owner, topic, options) {
|
|
67
67
|
return __awaiter(this, void 0, void 0, function* () {
|
|
68
68
|
const response = yield (0, http_1.http)(ky, {
|
|
69
69
|
responseType: 'json',
|
|
@@ -73,4 +73,4 @@ function fetchFeedUpdate(ky, owner, topic, options) {
|
|
|
73
73
|
return Object.assign(Object.assign({}, response.data), readFeedUpdateHeaders(response.headers));
|
|
74
74
|
});
|
|
75
75
|
}
|
|
76
|
-
exports.
|
|
76
|
+
exports.fetchLatestFeedUpdate = fetchLatestFeedUpdate;
|
package/dist/cjs/types/index.js
CHANGED
|
@@ -10,7 +10,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
10
10
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
11
11
|
};
|
|
12
12
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
-
exports.SIGNATURE_BYTES_LENGTH = exports.SIGNATURE_HEX_LENGTH = exports.TOPIC_HEX_LENGTH = exports.TOPIC_BYTES_LENGTH = exports.TAGS_LIMIT_MAX = exports.TAGS_LIMIT_MIN = exports.STAMPS_DEPTH_MAX = exports.STAMPS_DEPTH_MIN = exports.ENCRYPTED_REFERENCE_BYTES_LENGTH = exports.REFERENCE_BYTES_LENGTH = exports.ENCRYPTED_REFERENCE_HEX_LENGTH = exports.REFERENCE_HEX_LENGTH = exports.BATCH_ID_HEX_LENGTH = exports.PUBKEY_HEX_LENGTH = exports.PSS_TARGET_HEX_LENGTH_MAX = exports.ADDRESS_HEX_LENGTH = exports.CHUNK_SIZE = exports.BRANCHES = exports.SECTION_SIZE = exports.SPAN_SIZE = void 0;
|
|
13
|
+
exports.SIGNATURE_BYTES_LENGTH = exports.SIGNATURE_HEX_LENGTH = exports.TOPIC_HEX_LENGTH = exports.TOPIC_BYTES_LENGTH = exports.FEED_INDEX_HEX_LENGTH = exports.TAGS_LIMIT_MAX = exports.TAGS_LIMIT_MIN = exports.STAMPS_DEPTH_MAX = exports.STAMPS_DEPTH_MIN = exports.ENCRYPTED_REFERENCE_BYTES_LENGTH = exports.REFERENCE_BYTES_LENGTH = exports.ENCRYPTED_REFERENCE_HEX_LENGTH = exports.REFERENCE_HEX_LENGTH = exports.BATCH_ID_HEX_LENGTH = exports.PUBKEY_HEX_LENGTH = exports.PSS_TARGET_HEX_LENGTH_MAX = exports.ADDRESS_HEX_LENGTH = exports.CHUNK_SIZE = exports.BRANCHES = exports.SECTION_SIZE = exports.SPAN_SIZE = void 0;
|
|
14
14
|
__exportStar(require("./debug"), exports);
|
|
15
15
|
exports.SPAN_SIZE = 8;
|
|
16
16
|
exports.SECTION_SIZE = 32;
|
|
@@ -34,6 +34,7 @@ exports.STAMPS_DEPTH_MIN = 17;
|
|
|
34
34
|
exports.STAMPS_DEPTH_MAX = 255;
|
|
35
35
|
exports.TAGS_LIMIT_MIN = 1;
|
|
36
36
|
exports.TAGS_LIMIT_MAX = 1000;
|
|
37
|
+
exports.FEED_INDEX_HEX_LENGTH = 16;
|
|
37
38
|
/*********************************************************
|
|
38
39
|
* Writers and Readers interfaces
|
|
39
40
|
*/
|
package/dist/cjs/utils/bytes.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.wrapBytesWithHelpers = exports.makeBytes = exports.bytesEqual = exports.flexBytesAtOffset = exports.bytesAtOffset = exports.assertFlexBytes = exports.isFlexBytes = exports.assertBytes = exports.isBytes = void 0;
|
|
3
|
+
exports.wrapBytesWithHelpers = exports.makeBytes = exports.bytesEqual = exports.flexBytesAtOffset = exports.bytesAtOffset = exports.assertFlexBytes = exports.isFlexBytes = exports.assertBytes = exports.hasBytesAtOffset = exports.isBytes = void 0;
|
|
4
4
|
const hex_1 = require("./hex");
|
|
5
5
|
/**
|
|
6
6
|
* Type guard for `Bytes<T>` type
|
|
@@ -12,6 +12,20 @@ function isBytes(b, length) {
|
|
|
12
12
|
return b instanceof Uint8Array && b.length === length;
|
|
13
13
|
}
|
|
14
14
|
exports.isBytes = isBytes;
|
|
15
|
+
/**
|
|
16
|
+
* Function that verifies if passed data are Bytes and if the array has "length" number of bytes under given offset.
|
|
17
|
+
* @param data
|
|
18
|
+
* @param offset
|
|
19
|
+
* @param length
|
|
20
|
+
*/
|
|
21
|
+
function hasBytesAtOffset(data, offset, length) {
|
|
22
|
+
if (!(data instanceof Uint8Array)) {
|
|
23
|
+
throw new TypeError('Data has to an Uint8Array!');
|
|
24
|
+
}
|
|
25
|
+
const offsetBytes = data.slice(offset, offset + length);
|
|
26
|
+
return isBytes(offsetBytes, length);
|
|
27
|
+
}
|
|
28
|
+
exports.hasBytesAtOffset = hasBytesAtOffset;
|
|
15
29
|
/**
|
|
16
30
|
* Verifies if a byte array has a certain length
|
|
17
31
|
*
|