@upcoming/bee-js 9.9.1 → 11.1.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.
Files changed (103) hide show
  1. package/README.md +2 -2
  2. package/dist/cjs/bee.js +881 -370
  3. package/dist/cjs/chunk/bmt.js +1 -2
  4. package/dist/cjs/chunk/cac.js +27 -32
  5. package/dist/cjs/chunk/soc.js +39 -31
  6. package/dist/cjs/feed/identifier.js +1 -2
  7. package/dist/cjs/feed/index.js +29 -19
  8. package/dist/cjs/feed/retrievable.js +1 -2
  9. package/dist/cjs/index.js +17 -7
  10. package/dist/cjs/manifest/manifest.js +19 -2
  11. package/dist/cjs/modules/bytes.js +4 -5
  12. package/dist/cjs/modules/bzz.js +4 -5
  13. package/dist/cjs/modules/chunk.js +2 -3
  14. package/dist/cjs/modules/debug/balance.js +4 -5
  15. package/dist/cjs/modules/debug/chequebook.js +9 -10
  16. package/dist/cjs/modules/debug/connectivity.js +7 -8
  17. package/dist/cjs/modules/debug/settlements.js +2 -3
  18. package/dist/cjs/modules/debug/stake.js +6 -7
  19. package/dist/cjs/modules/debug/stamps.js +24 -60
  20. package/dist/cjs/modules/debug/states.js +6 -6
  21. package/dist/cjs/modules/debug/status.js +9 -9
  22. package/dist/cjs/modules/debug/transactions.js +4 -5
  23. package/dist/cjs/modules/envelope.js +1 -2
  24. package/dist/cjs/modules/feed.js +3 -4
  25. package/dist/cjs/modules/grantee.js +3 -4
  26. package/dist/cjs/modules/gsoc.js +2 -3
  27. package/dist/cjs/modules/pinning.js +4 -5
  28. package/dist/cjs/modules/pss.js +2 -3
  29. package/dist/cjs/modules/rchash.js +1 -2
  30. package/dist/cjs/modules/soc.js +1 -2
  31. package/dist/cjs/modules/status.js +2 -3
  32. package/dist/cjs/modules/stewardship.js +2 -3
  33. package/dist/cjs/modules/tag.js +5 -6
  34. package/dist/cjs/types/debug.js +3 -3
  35. package/dist/cjs/types/index.js +11 -6
  36. package/dist/cjs/utils/bytes.js +23 -3
  37. package/dist/cjs/utils/chunk-size.js +1 -2
  38. package/dist/cjs/utils/chunk-stream.browser.js +30 -6
  39. package/dist/cjs/utils/chunk-stream.js +3 -4
  40. package/dist/cjs/utils/cid.js +3 -3
  41. package/dist/cjs/utils/collection.browser.js +2 -3
  42. package/dist/cjs/utils/collection.js +5 -6
  43. package/dist/cjs/utils/collection.node.js +2 -3
  44. package/dist/cjs/utils/data.browser.js +1 -2
  45. package/dist/cjs/utils/data.js +1 -2
  46. package/dist/cjs/utils/duration.js +27 -1
  47. package/dist/cjs/utils/expose.js +4 -1
  48. package/dist/cjs/utils/file.js +2 -3
  49. package/dist/cjs/utils/headers.js +2 -3
  50. package/dist/cjs/utils/http.js +25 -5
  51. package/dist/cjs/utils/pss.js +1 -2
  52. package/dist/cjs/utils/redundancy.js +3 -4
  53. package/dist/cjs/utils/size.js +25 -0
  54. package/dist/cjs/utils/stamps.js +60 -11
  55. package/dist/cjs/utils/tar-uploader.browser.js +1 -2
  56. package/dist/cjs/utils/tar-uploader.js +1 -2
  57. package/dist/cjs/utils/tar-writer.browser.js +1 -2
  58. package/dist/cjs/utils/tar-writer.js +1 -2
  59. package/dist/cjs/utils/type.js +37 -25
  60. package/dist/cjs/utils/url.js +3 -4
  61. package/dist/cjs/utils/workaround.js +7 -5
  62. package/dist/index.browser.min.js +1 -1
  63. package/dist/index.browser.min.js.map +1 -1
  64. package/dist/mjs/bee.js +864 -366
  65. package/dist/mjs/chunk/cac.js +21 -30
  66. package/dist/mjs/chunk/soc.js +16 -17
  67. package/dist/mjs/feed/index.js +7 -6
  68. package/dist/mjs/manifest/manifest.js +19 -2
  69. package/dist/mjs/modules/debug/chequebook.js +2 -2
  70. package/dist/mjs/modules/debug/stamps.js +38 -93
  71. package/dist/mjs/modules/debug/states.js +3 -0
  72. package/dist/mjs/modules/debug/status.js +1 -1
  73. package/dist/mjs/types/index.js +8 -3
  74. package/dist/mjs/utils/bytes.js +19 -2
  75. package/dist/mjs/utils/chunk-stream.browser.js +29 -5
  76. package/dist/mjs/utils/duration.js +27 -1
  77. package/dist/mjs/utils/expose.js +1 -1
  78. package/dist/mjs/utils/http.js +25 -3
  79. package/dist/mjs/utils/size.js +25 -0
  80. package/dist/mjs/utils/stamps.js +48 -0
  81. package/dist/mjs/utils/type.js +8 -1
  82. package/dist/mjs/utils/workaround.js +5 -2
  83. package/dist/types/bee.d.ts +756 -252
  84. package/dist/types/chunk/cac.d.ts +27 -13
  85. package/dist/types/chunk/soc.d.ts +43 -11
  86. package/dist/types/index.d.ts +3 -0
  87. package/dist/types/modules/bzz.d.ts +0 -1
  88. package/dist/types/modules/debug/stamps.d.ts +2 -2
  89. package/dist/types/modules/debug/status.d.ts +1 -1
  90. package/dist/types/modules/gsoc.d.ts +0 -1
  91. package/dist/types/modules/pss.d.ts +0 -1
  92. package/dist/types/types/debug.d.ts +2 -1
  93. package/dist/types/types/index.d.ts +53 -6
  94. package/dist/types/utils/constants.d.ts +3 -3
  95. package/dist/types/utils/duration.d.ts +24 -0
  96. package/dist/types/utils/error.d.ts +2 -2
  97. package/dist/types/utils/expose.d.ts +1 -1
  98. package/dist/types/utils/size.d.ts +23 -0
  99. package/dist/types/utils/stamps.d.ts +15 -1
  100. package/dist/types/utils/tar.browser.d.ts +1 -1
  101. package/dist/types/utils/tar.d.ts +0 -1
  102. package/dist/types/utils/type.d.ts +0 -1
  103. package/package.json +10 -13
@@ -1,41 +1,32 @@
1
- import { Binary } from 'cafe-utility';
1
+ import { Binary, Types } from 'cafe-utility';
2
2
  import { Bytes } from "../utils/bytes.js";
3
3
  import { Span } from "../utils/typed-bytes.js";
4
4
  import { calculateChunkAddress } from "./bmt.js";
5
+ import { makeSingleOwnerChunk } from "./soc.js";
5
6
  export const MIN_PAYLOAD_SIZE = 1;
6
7
  export const MAX_PAYLOAD_SIZE = 4096;
7
- const ENCODER = new TextEncoder();
8
- /**
9
- * Creates a content addressed chunk and verifies the payload size.
10
- *
11
- * @param payloadBytes the data to be stored in the chunk
12
- */
13
- export function makeContentAddressedChunk(payloadBytes) {
14
- if (!(payloadBytes instanceof Uint8Array)) {
15
- payloadBytes = ENCODER.encode(payloadBytes);
16
- }
17
- if (payloadBytes.length < MIN_PAYLOAD_SIZE || payloadBytes.length > MAX_PAYLOAD_SIZE) {
18
- throw new RangeError(`payload size ${payloadBytes.length} exceeds limits [${MIN_PAYLOAD_SIZE}, ${MAX_PAYLOAD_SIZE}]`);
19
- }
20
- const span = Span.fromBigInt(BigInt(payloadBytes.length));
21
- const data = Binary.concatBytes(span.toUint8Array(), payloadBytes);
22
- return {
23
- data,
24
- span,
25
- payload: Bytes.fromSlice(data, Span.LENGTH),
26
- address: calculateChunkAddress(data)
27
- };
8
+ export function unmarshalContentAddressedChunk(data) {
9
+ data = new Bytes(data);
10
+ return makeContentAddressedChunk(data.toUint8Array().slice(Span.LENGTH), Span.fromSlice(data.toUint8Array(), 0));
28
11
  }
29
- export function asContentAddressedChunk(chunkBytes) {
30
- if (chunkBytes.length < MIN_PAYLOAD_SIZE + Span.LENGTH || chunkBytes.length > MAX_PAYLOAD_SIZE + Span.LENGTH) {
31
- throw new RangeError(`chunk size ${chunkBytes.length} exceeds limits [${MIN_PAYLOAD_SIZE + Span.LENGTH}, ${Span.LENGTH}]`);
12
+ export function makeContentAddressedChunk(rawPayload, span) {
13
+ if (Types.isString(rawPayload)) {
14
+ rawPayload = Bytes.fromUtf8(rawPayload);
15
+ }
16
+ if (rawPayload.length < MIN_PAYLOAD_SIZE || rawPayload.length > MAX_PAYLOAD_SIZE) {
17
+ throw new RangeError(`payload size ${rawPayload.length} exceeds limits [${MIN_PAYLOAD_SIZE}, ${MAX_PAYLOAD_SIZE}]`);
32
18
  }
33
- const span = Span.fromSlice(chunkBytes, 0);
34
- const data = Binary.concatBytes(span.toUint8Array(), chunkBytes.slice(Span.LENGTH));
19
+ const typedSpan = span ? typeof span === 'bigint' ? Span.fromBigInt(span) : span : Span.fromBigInt(BigInt(rawPayload.length));
20
+ const payload = new Bytes(rawPayload);
21
+ const data = Binary.concatBytes(typedSpan.toUint8Array(), payload.toUint8Array());
22
+ const address = calculateChunkAddress(data);
35
23
  return {
36
24
  data,
37
- span,
38
- payload: Bytes.fromSlice(data, Span.LENGTH),
39
- address: calculateChunkAddress(data)
25
+ span: typedSpan,
26
+ payload,
27
+ address,
28
+ toSingleOwnerChunk: (identifier, signer) => {
29
+ return makeSingleOwnerChunk(address, typedSpan, payload, identifier, signer);
30
+ }
40
31
  };
41
32
  }
@@ -5,10 +5,10 @@ import { Bytes } from "../utils/bytes.js";
5
5
  import { BeeError } from "../utils/error.js";
6
6
  import { EthAddress, Identifier, PrivateKey, Reference, Signature, Span } from "../utils/typed-bytes.js";
7
7
  import { calculateChunkAddress } from "./bmt.js";
8
- import { asContentAddressedChunk, makeContentAddressedChunk } from "./cac.js";
8
+ import { makeContentAddressedChunk } from "./cac.js";
9
9
  const SOC_SIGNATURE_OFFSET = Identifier.LENGTH;
10
- const SOC_SPAN_OFFSET = SOC_SIGNATURE_OFFSET + Signature.LENGTH;
11
- const SOC_PAYLOAD_OFFSET = SOC_SPAN_OFFSET + Span.LENGTH;
10
+ const SOC_SPAN_OFFSET = Identifier.LENGTH + Signature.LENGTH;
11
+ const SOC_PAYLOAD_OFFSET = Identifier.LENGTH + Signature.LENGTH + Span.LENGTH;
12
12
  function recoverChunkOwner(data) {
13
13
  const cacData = data.slice(SOC_SPAN_OFFSET);
14
14
  const chunkAddress = calculateChunkAddress(cacData);
@@ -19,21 +19,22 @@ function recoverChunkOwner(data) {
19
19
  return ownerAddress;
20
20
  }
21
21
  /**
22
- * Verifies if the data is a valid single owner chunk
22
+ * Unmarshals arbitrary data into a Single Owner Chunk.
23
+ * Throws an error if the data is not a valid SOC.
23
24
  *
24
25
  * @param data The chunk data
25
26
  * @param address The address of the single owner chunk
26
27
  *
27
28
  * @returns a single owner chunk or throws error
28
29
  */
29
- export function makeSingleOwnerChunkFromData(data, address) {
30
+ export function unmarshalSingleOwnerChunk(data, address) {
30
31
  data = data instanceof Bytes ? data.toUint8Array() : data;
31
32
  address = new Reference(address);
32
33
  const ownerAddress = recoverChunkOwner(data);
33
34
  const identifier = Bytes.fromSlice(data, 0, Identifier.LENGTH);
34
35
  const socAddress = new Reference(Binary.keccak256(Binary.concatBytes(identifier.toUint8Array(), ownerAddress.toUint8Array())));
35
36
  if (!Binary.equals(address.toUint8Array(), socAddress.toUint8Array())) {
36
- throw new BeeError('SOC Data does not match given address!');
37
+ throw new BeeError('SOC data does not match given address!');
37
38
  }
38
39
  const signature = Signature.fromSlice(data, SOC_SIGNATURE_OFFSET);
39
40
  const span = Span.fromSlice(data, SOC_SPAN_OFFSET);
@@ -58,21 +59,19 @@ export function makeSOCAddress(identifier, address) {
58
59
  * @param identifier The identifier of the chunk
59
60
  * @param signer The signer interface for signing the chunk
60
61
  */
61
- export function makeSingleOwnerChunk(chunk, identifier, signer) {
62
+ export function makeSingleOwnerChunk(address, span, payload, identifier, signer) {
62
63
  identifier = new Identifier(identifier);
63
64
  signer = new PrivateKey(signer);
64
- const address = makeSOCAddress(identifier, signer.publicKey().address());
65
- const signature = signer.sign(Binary.concatBytes(identifier.toUint8Array(), chunk.address.toUint8Array()));
66
- const data = Binary.concatBytes(identifier.toUint8Array(), signature.toUint8Array(), chunk.data);
67
- const span = Span.fromSlice(chunk.data, 0);
68
- const payload = Bytes.fromSlice(chunk.data, Span.LENGTH);
65
+ const socAddress = makeSOCAddress(identifier, signer.publicKey().address());
66
+ const signature = signer.sign(Binary.concatBytes(identifier.toUint8Array(), address.toUint8Array()));
67
+ const data = Binary.concatBytes(identifier.toUint8Array(), signature.toUint8Array(), span.toUint8Array(), payload.toUint8Array());
69
68
  return {
70
69
  data,
71
70
  identifier,
72
71
  signature,
73
72
  span,
74
73
  payload,
75
- address,
74
+ address: socAddress,
76
75
  owner: signer.publicKey().address()
77
76
  };
78
77
  }
@@ -104,13 +103,13 @@ export async function uploadSingleOwnerChunkData(requestOptions, signer, stamp,
104
103
  signer = new PrivateKey(signer);
105
104
  identifier = new Identifier(identifier);
106
105
  const cac = makeContentAddressedChunk(data);
107
- const soc = makeSingleOwnerChunk(cac, identifier, signer);
106
+ const soc = cac.toSingleOwnerChunk(identifier, signer);
108
107
  return uploadSingleOwnerChunk(requestOptions, soc, stamp, options);
109
108
  }
110
- export async function uploadSingleOwnerChunkWithWrappedChunk(requestOptions, signer, stamp, identifier, rootChunk, options) {
109
+ export async function uploadSingleOwnerChunkWithWrappedChunk(requestOptions, signer, stamp, identifier, wrappedChunk, options) {
111
110
  signer = new PrivateKey(signer);
112
111
  identifier = new Identifier(identifier);
113
- const soc = makeSingleOwnerChunk(asContentAddressedChunk(rootChunk), identifier, signer);
112
+ const soc = wrappedChunk.toSingleOwnerChunk(identifier, signer);
114
113
  return uploadSingleOwnerChunk(requestOptions, soc, stamp, options);
115
114
  }
116
115
  /**
@@ -125,5 +124,5 @@ export async function downloadSingleOwnerChunk(requestOptions, ownerAddress, ide
125
124
  ownerAddress = new EthAddress(ownerAddress);
126
125
  const address = makeSOCAddress(identifier, ownerAddress);
127
126
  const cac = await chunkAPI.download(requestOptions, address.toHex());
128
- return makeSingleOwnerChunkFromData(cac, address);
127
+ return unmarshalSingleOwnerChunk(cac, address);
129
128
  }
@@ -1,13 +1,13 @@
1
1
  import { Binary, Optional, Types } from 'cafe-utility';
2
- import { asContentAddressedChunk } from "../chunk/cac.js";
3
- import { makeSingleOwnerChunkFromData, uploadSingleOwnerChunkData, uploadSingleOwnerChunkWithWrappedChunk } from "../chunk/soc.js";
2
+ import { makeContentAddressedChunk, unmarshalContentAddressedChunk } from "../chunk/cac.js";
3
+ import { unmarshalSingleOwnerChunk, uploadSingleOwnerChunkData, uploadSingleOwnerChunkWithWrappedChunk } from "../chunk/soc.js";
4
4
  import * as bytes from "../modules/bytes.js";
5
5
  import * as chunkAPI from "../modules/chunk.js";
6
6
  import { fetchLatestFeedUpdate, probeFeed } from "../modules/feed.js";
7
7
  import { Bytes } from "../utils/bytes.js";
8
8
  import { BeeResponseError } from "../utils/error.js";
9
9
  import { ResourceLocator } from "../utils/resource-locator.js";
10
- import { FeedIndex, Identifier, Reference, Signature } from "../utils/typed-bytes.js";
10
+ import { FeedIndex, Reference } from "../utils/typed-bytes.js";
11
11
  import { makeFeedIdentifier } from "./identifier.js";
12
12
  const TIMESTAMP_PAYLOAD_OFFSET = 0;
13
13
  const TIMESTAMP_PAYLOAD_SIZE = 8;
@@ -40,7 +40,7 @@ export async function updateFeedWithPayload(requestOptions, signer, topic, data,
40
40
  const identifier = makeFeedIdentifier(topic, nextIndex);
41
41
  if (data.length > 4096) {
42
42
  const uploadResult = await bytes.upload(requestOptions, data, postageBatchId, options);
43
- const rootChunk = await chunkAPI.download(requestOptions, uploadResult.reference);
43
+ const rootChunk = unmarshalContentAddressedChunk(await chunkAPI.download(requestOptions, uploadResult.reference));
44
44
  return uploadSingleOwnerChunkWithWrappedChunk(requestOptions, signer, postageBatchId, identifier, rootChunk, options);
45
45
  }
46
46
  return uploadSingleOwnerChunkData(requestOptions, signer, postageBatchId, identifier, Types.isString(data) ? Bytes.fromUtf8(data).toUint8Array() : data, options);
@@ -53,7 +53,7 @@ export async function downloadFeedUpdate(requestOptions, owner, topic, index, ha
53
53
  index = typeof index === 'number' ? FeedIndex.fromBigInt(BigInt(index)) : index;
54
54
  const address = getFeedUpdateChunkReference(owner, topic, index);
55
55
  const data = await chunkAPI.download(requestOptions, address.toHex());
56
- const soc = makeSingleOwnerChunkFromData(data, address);
56
+ const soc = unmarshalSingleOwnerChunk(data, address);
57
57
  let timestamp = Optional.empty();
58
58
  if (hasTimestamp) {
59
59
  const timestampBytes = Bytes.fromSlice(soc.payload.toUint8Array(), TIMESTAMP_PAYLOAD_OFFSET, TIMESTAMP_PAYLOAD_SIZE);
@@ -68,7 +68,8 @@ export async function downloadFeedUpdateAsCAC(requestOptions, owner, topic, inde
68
68
  index = typeof index === 'number' ? FeedIndex.fromBigInt(BigInt(index)) : index;
69
69
  const address = getFeedUpdateChunkReference(owner, topic, index);
70
70
  const data = await chunkAPI.download(requestOptions, address);
71
- return asContentAddressedChunk(data.slice(Identifier.LENGTH + Signature.LENGTH));
71
+ const soc = unmarshalSingleOwnerChunk(data, address);
72
+ return makeContentAddressedChunk(soc.payload, soc.span);
72
73
  }
73
74
  export function makeFeedReader(requestOptions, topic, owner) {
74
75
  // TODO: remove after enough time has passed in deprecated version
@@ -320,7 +320,17 @@ export class MantarayNode {
320
320
  */
321
321
  async saveRecursively(bee, postageBatchId, options, requestOptions) {
322
322
  for (const fork of this.forks.values()) {
323
- await fork.node.saveRecursively(bee, postageBatchId, options, requestOptions);
323
+ const uploadResult = await fork.node.saveRecursively(bee, postageBatchId, options, requestOptions);
324
+ if (options?.act) {
325
+ let historyAddress;
326
+ uploadResult.historyAddress.ifPresent(ref => historyAddress = ref);
327
+ if (historyAddress) {
328
+ if (!fork.node.metadata) {
329
+ fork.node.metadata = {};
330
+ }
331
+ fork.node.metadata['swarm-act-history-address'] = historyAddress.toHex();
332
+ }
333
+ }
324
334
  }
325
335
  const result = await bee.uploadData(postageBatchId, await this.marshal(), options, requestOptions);
326
336
  this.selfAddress = result.reference.toUint8Array();
@@ -334,7 +344,14 @@ export class MantarayNode {
334
344
  if (!fork.node.selfAddress) {
335
345
  throw Error('MantarayNode#loadRecursively fork.node.selfAddress is not set');
336
346
  }
337
- const node = await MantarayNode.unmarshal(bee, fork.node.selfAddress, options, requestOptions);
347
+ let downloadOptions = options;
348
+ if (fork.node.metadata && fork.node.metadata['swarm-act-history-address']) {
349
+ downloadOptions = {
350
+ ...options,
351
+ actHistoryAddress: fork.node.metadata['swarm-act-history-address']
352
+ };
353
+ }
354
+ const node = await MantarayNode.unmarshal(bee, fork.node.selfAddress, downloadOptions, requestOptions);
338
355
  fork.node.targetAddress = node.targetAddress;
339
356
  fork.node.forks = node.forks;
340
357
  fork.node.path = fork.prefix;
@@ -19,9 +19,9 @@ export async function getChequebookAddress(requestOptions) {
19
19
  name: 'response.data'
20
20
  });
21
21
  return {
22
- chequebookAddress: Types.asString(body.chequebookAddress, {
22
+ chequebookAddress: new EthAddress(Types.asString(body.chequebookAddress, {
23
23
  name: 'chequebookAddress'
24
- })
24
+ }))
25
25
  };
26
26
  }
27
27
  /**
@@ -1,11 +1,8 @@
1
1
  import { Types } from 'cafe-utility';
2
- import { Duration } from "../../utils/duration.js";
3
2
  import { http } from "../../utils/http.js";
4
- import { Size } from "../../utils/size.js";
5
- import { getStampEffectiveBytes, getStampTheoreticalBytes, getStampUsage } from "../../utils/stamps.js";
3
+ import { mapPostageBatch } from "../../utils/stamps.js";
6
4
  import { asNumberString } from "../../utils/type.js";
7
5
  import { BatchId, EthAddress } from "../../utils/typed-bytes.js";
8
- import { normalizeBatchTTL } from "../../utils/workaround.js";
9
6
  const STAMPS_ENDPOINT = 'stamps';
10
7
  const BATCHES_ENDPOINT = 'batches';
11
8
  export async function getGlobalPostageBatches(requestOptions) {
@@ -63,53 +60,9 @@ export async function getAllPostageBatches(requestOptions) {
63
60
  }).map(x => Types.asObject(x, {
64
61
  name: 'stamp'
65
62
  }));
66
- return stamps.map(x => {
67
- const utilization = Types.asNumber(x.utilization, {
68
- name: 'utilization'
69
- });
70
- const depth = Types.asNumber(x.depth, {
71
- name: 'depth'
72
- });
73
- const bucketDepth = Types.asNumber(x.bucketDepth, {
74
- name: 'bucketDepth'
75
- });
76
- const usage = getStampUsage(utilization, depth, bucketDepth);
77
- const batchTTL = normalizeBatchTTL(Types.asNumber(x.batchTTL, {
78
- name: 'batchTTL'
79
- }));
80
- const duration = Duration.fromSeconds(batchTTL);
81
- return {
82
- batchID: new BatchId(Types.asString(x.batchID, {
83
- name: 'batchID'
84
- })),
85
- utilization,
86
- usable: Types.asBoolean(x.usable, {
87
- name: 'usable'
88
- }),
89
- label: Types.asEmptiableString(x.label, {
90
- name: 'label'
91
- }),
92
- depth,
93
- amount: asNumberString(x.amount, {
94
- name: 'amount'
95
- }),
96
- bucketDepth,
97
- blockNumber: Types.asNumber(x.blockNumber, {
98
- name: 'blockNumber'
99
- }),
100
- immutableFlag: Types.asBoolean(x.immutableFlag, {
101
- name: 'immutableFlag'
102
- }),
103
- usage,
104
- usageText: `${Math.round(usage * 100)}%`,
105
- size: Size.fromBytes(getStampEffectiveBytes(depth)),
106
- remainingSize: Size.fromBytes(Math.ceil(getStampEffectiveBytes(depth) * (1 - usage))),
107
- theoreticalSize: Size.fromBytes(getStampTheoreticalBytes(depth)),
108
- duration
109
- };
110
- });
63
+ return stamps.map(x => mapPostageBatch(validateRawPostageBatch(x)));
111
64
  }
112
- export async function getPostageBatch(requestOptions, postageBatchId) {
65
+ export async function getPostageBatch(requestOptions, postageBatchId, encryption, erasureCodeLevel) {
113
66
  const response = await http(requestOptions, {
114
67
  method: 'get',
115
68
  url: `${STAMPS_ENDPOINT}/${postageBatchId}`,
@@ -118,49 +71,7 @@ export async function getPostageBatch(requestOptions, postageBatchId) {
118
71
  const body = Types.asObject(response.data, {
119
72
  name: 'response.data'
120
73
  });
121
- const utilization = Types.asNumber(body.utilization, {
122
- name: 'utilization'
123
- });
124
- const depth = Types.asNumber(body.depth, {
125
- name: 'depth'
126
- });
127
- const bucketDepth = Types.asNumber(body.bucketDepth, {
128
- name: 'bucketDepth'
129
- });
130
- const usage = getStampUsage(utilization, depth, bucketDepth);
131
- const batchTTL = normalizeBatchTTL(Types.asNumber(body.batchTTL, {
132
- name: 'batchTTL'
133
- }));
134
- const duration = Duration.fromSeconds(batchTTL);
135
- return {
136
- batchID: new BatchId(Types.asString(body.batchID, {
137
- name: 'batchID'
138
- })),
139
- utilization,
140
- usable: Types.asBoolean(body.usable, {
141
- name: 'usable'
142
- }),
143
- label: Types.asEmptiableString(body.label, {
144
- name: 'label'
145
- }),
146
- depth,
147
- amount: asNumberString(body.amount, {
148
- name: 'amount'
149
- }),
150
- bucketDepth,
151
- blockNumber: Types.asNumber(body.blockNumber, {
152
- name: 'blockNumber'
153
- }),
154
- immutableFlag: Types.asBoolean(body.immutableFlag, {
155
- name: 'immutableFlag'
156
- }),
157
- usage,
158
- usageText: `${Math.round(usage * 100)}%`,
159
- size: Size.fromBytes(getStampEffectiveBytes(depth)),
160
- remainingSize: Size.fromBytes(Math.ceil(getStampEffectiveBytes(depth) * (1 - usage))),
161
- theoreticalSize: Size.fromBytes(getStampTheoreticalBytes(depth)),
162
- duration
163
- };
74
+ return mapPostageBatch(validateRawPostageBatch(body), encryption, erasureCodeLevel);
164
75
  }
165
76
  export async function getPostageBatchBuckets(requestOptions, postageBatchId) {
166
77
  const response = await http(requestOptions, {
@@ -244,4 +155,38 @@ export async function diluteBatch(requestOptions, id, depth) {
244
155
  return new BatchId(Types.asString(body.batchID, {
245
156
  name: 'batchID'
246
157
  }));
158
+ }
159
+ function validateRawPostageBatch(raw) {
160
+ return {
161
+ amount: asNumberString(raw.amount, {
162
+ name: 'amount'
163
+ }),
164
+ batchID: Types.asString(raw.batchID, {
165
+ name: 'batchID'
166
+ }),
167
+ batchTTL: Types.asNumber(raw.batchTTL, {
168
+ name: 'batchTTL'
169
+ }),
170
+ bucketDepth: Types.asNumber(raw.bucketDepth, {
171
+ name: 'bucketDepth'
172
+ }),
173
+ blockNumber: Types.asNumber(raw.blockNumber, {
174
+ name: 'blockNumber'
175
+ }),
176
+ depth: Types.asNumber(raw.depth, {
177
+ name: 'depth'
178
+ }),
179
+ immutableFlag: Types.asBoolean(raw.immutableFlag, {
180
+ name: 'immutableFlag'
181
+ }),
182
+ label: Types.asEmptiableString(raw.label, {
183
+ name: 'label'
184
+ }),
185
+ usable: Types.asBoolean(raw.usable, {
186
+ name: 'usable'
187
+ }),
188
+ utilization: Types.asNumber(raw.utilization, {
189
+ name: 'utilization'
190
+ })
191
+ };
247
192
  }
@@ -30,6 +30,9 @@ export async function getReserveState(requestOptions) {
30
30
  }),
31
31
  storageRadius: Types.asNumber(body.storageRadius, {
32
32
  name: 'storageRadius'
33
+ }),
34
+ reserveCapacityDoubling: Types.asNumber(body.reserveCapacityDoubling, {
35
+ name: 'reserveCapacityDoubling'
33
36
  })
34
37
  };
35
38
  }
@@ -2,7 +2,7 @@ import { Types } from 'cafe-utility';
2
2
  import getMajorSemver from 'semver/functions/major.js';
3
3
  import { toBeeMode } from "../../types/debug.js";
4
4
  import { http } from "../../utils/http.js";
5
- export const SUPPORTED_BEE_VERSION_EXACT = '2.6.0-d0aa8b93';
5
+ export const SUPPORTED_BEE_VERSION_EXACT = '2.7.0-6ddf9b45';
6
6
  export const SUPPORTED_BEE_VERSION = SUPPORTED_BEE_VERSION_EXACT.split('-')[0];
7
7
  export const SUPPORTED_API_VERSION = '7.3.0';
8
8
  const NODE_INFO_URL = 'node';
@@ -4,16 +4,21 @@ export const BRANCHES = 128;
4
4
  export const CHUNK_SIZE = SECTION_SIZE * BRANCHES;
5
5
  export const PSS_TARGET_HEX_LENGTH_MAX = 4;
6
6
  /**
7
- * Minimal depth that can be used for creation of postage batch
7
+ * Minimum postage batch depth.
8
8
  */
9
9
  export const STAMPS_DEPTH_MIN = 17;
10
10
  /**
11
- * Maximal depth that can be used for creation of postage batch
11
+ * Maximum postage batch depth.
12
12
  */
13
13
  export const STAMPS_DEPTH_MAX = 255;
14
+ /**
15
+ * Minimum tags API page size.
16
+ */
14
17
  export const TAGS_LIMIT_MIN = 1;
18
+ /**
19
+ * Maximum tags API page size.
20
+ */
15
21
  export const TAGS_LIMIT_MAX = 1000;
16
- export const FEED_INDEX_HEX_LENGTH = 16;
17
22
  /**
18
23
  * Add redundancy to the data being uploaded so that downloaders can download it with better UX.
19
24
  * 0 value is default and does not add any redundancy to the file.
@@ -1,8 +1,13 @@
1
- import { Binary, Types } from 'cafe-utility';
1
+ import { Binary, Objects, Types } from 'cafe-utility';
2
+ import _debug from 'debug';
3
+ const debug = _debug('bee-js:bytes');
2
4
  const DECODER = new TextDecoder();
3
5
  const ENCODER = new TextEncoder();
4
6
  export class Bytes {
5
7
  constructor(bytes, byteLength) {
8
+ if (!bytes) {
9
+ throw Error(`Bytes#constructor: constructor parameter is falsy: ${bytes}`);
10
+ }
6
11
  if (bytes instanceof Bytes) {
7
12
  this.bytes = bytes.bytes;
8
13
  } else if (typeof bytes === 'string') {
@@ -11,8 +16,20 @@ export class Bytes {
11
16
  }));
12
17
  } else if (bytes instanceof ArrayBuffer) {
13
18
  this.bytes = new Uint8Array(bytes);
14
- } else {
19
+ } else if (bytes instanceof Uint8Array) {
15
20
  this.bytes = bytes;
21
+ } else {
22
+ const unknownInput = bytes;
23
+ const toHex = Objects.getDeep(unknownInput, 'toHex');
24
+ if (Types.isFunction(toHex)) {
25
+ const hex = toHex.call(unknownInput);
26
+ this.bytes = Binary.hexToUint8Array(Types.asHexString(hex, {
27
+ name: 'Bytes#constructor(bytes)'
28
+ }));
29
+ } else {
30
+ debug('bytes', bytes);
31
+ throw new Error(`Bytes#constructor: unsupported type: ${typeof bytes}`);
32
+ }
16
33
  }
17
34
  this.length = this.bytes.length;
18
35
  if (byteLength) {
@@ -12,6 +12,10 @@ export async function streamDirectory(_bee, _dir, _postageBatchId, _onUploadProg
12
12
  throw new Error('Streaming directories is not supported in browsers!');
13
13
  }
14
14
  export async function streamFiles(bee, files, postageBatchId, onUploadProgress, options, requestOptions) {
15
+ const signal = requestOptions?.signal;
16
+ if (signal?.aborted) {
17
+ throw new Error('Request aborted');
18
+ }
15
19
  const queue = new AsyncQueue(64, 64);
16
20
  let total = 0;
17
21
  let processed = 0;
@@ -21,15 +25,28 @@ export async function streamFiles(bee, files, postageBatchId, onUploadProgress,
21
25
  postageBatchId = new BatchId(postageBatchId);
22
26
  async function onChunk(chunk) {
23
27
  await queue.enqueue(async () => {
24
- await bee.uploadChunk(postageBatchId, chunk.build(), options, requestOptions);
25
- onUploadProgress?.({
26
- total,
27
- processed: ++processed
28
- });
28
+ if (signal?.aborted) {
29
+ return;
30
+ }
31
+ try {
32
+ await bee.uploadChunk(postageBatchId, chunk.build(), options, requestOptions);
33
+ onUploadProgress?.({
34
+ total,
35
+ processed: ++processed
36
+ });
37
+ } catch (err) {
38
+ if (signal?.aborted) {
39
+ return;
40
+ }
41
+ throw err;
42
+ }
29
43
  });
30
44
  }
31
45
  const mantaray = new MantarayNode();
32
46
  for (const file of files) {
47
+ if (signal?.aborted) {
48
+ throw new Error('Request aborted');
49
+ }
33
50
  const rootChunk = await new Promise((resolve, reject) => {
34
51
  const tree = new MerkleTree(onChunk);
35
52
  let offset = 0;
@@ -38,6 +55,10 @@ export async function streamFiles(bee, files, postageBatchId, onUploadProgress,
38
55
  reject(reader.error);
39
56
  };
40
57
  const readNextChunk = async () => {
58
+ if (signal?.aborted) {
59
+ reject(new Error('Request aborted'));
60
+ return;
61
+ }
41
62
  if (offset >= file.size) {
42
63
  const rootChunk = await tree.finalize();
43
64
  resolve(rootChunk);
@@ -75,6 +96,9 @@ export async function streamFiles(bee, files, postageBatchId, onUploadProgress,
75
96
  });
76
97
  }
77
98
  }
99
+ if (signal?.aborted) {
100
+ throw new Error('Request aborted');
101
+ }
78
102
  return mantaray.saveRecursively(bee, postageBatchId, options, requestOptions);
79
103
  }
80
104
  function maybeEnrichMime(mime) {
@@ -3,7 +3,7 @@ export class Duration {
3
3
  constructor(seconds) {
4
4
  this.seconds = Math.ceil(seconds);
5
5
  if (seconds < 0) {
6
- throw Error('Duration cannot be negative');
6
+ this.seconds = 0;
7
7
  }
8
8
  }
9
9
  static fromMilliseconds(milliseconds) {
@@ -27,6 +27,32 @@ export class Duration {
27
27
  static fromEndDate(endDate, startDate) {
28
28
  return new Duration((endDate.getTime() - (startDate ?? new Date()).getTime()) / 1000);
29
29
  }
30
+ /**
31
+ * Parses a duration string and returns a `Duration` instance.
32
+ *
33
+ * Case insensitive. E.g. both `"28h"` and `"1D"` are valid.
34
+ *
35
+ * Whitespaces are ignored. E.g. both `"5 d"` and `"2weeks"` are valid.
36
+ *
37
+ * Decimal numbers are supported. E.g. `"1.5h"` is valid.
38
+ *
39
+ * Supported units:
40
+ *
41
+ * - ms, milli, millis, millisecond, milliseconds
42
+ * - s, sec, second, seconds
43
+ * - m, min, minute, minutes
44
+ * - h, hour, hours
45
+ * - d, day, days
46
+ * - w, week, weeks
47
+ * - month, months
48
+ * - y, year, years
49
+ *
50
+ * @param duration - A string representing a duration
51
+ * @returns a `Duration` instance
52
+ */
53
+ static parseFromString(duration) {
54
+ return Duration.fromSeconds(Dates.make(duration) / 1000);
55
+ }
30
56
  toSeconds() {
31
57
  return this.seconds;
32
58
  }
@@ -2,4 +2,4 @@ export { getCollectionSize, makeCollectionFromFileList } from "./collection.js";
2
2
  export { getFolderSize } from "./collection.node.js";
3
3
  export { makeMaxTarget } from "./pss.js";
4
4
  export { approximateOverheadForRedundancyLevel, getRedundancyStat, getRedundancyStats } from "./redundancy.js";
5
- export { getAmountForDuration, getDepthForSize, getStampCost, getStampDuration, getStampEffectiveBytes, getStampEffectiveBytesBreakpoints, getStampTheoreticalBytes, getStampUsage } from "./stamps.js";
5
+ export { convertEnvelopeToMarshaledStamp, getAmountForDuration, getDepthForSize, getStampCost, getStampDuration, getStampEffectiveBytes, getStampEffectiveBytesBreakpoints, getStampTheoreticalBytes, getStampUsage, mapPostageBatch, unmapPostageBatch } from "./stamps.js";