@upcoming/bee-js 0.11.0 → 0.13.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.
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.makeContentAddressedChunk = exports.MAX_PAYLOAD_SIZE = exports.MIN_PAYLOAD_SIZE = void 0;
3
+ exports.asContentAddressedChunk = exports.makeContentAddressedChunk = exports.MAX_PAYLOAD_SIZE = exports.MIN_PAYLOAD_SIZE = void 0;
4
4
  const cafe_utility_1 = require("cafe-utility");
5
5
  const bytes_1 = require("../utils/bytes");
6
6
  const typed_bytes_1 = require("../utils/typed-bytes");
@@ -30,3 +30,17 @@ function makeContentAddressedChunk(payloadBytes) {
30
30
  };
31
31
  }
32
32
  exports.makeContentAddressedChunk = makeContentAddressedChunk;
33
+ function asContentAddressedChunk(chunkBytes) {
34
+ if (chunkBytes.length < exports.MIN_PAYLOAD_SIZE + typed_bytes_1.Span.LENGTH || chunkBytes.length > exports.MAX_PAYLOAD_SIZE + typed_bytes_1.Span.LENGTH) {
35
+ throw new RangeError(`chunk size ${chunkBytes.length} exceeds limits [${exports.MIN_PAYLOAD_SIZE + typed_bytes_1.Span.LENGTH}, ${typed_bytes_1.Span.LENGTH}]`);
36
+ }
37
+ const span = typed_bytes_1.Span.fromSlice(chunkBytes, 0);
38
+ const data = cafe_utility_1.Binary.concatBytes(span.toUint8Array(), chunkBytes.slice(typed_bytes_1.Span.LENGTH));
39
+ return {
40
+ data,
41
+ span,
42
+ payload: bytes_1.Bytes.fromSlice(data, typed_bytes_1.Span.LENGTH),
43
+ address: (0, bmt_1.calculateChunkAddress)(data),
44
+ };
45
+ }
46
+ exports.asContentAddressedChunk = asContentAddressedChunk;
@@ -23,7 +23,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
23
23
  return result;
24
24
  };
25
25
  Object.defineProperty(exports, "__esModule", { value: true });
26
- exports.downloadSingleOwnerChunk = exports.uploadSingleOwnerChunkData = exports.uploadSingleOwnerChunk = exports.makeSingleOwnerChunk = exports.makeSOCAddress = exports.makeSingleOwnerChunkFromData = void 0;
26
+ exports.downloadSingleOwnerChunk = exports.uploadSingleOwnerChunkWithWrappedChunk = exports.uploadSingleOwnerChunkData = exports.uploadSingleOwnerChunk = exports.makeSingleOwnerChunk = exports.makeSOCAddress = exports.makeSingleOwnerChunkFromData = void 0;
27
27
  const cafe_utility_1 = require("cafe-utility");
28
28
  const chunkAPI = __importStar(require("../modules/chunk"));
29
29
  const socAPI = __importStar(require("../modules/soc"));
@@ -138,6 +138,13 @@ async function uploadSingleOwnerChunkData(requestOptions, signer, stamp, identif
138
138
  return uploadSingleOwnerChunk(requestOptions, soc, stamp, options);
139
139
  }
140
140
  exports.uploadSingleOwnerChunkData = uploadSingleOwnerChunkData;
141
+ async function uploadSingleOwnerChunkWithWrappedChunk(requestOptions, signer, stamp, identifier, rootChunk, options) {
142
+ signer = new typed_bytes_1.PrivateKey(signer);
143
+ identifier = new typed_bytes_1.Identifier(identifier);
144
+ const soc = makeSingleOwnerChunk((0, cac_1.asContentAddressedChunk)(rootChunk), identifier, signer);
145
+ return uploadSingleOwnerChunk(requestOptions, soc, stamp, options);
146
+ }
147
+ exports.uploadSingleOwnerChunkWithWrappedChunk = uploadSingleOwnerChunkWithWrappedChunk;
141
148
  /**
142
149
  * Helper function to download SOC.
143
150
  *
@@ -23,13 +23,16 @@ var __importStar = (this && this.__importStar) || function (mod) {
23
23
  return result;
24
24
  };
25
25
  Object.defineProperty(exports, "__esModule", { value: true });
26
- exports.makeFeedWriter = exports.makeFeedReader = exports.downloadFeedUpdate = exports.getFeedUpdateChunkReference = exports.updateFeed = exports.findNextIndex = void 0;
26
+ exports.makeFeedWriter = exports.makeFeedReader = exports.downloadFeedUpdateAsCAC = exports.downloadFeedUpdate = exports.getFeedUpdateChunkReference = exports.updateFeedWithPayload = exports.updateFeedWithReference = exports.findNextIndex = void 0;
27
27
  const cafe_utility_1 = require("cafe-utility");
28
+ const cac_1 = require("../chunk/cac");
28
29
  const soc_1 = require("../chunk/soc");
30
+ const bytes = __importStar(require("../modules/bytes"));
29
31
  const chunkAPI = __importStar(require("../modules/chunk"));
30
32
  const feed_1 = require("../modules/feed");
31
33
  const bytes_1 = require("../utils/bytes");
32
34
  const error_1 = require("../utils/error");
35
+ const resource_locator_1 = require("../utils/resource-locator");
33
36
  const typed_bytes_1 = require("../utils/typed-bytes");
34
37
  const identifier_1 = require("./identifier");
35
38
  const TIMESTAMP_PAYLOAD_OFFSET = 0;
@@ -51,7 +54,7 @@ async function findNextIndex(requestOptions, owner, topic) {
51
54
  }
52
55
  }
53
56
  exports.findNextIndex = findNextIndex;
54
- async function updateFeed(requestOptions, signer, topic, reference, postageBatchId, options) {
57
+ async function updateFeedWithReference(requestOptions, signer, topic, reference, postageBatchId, options) {
55
58
  reference = new typed_bytes_1.Reference(reference);
56
59
  const nextIndex = options?.index ?? (await findNextIndex(requestOptions, signer.publicKey().address(), topic));
57
60
  const identifier = (0, identifier_1.makeFeedIdentifier)(topic, nextIndex);
@@ -60,50 +63,105 @@ async function updateFeed(requestOptions, signer, topic, reference, postageBatch
60
63
  const payloadBytes = cafe_utility_1.Binary.concatBytes(timestamp, reference.toUint8Array());
61
64
  return (0, soc_1.uploadSingleOwnerChunkData)(requestOptions, signer, postageBatchId, identifier, payloadBytes, options);
62
65
  }
63
- exports.updateFeed = updateFeed;
66
+ exports.updateFeedWithReference = updateFeedWithReference;
67
+ async function updateFeedWithPayload(requestOptions, signer, topic, data, postageBatchId, options) {
68
+ const nextIndex = options?.index ?? (await findNextIndex(requestOptions, signer.publicKey().address(), topic));
69
+ const identifier = (0, identifier_1.makeFeedIdentifier)(topic, nextIndex);
70
+ if (data.length > 4096) {
71
+ const uploadResult = await bytes.upload(requestOptions, data, postageBatchId, options);
72
+ const rootChunk = await chunkAPI.download(requestOptions, uploadResult.reference);
73
+ return (0, soc_1.uploadSingleOwnerChunkWithWrappedChunk)(requestOptions, signer, postageBatchId, identifier, rootChunk, options);
74
+ }
75
+ return (0, soc_1.uploadSingleOwnerChunkData)(requestOptions, signer, postageBatchId, identifier, cafe_utility_1.Types.isString(data) ? bytes_1.Bytes.fromUtf8(data).toUint8Array() : data, options);
76
+ }
77
+ exports.updateFeedWithPayload = updateFeedWithPayload;
64
78
  function getFeedUpdateChunkReference(owner, topic, index) {
65
79
  const identifier = (0, identifier_1.makeFeedIdentifier)(topic, index);
66
80
  return new typed_bytes_1.Reference(cafe_utility_1.Binary.keccak256(cafe_utility_1.Binary.concatBytes(identifier.toUint8Array(), owner.toUint8Array())));
67
81
  }
68
82
  exports.getFeedUpdateChunkReference = getFeedUpdateChunkReference;
69
- async function downloadFeedUpdate(requestOptions, owner, topic, index) {
83
+ async function downloadFeedUpdate(requestOptions, owner, topic, index, hasTimestamp = false) {
70
84
  index = typeof index === 'number' ? typed_bytes_1.FeedIndex.fromBigInt(BigInt(index)) : index;
71
85
  const address = getFeedUpdateChunkReference(owner, topic, index);
72
86
  const data = await chunkAPI.download(requestOptions, address.toHex());
73
87
  const soc = (0, soc_1.makeSingleOwnerChunkFromData)(data, address);
74
- const timestampBytes = bytes_1.Bytes.fromSlice(soc.payload.toUint8Array(), TIMESTAMP_PAYLOAD_OFFSET, TIMESTAMP_PAYLOAD_SIZE);
75
- const timestamp = Number(cafe_utility_1.Binary.uint64ToNumber(timestampBytes.toUint8Array(), 'BE'));
88
+ let timestamp = cafe_utility_1.Optional.empty();
89
+ if (hasTimestamp) {
90
+ const timestampBytes = bytes_1.Bytes.fromSlice(soc.payload.toUint8Array(), TIMESTAMP_PAYLOAD_OFFSET, TIMESTAMP_PAYLOAD_SIZE);
91
+ timestamp = cafe_utility_1.Optional.of(Number(cafe_utility_1.Binary.uint64ToNumber(timestampBytes.toUint8Array(), 'BE')));
92
+ }
76
93
  return {
77
94
  timestamp,
78
- payload: new bytes_1.Bytes(soc.payload.offset(REFERENCE_PAYLOAD_OFFSET)),
95
+ payload: new bytes_1.Bytes(soc.payload.offset(hasTimestamp ? REFERENCE_PAYLOAD_OFFSET : 0)),
79
96
  };
80
97
  }
81
98
  exports.downloadFeedUpdate = downloadFeedUpdate;
99
+ async function downloadFeedUpdateAsCAC(requestOptions, owner, topic, index) {
100
+ index = typeof index === 'number' ? typed_bytes_1.FeedIndex.fromBigInt(BigInt(index)) : index;
101
+ const address = getFeedUpdateChunkReference(owner, topic, index);
102
+ const data = await chunkAPI.download(requestOptions, address);
103
+ return (0, cac_1.asContentAddressedChunk)(data.slice(typed_bytes_1.Identifier.LENGTH + typed_bytes_1.Signature.LENGTH));
104
+ }
105
+ exports.downloadFeedUpdateAsCAC = downloadFeedUpdateAsCAC;
82
106
  function makeFeedReader(requestOptions, topic, owner) {
107
+ // TODO: remove after enough time has passed in deprecated version
108
+ const download = async (options) => {
109
+ if (options?.index === undefined) {
110
+ return (0, feed_1.fetchLatestFeedUpdate)(requestOptions, owner, topic);
111
+ }
112
+ const update = await downloadFeedUpdate(requestOptions, owner, topic, options.index, options.hasTimestamp ?? true);
113
+ const feedIndex = typeof options.index === 'number' ? typed_bytes_1.FeedIndex.fromBigInt(BigInt(options.index)) : options.index;
114
+ return {
115
+ payload: update.payload,
116
+ feedIndex,
117
+ };
118
+ };
119
+ const downloadPayload = async (options) => {
120
+ if (options?.index === undefined) {
121
+ return (0, feed_1.fetchLatestFeedUpdate)(requestOptions, owner, topic);
122
+ }
123
+ const cac = await downloadFeedUpdateAsCAC(requestOptions, owner, topic, options.index);
124
+ const payload = cac.span.toBigInt() <= 4096n
125
+ ? cac.payload
126
+ : await bytes.download(requestOptions, new resource_locator_1.ResourceLocator(cac.address));
127
+ const feedIndex = typeof options.index === 'number' ? typed_bytes_1.FeedIndex.fromBigInt(BigInt(options.index)) : options.index;
128
+ return {
129
+ payload,
130
+ feedIndex,
131
+ };
132
+ };
133
+ const downloadReference = async (options) => {
134
+ let index = options?.index;
135
+ if (index === undefined) {
136
+ index = (await (0, feed_1.probeFeed)(requestOptions, owner, topic)).feedIndex;
137
+ }
138
+ const payload = await download({ ...options, index: index });
139
+ return {
140
+ reference: new typed_bytes_1.Reference(payload.payload.toUint8Array()),
141
+ feedIndex: payload.feedIndex,
142
+ };
143
+ };
83
144
  return {
145
+ download,
146
+ downloadPayload,
147
+ downloadReference,
84
148
  owner,
85
149
  topic,
86
- async download(options) {
87
- if (options?.index === undefined) {
88
- return (0, feed_1.fetchLatestFeedUpdate)(requestOptions, owner, topic);
89
- }
90
- const update = await downloadFeedUpdate(requestOptions, owner, topic, options.index);
91
- const feedIndex = typeof options.index === 'number' ? typed_bytes_1.FeedIndex.fromBigInt(BigInt(options.index)) : options.index;
92
- return {
93
- payload: update.payload,
94
- feedIndex,
95
- };
96
- },
97
150
  };
98
151
  }
99
152
  exports.makeFeedReader = makeFeedReader;
100
153
  function makeFeedWriter(requestOptions, topic, signer) {
101
154
  const upload = async (postageBatchId, reference, options) => {
102
- return updateFeed(requestOptions, signer, topic, reference, postageBatchId, options);
155
+ return updateFeedWithReference(requestOptions, signer, topic, reference, postageBatchId, options);
156
+ };
157
+ const uploadPayload = async (postageBatchId, data, options) => {
158
+ return updateFeedWithPayload(requestOptions, signer, topic, data, postageBatchId, options);
103
159
  };
104
160
  return {
105
161
  ...makeFeedReader(requestOptions, topic, signer.publicKey().address()),
106
162
  upload,
163
+ uploadReference: upload,
164
+ uploadPayload,
107
165
  };
108
166
  }
109
167
  exports.makeFeedWriter = makeFeedWriter;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.fetchLatestFeedUpdate = exports.createFeedManifest = void 0;
3
+ exports.probeFeed = exports.fetchLatestFeedUpdate = exports.createFeedManifest = void 0;
4
4
  const cafe_utility_1 = require("cafe-utility");
5
5
  const bytes_1 = require("../utils/bytes");
6
6
  const error_1 = require("../utils/error");
@@ -51,8 +51,8 @@ function readFeedUpdateHeaders(headers) {
51
51
  * index of the subsequent update.
52
52
  *
53
53
  * @param requestOptions Options for making requests
54
- * @param owner Owner's ethereum address in hex
55
- * @param topic Topic in hex
54
+ * @param owner Owner's ethereum address
55
+ * @param topic Topic
56
56
  * @param options Additional options, like index, at, type
57
57
  */
58
58
  async function fetchLatestFeedUpdate(requestOptions, owner, topic, options) {
@@ -67,3 +67,14 @@ async function fetchLatestFeedUpdate(requestOptions, owner, topic, options) {
67
67
  };
68
68
  }
69
69
  exports.fetchLatestFeedUpdate = fetchLatestFeedUpdate;
70
+ async function probeFeed(requestOptions, owner, topic) {
71
+ const response = await (0, http_1.http)(requestOptions, {
72
+ responseType: 'arraybuffer',
73
+ url: `${feedEndpoint}/${owner}/${topic}`,
74
+ params: {
75
+ 'Swarm-Only-Root-Chunk': true,
76
+ },
77
+ });
78
+ return readFeedUpdateHeaders(response.headers);
79
+ }
80
+ exports.probeFeed = probeFeed;
@@ -66,5 +66,8 @@ class Bytes {
66
66
  toJSON() {
67
67
  return JSON.parse(this.toUtf8());
68
68
  }
69
+ equals(other) {
70
+ return this.toHex() === new Bytes(other).toHex();
71
+ }
69
72
  }
70
73
  exports.Bytes = Bytes;
@@ -63,6 +63,9 @@ class Identifier extends bytes_1.Bytes {
63
63
  constructor(bytes) {
64
64
  super(bytes, 32);
65
65
  }
66
+ static fromString(value) {
67
+ return new Identifier(cafe_utility_1.Binary.keccak256(ENCODER.encode(value)));
68
+ }
66
69
  }
67
70
  exports.Identifier = Identifier;
68
71
  Identifier.LENGTH = 32;
@@ -142,6 +145,11 @@ class Signature extends bytes_1.Bytes {
142
145
  const [x, y] = cafe_utility_1.Elliptic.recoverPublicKey(cafe_utility_1.Binary.concatBytes(ENCODER.encode(`\x19Ethereum Signed Message:\n32`), cafe_utility_1.Binary.keccak256(digest instanceof Uint8Array ? digest : ENCODER.encode(digest))), r, s, v);
143
146
  return new PublicKey(cafe_utility_1.Binary.concatBytes(cafe_utility_1.Binary.numberToUint256(x, 'BE'), cafe_utility_1.Binary.numberToUint256(y, 'BE')));
144
147
  }
148
+ isValid(digest, expectedAddress) {
149
+ const publicKey = this.recoverPublicKey(digest);
150
+ const address = publicKey.address();
151
+ return address.equals(expectedAddress);
152
+ }
145
153
  }
146
154
  exports.Signature = Signature;
147
155
  Signature.LENGTH = 65;
@@ -168,3 +176,4 @@ class FeedIndex extends bytes_1.Bytes {
168
176
  }
169
177
  exports.FeedIndex = FeedIndex;
170
178
  FeedIndex.LENGTH = 8;
179
+ FeedIndex.MINUS_ONE = new FeedIndex(new Uint8Array(8).fill(0xff, 0, 8));