Skip to content

Commit cb00903

Browse files
committed
Adding latest Leth changes for stream content
1 parent a60563e commit cb00903

File tree

5 files changed

+154
-71
lines changed

5 files changed

+154
-71
lines changed

package-lock.json

Lines changed: 14 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "lightstreams-js-sdk",
3-
"version": "0.17.1",
3+
"version": "0.18.0",
44
"description": "Lightstreams JS SDK for building mainstream DApps with support for Programmable Decentralized Private Storage.",
55
"author": "Gabriel Garrido",
66
"contributors": [

src/contracts/profile.js

Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
const Debug = require('debug');
77
const Web3Wrapper = require('../web3');
88

9-
const CID = require('cids');
109
const {
1110
fundRecipient,
1211
isRelayHubDeployed,
@@ -17,26 +16,7 @@ const factoryScJSON = require('../../build/contracts/GSNProfileFactory.json');
1716
const profileScJSON = require('../../build/contracts/GSNProfile.json');
1817
const logger = Debug('ls-sdk:contract:profile');
1918

20-
const cidPrefix = 'Qm';
21-
const cidLength = 46;
22-
23-
function convertHexToCid(hexValue) {
24-
// [18,32] Correspond to the removed cidPrefix 'Qm'
25-
const arrayBuffer = [...[18, 32], ...Web3Wrapper.utils.hexToBytes(hexValue)];
26-
const cidObj = new CID(Web3Wrapper.utils.toBuffer(arrayBuffer));
27-
return cidObj.toString();
28-
}
29-
30-
function convertCidToBytes32(cid) {
31-
if (cid.length !== cidLength || cid.indexOf(cidPrefix) !== 0) {
32-
throw new Error('Invalid cid value');
33-
}
34-
const cidObj = new CID(cid);
35-
return cidObj.multihash.slice(2).toJSON().data;
36-
}
37-
38-
module.exports.convertHexToCid = convertHexToCid;
39-
module.exports.convertCidToBytes32 = convertCidToBytes32;
19+
const {convertHexToCid, convertCidToBytes32} = require('../leth/cid');
4020

4121
module.exports.initializeProfileFactory = async (web3, { contractAddr, relayHub, from, factoryFundingInPht, faucetFundingInPht }) => {
4222
Web3Wrapper.validator.validateAddress("from", from);

src/gateway/storage.js

Lines changed: 90 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,18 @@
33
* Date: 4/02/19 11:04
44
* Copyright 2019 (c) Lightstreams, Palma
55
*/
6-
76
const ADD_FILE_PATH = `/storage/add`;
87
const ADD_RAW_PATH = `/storage/add-raw`;
98
const UPDATE_FILE_PATH = `/storage/update`;
109
const UPDATE_RAW_PATH = `/storage/update-raw`;
1110
const ADD_FILE_WITH_ACL_PATH = `/storage/add-with-acl`;
1211
const ADD_RAW_WITH_ACL_PATH = `/storage/add-raw-with-acl`;
1312
const FETCH_FILE_PATH = `/storage/fetch`;
13+
const STREAM_FILE_PATH = `/storage/stream`;
1414
const META_PATH = `/storage/meta`;
1515

1616
const request = require('../http/request');
17+
const {validateCid} = require('../leth/cid');
1718

1819
module.exports = (gwDomain) => ({
1920

@@ -28,7 +29,7 @@ module.exports = (gwDomain) => ({
2829
if (typeof File !== 'undefined' && file instanceof File) {
2930
const reader = new FileReader();
3031
const fileBlob = file.slice(0, file.size);
31-
reader.readAsBinaryString(fileBlob)
32+
reader.readAsBinaryString(fileBlob);
3233
}
3334
return request.postFile(`${gwDomain}${ADD_FILE_PATH}`, {
3435
owner,
@@ -40,22 +41,20 @@ module.exports = (gwDomain) => ({
4041
* Uploaded new file into distributed storage using raw data and fixed file type
4142
* @param owner {string} Address of the owner of the file
4243
* @param password {string} The password that unlocks the owner
43-
* @param data {Blob} File content in blob object
44+
* @param rawData {string} File content in blob object
4445
* @param ext {string} Content extension format. For example: '.json', '.png'..
4546
* @returns { meta, acl }
4647
*/
47-
addRaw: (owner, password, data, ext) => {
48-
if(!data instanceof Blob) {
49-
throw new Exception(`Argument "data" must be a Blob`);
48+
addRaw: (owner, password, rawData, ext) => {
49+
if (typeof rawData !== 'string') {
50+
throw new Exception(`Argument "data" must be an string`);
5051
}
5152

52-
return data.text().then(rawData => {
53-
return request.post(`${gwDomain}${ADD_RAW_PATH}`, {
54-
owner,
55-
password,
56-
data: rawData,
57-
ext: ext
58-
});
53+
return request.post(`${gwDomain}${ADD_RAW_PATH}`, {
54+
owner,
55+
password,
56+
data: rawData,
57+
ext: ext,
5958
});
6059
},
6160

@@ -70,7 +69,7 @@ module.exports = (gwDomain) => ({
7069
if (typeof File !== 'undefined' && file instanceof File) {
7170
const reader = new FileReader();
7271
const fileBlob = file.slice(0, file.size);
73-
reader.readAsBinaryString(fileBlob)
72+
reader.readAsBinaryString(fileBlob);
7473
}
7574
return request.postFile(`${gwDomain}${ADD_FILE_WITH_ACL_PATH}`, {
7675
owner,
@@ -82,22 +81,20 @@ module.exports = (gwDomain) => ({
8281
* Uploaded new file into distributed storage using raw data and fixed file extension and using an already deployed acl
8382
* @param owner {string} Address of the owner of the file
8483
* @param acl {string} {string} Address to acl contract
85-
* @param data {Blob} File content in blob object
84+
* @param rawData {string} File content in blob object
8685
* @param ext {string} Content extension format. For example: '.json', '.png'..
8786
* @returns { meta, acl }
8887
*/
89-
addRawWithAcl: (owner, acl, data, ext) => {
90-
if (!data instanceof Blob) {
91-
throw new Exception(`Argument "data" must be a Blob`);
88+
addRawWithAcl: (owner, acl, rawData, ext) => {
89+
if (typeof rawData !== 'string') {
90+
throw new Error(`Argument "data" must be an string`);
9291
}
9392

94-
return data.text().then(rawData => {
95-
return request.post(`${gwDomain}${ADD_RAW_WITH_ACL_PATH}`, {
96-
owner,
97-
acl,
98-
data: rawData,
99-
ext: ext
100-
});
93+
return request.post(`${gwDomain}${ADD_RAW_WITH_ACL_PATH}`, {
94+
owner,
95+
acl,
96+
data: rawData,
97+
ext: ext,
10198
});
10299
},
103100

@@ -109,11 +106,14 @@ module.exports = (gwDomain) => ({
109106
* @returns {StreamResponse<{ meta, acl }>} | {<{ meta, acl }>}
110107
*/
111108
update: (owner, meta, file) => {
109+
validateCid(meta);
110+
112111
if (typeof File !== 'undefined' && file instanceof File) {
113112
const reader = new FileReader();
114113
const fileBlob = file.slice(0, file.size);
115-
reader.readAsBinaryString(fileBlob)
114+
reader.readAsBinaryString(fileBlob);
116115
}
116+
117117
return request.postFile(`${gwDomain}${UPDATE_FILE_PATH}`, {
118118
meta,
119119
owner,
@@ -124,22 +124,20 @@ module.exports = (gwDomain) => ({
124124
* Uploaded new file into distributed storage using raw data and fixed file extension
125125
* @param owner {string} Address of the owner of the file
126126
* @param password {string} The password that unlocks the owner
127-
* @param data {Blob} File content in blob object
127+
* @param rawData {string} File content in blob object
128128
* @param ext {string} Content extension format. For example: '.json', '.png'..
129129
* @returns { meta, acl }
130130
*/
131-
updateRaw: (owner, password, data, ext) => {
132-
if (!data instanceof Blob) {
133-
throw new Exception(`Argument "data" must be a Blob`);
131+
updateRaw: (owner, password, rawData, ext) => {
132+
if (typeof rawData !== 'string') {
133+
throw new Error(`Argument "data" must be a Blob`);
134134
}
135135

136-
return data.text().then(rawData => {
137-
return request.post(`${gwDomain}${UPDATE_RAW_PATH}`, {
138-
owner,
139-
password,
140-
data: rawData,
141-
ext: ext
142-
});
136+
return request.post(`${gwDomain}${UPDATE_RAW_PATH}`, {
137+
owner,
138+
password,
139+
data: rawData,
140+
ext: ext,
143141
});
144142
},
145143

@@ -151,14 +149,17 @@ module.exports = (gwDomain) => ({
151149
* @returns {StreamResponse<**CONTENT_FILE**>} || <**CONTENT_FILE**>
152150
*/
153151
fetch: (meta, token, stream) => {
154-
return request.fetchFile(`${gwDomain}${FETCH_FILE_PATH}`, {
155-
meta,
156-
token
157-
}, {
152+
validateCid(meta);
153+
154+
let reqData = {meta};
155+
if (token) {
156+
reqData = {...reqData, token};
157+
}
158+
return request.fetchFile(`${gwDomain}${FETCH_FILE_PATH}`, reqData, {
158159
stream,
159160
headers: {
160-
'Content-Type': 'application/json'
161-
}
161+
'Content-Type': 'application/json',
162+
},
162163
});
163164
},
164165

@@ -168,24 +169,65 @@ module.exports = (gwDomain) => ({
168169
* @param token {string} Account authentication token
169170
*/
170171
fetchUrl: (meta, token) => {
171-
if(!token) {
172-
return `${gwDomain}${FETCH_FILE_PATH}?meta=${meta}`
172+
validateCid(meta);
173+
174+
if (!token) {
175+
return `${gwDomain}${FETCH_FILE_PATH}?meta=${meta}`;
173176
}
174177
return `${gwDomain}${FETCH_FILE_PATH}?meta=${meta}&token=${encodeURI(token)}`;
175178
},
176179

180+
/**
181+
* Stream file from distributed storage
182+
* @param meta {string} Unique identifier of stored file
183+
* @param token {string} Account authentication token
184+
* @param stream {boolean} Response to be streamed or not
185+
* @returns {StreamResponse<**CONTENT_FILE**>} || <**CONTENT_FILE**>
186+
*/
187+
stream: (meta, token, stream) => {
188+
validateCid(meta);
189+
190+
let reqData = {meta};
191+
if (token) {
192+
reqData = {...reqData, token};
193+
}
194+
195+
return request.fetchFile(`${gwDomain}${STREAM_FILE_PATH}`, reqData, {
196+
stream,
197+
headers: {
198+
'Content-Type': 'application/json',
199+
},
200+
});
201+
},
202+
203+
/**
204+
* Return an string with the GET url to fetch content from distributed storage
205+
* @param meta {string} Unique identifier of stored file
206+
* @param token {string} Account authentication token
207+
*/
208+
streamUrl: (meta, token) => {
209+
validateCid(meta);
210+
211+
if (!token) {
212+
return `${gwDomain}${STREAM_FILE_PATH}?meta=${meta}`;
213+
}
214+
return `${gwDomain}${STREAM_FILE_PATH}?meta=${meta}&token=${encodeURI(token)}`;
215+
},
216+
177217
/**
178218
* Fetch metadata information about distributed file
179219
* @param meta {string} Unique identifier of stored file
180220
* @returns {Promise<{ filename, owner, ext, hash, acl, acl, prev_meta_hash }>}
181221
*/
182222
meta: (meta) => {
223+
validateCid(meta);
224+
183225
return request.get(`${gwDomain}${META_PATH}`, {
184-
meta
226+
meta,
185227
}, {
186228
headers: {
187-
'Content-Type': 'application/json'
188-
}
229+
'Content-Type': 'application/json',
230+
},
189231
});
190232
},
191233
});

src/leth/cid.js

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/**
2+
* User: ggarrido
3+
* Date: 25/02/20 12:53
4+
* Copyright 2019 (c) Lightstreams, Granada
5+
*/
6+
7+
8+
const CID = require('cids');
9+
const Web3Wrapper = require('../web3');
10+
11+
const cidPrefix = 'Qm';
12+
const cidLength = 46;
13+
14+
function convertHexToCid(hexValue) {
15+
const arrayBuffer = [...[18, 32], ...Web3Wrapper.utils.hexToBytes(hexValue)];
16+
const cidObj = new CID(Web3Wrapper.utils.toBuffer(arrayBuffer));
17+
return cidObj.toString();
18+
}
19+
20+
function convertCidToBytes32(cid) {
21+
if (cid.length !== cidLength || cid.indexOf(cidPrefix) !== 0) {
22+
throw new Error('Invalid cid value');
23+
}
24+
const cidObj = new CID(cid);
25+
return cidObj.multihash.slice(2).toJSON().data;
26+
}
27+
28+
function validateCid(cid) {
29+
if (typeof cid !== 'string' || cid.length !== cidLength || cid.indexOf(cidPrefix) !== 0) {
30+
throw new Error(`Invalid CID value: ${cid}`);
31+
}
32+
33+
new CID(cid);
34+
}
35+
36+
function isValidCid(cid) {
37+
try{
38+
validateCid(cid);
39+
return true;
40+
} catch(err) {
41+
return false;
42+
}
43+
}
44+
45+
module.exports.convertHexToCid = convertHexToCid;
46+
module.exports.convertCidToBytes32 = convertCidToBytes32;
47+
module.exports.validateCid = validateCid;
48+
module.exports.isValidCid = isValidCid;

0 commit comments

Comments
 (0)