@eluvio/elv-client-js 4.2.29 → 4.2.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ElvClient-min.js +1 -1
- package/dist/ElvClient-node-min.js +1 -1
- package/dist/ElvFrameClient-min.js +1 -1
- package/dist/ElvPermissionsClient-min.js +1 -1
- package/dist/ElvWalletClient-min.js +1 -1
- package/dist/ElvWalletClient-node-min.js +1 -1
- package/dist/src/ElvClient.js +355 -275
- package/dist/src/EthClient.js +3 -2
- package/dist/src/FrameClient.js +1 -1
- package/dist/src/client/ABRPublishing.js +71 -60
- package/dist/src/client/ContentAccess.js +298 -204
- package/dist/src/client/Files.js +1400 -844
- package/dist/src/client/LiveConf.js +54 -37
- package/dist/src/client/LiveStream.js +123 -81
- package/package.json +1 -1
- package/src/ElvClient.js +51 -0
- package/src/FrameClient.js +1 -0
- package/dist/src/ContentObjectVerification.js +0 -281
package/src/ElvClient.js
CHANGED
|
@@ -936,6 +936,57 @@ class ElvClient {
|
|
|
936
936
|
json 79b {"adr":"VVf4DQU357tDnZGYQeDrntRJ5rs=","spc":"ispc3ANoVSzNA3P6t7abLR69ho5YPPZU"}
|
|
937
937
|
*/
|
|
938
938
|
|
|
939
|
+
/*
|
|
940
|
+
PLAIN TOKEN PREFIX + BODY | aplsjcJf1HYcDDUuCdXcSZtU86nYK162YmYJeuqwMczEBJVkD5D5EvsBvVwYDRsf4hzDvBWMoe9piBpqx...
|
|
941
|
+
PREFIX 6b aplsjc | apl=plain s=ES256K jc=json-compressed
|
|
942
|
+
BODY base58(SIGNATURE + PAYLOAD)
|
|
943
|
+
SIGNATURE 65b ES256K signature
|
|
944
|
+
PAYLOAD raw-deflate JSON
|
|
945
|
+
json {"adr":"VVf4DQU357tDnZGYQeDrntRJ5rs=","spc":"ispc3ANoVSzNA3P6t7abLR69ho5YPPZU"}
|
|
946
|
+
*/
|
|
947
|
+
|
|
948
|
+
/**
|
|
949
|
+
* Create a signed "plain" authorization token (`aplsjc...`).
|
|
950
|
+
*
|
|
951
|
+
* Plain tokens are largely the same as client-signed access tokens - they do not contain a b/c transaction
|
|
952
|
+
* and authorization is determined from the rights of the current signer's address.
|
|
953
|
+
* Currently needed for tenant content query /tenant/:tid/q/query
|
|
954
|
+
* This token will be deprecated in the future in favor of client-signed access tokens.
|
|
955
|
+
*
|
|
956
|
+
* @methodGroup Authorization
|
|
957
|
+
* @namedParams
|
|
958
|
+
* @param {string=} libraryId - Optional library ID to scope the token. If omitted, the token is space-wide.
|
|
959
|
+
* @returns {Promise<string>} - The signed Plain auth token
|
|
960
|
+
*/
|
|
961
|
+
async CreatePlainToken({libraryId}={}) {
|
|
962
|
+
const address = this.CurrentAccountAddress();
|
|
963
|
+
if(!address) {
|
|
964
|
+
throw Error("Unable to create plain token: No signer is configured");
|
|
965
|
+
}
|
|
966
|
+
|
|
967
|
+
const token = {
|
|
968
|
+
adr: Buffer.from(address.replace(/^0x/, ""), "hex").toString("base64"),
|
|
969
|
+
spc: await this.ContentSpaceId()
|
|
970
|
+
};
|
|
971
|
+
|
|
972
|
+
if(libraryId) {
|
|
973
|
+
token.lib = libraryId;
|
|
974
|
+
}
|
|
975
|
+
|
|
976
|
+
const compressedToken = Pako.deflateRaw(Buffer.from(JSON.stringify(token), "utf-8"));
|
|
977
|
+
const signature = await this.authClient.Sign(Ethers.utils.keccak256(compressedToken));
|
|
978
|
+
const signatureBytes = Buffer.from(signature.replace(/^0x/, ""), "hex");
|
|
979
|
+
|
|
980
|
+
if(signatureBytes.length !== 65) {
|
|
981
|
+
throw Error("Unable to create plain token: Expected a 65-byte ES256K signature");
|
|
982
|
+
}
|
|
983
|
+
|
|
984
|
+
return `aplsjc${this.utils.B58(Buffer.concat([
|
|
985
|
+
signatureBytes,
|
|
986
|
+
Buffer.from(compressedToken)
|
|
987
|
+
]))}`;
|
|
988
|
+
}
|
|
989
|
+
|
|
939
990
|
async PersonalSign({
|
|
940
991
|
message,
|
|
941
992
|
addEthereumPrefix,
|
package/src/FrameClient.js
CHANGED
|
@@ -1,281 +0,0 @@
|
|
|
1
|
-
var _regeneratorRuntime = require("@babel/runtime/regenerator");
|
|
2
|
-
var _asyncToGenerator = require("@babel/runtime/helpers/asyncToGenerator");
|
|
3
|
-
function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t["return"] || t["return"](); } finally { if (u) throw o; } } }; }
|
|
4
|
-
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
|
|
5
|
-
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
|
|
6
|
-
var CBOR = require("cbor");
|
|
7
|
-
var SJCL = require("sjcl");
|
|
8
|
-
var MultiHash = require("multihashes");
|
|
9
|
-
var DeepEqual = require("deep-equal");
|
|
10
|
-
var Utils = require("./Utils");
|
|
11
|
-
var ContentObjectVerification = {
|
|
12
|
-
VerifyContentObject: function VerifyContentObject(_ref) {
|
|
13
|
-
return _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
|
|
14
|
-
var client, libraryId, objectId, versionHash, response, partHash, qpartsResponse, partVerification, qmdHash, metadataPartHash, metadataPartResponse, metadataVerification, metadata, qstructHash, structPartHash, structPartResponse, structVerification;
|
|
15
|
-
return _regeneratorRuntime.wrap(function _callee$(_context) {
|
|
16
|
-
while (1) switch (_context.prev = _context.next) {
|
|
17
|
-
case 0:
|
|
18
|
-
client = _ref.client, libraryId = _ref.libraryId, objectId = _ref.objectId, versionHash = _ref.versionHash;
|
|
19
|
-
response = {
|
|
20
|
-
hash: versionHash
|
|
21
|
-
};
|
|
22
|
-
partHash = Utils.DecodeVersionHash(versionHash).partHash;
|
|
23
|
-
_context.next = 5;
|
|
24
|
-
return client.QParts({
|
|
25
|
-
libraryId: libraryId,
|
|
26
|
-
objectId: objectId,
|
|
27
|
-
partHash: partHash,
|
|
28
|
-
format: "arrayBuffer"
|
|
29
|
-
}).then(function (response) {
|
|
30
|
-
return Buffer.from(response);
|
|
31
|
-
});
|
|
32
|
-
case 5:
|
|
33
|
-
qpartsResponse = _context.sent;
|
|
34
|
-
partVerification = ContentObjectVerification._VerifyPart({
|
|
35
|
-
partHash: partHash,
|
|
36
|
-
qpartsResponse: qpartsResponse
|
|
37
|
-
});
|
|
38
|
-
if (partVerification.valid) {
|
|
39
|
-
response.qref = {
|
|
40
|
-
valid: true
|
|
41
|
-
};
|
|
42
|
-
} else {
|
|
43
|
-
response.qref = {
|
|
44
|
-
valid: false,
|
|
45
|
-
error: partVerification.error.message
|
|
46
|
-
};
|
|
47
|
-
}
|
|
48
|
-
response.qref.hash = partHash;
|
|
49
|
-
if (!response.qref.valid) {
|
|
50
|
-
_context.next = 32;
|
|
51
|
-
break;
|
|
52
|
-
}
|
|
53
|
-
// Validate Metadata
|
|
54
|
-
qmdHash = partVerification.cbor.QmdHash.value;
|
|
55
|
-
metadataPartHash = "hqp_" + MultiHash.toB58String(qmdHash.slice(1, qmdHash.length));
|
|
56
|
-
_context.next = 14;
|
|
57
|
-
return client.QParts({
|
|
58
|
-
libraryId: libraryId,
|
|
59
|
-
objectId: objectId,
|
|
60
|
-
partHash: metadataPartHash,
|
|
61
|
-
format: "arrayBuffer"
|
|
62
|
-
}).then(function (response) {
|
|
63
|
-
return Buffer.from(response);
|
|
64
|
-
});
|
|
65
|
-
case 14:
|
|
66
|
-
metadataPartResponse = _context.sent;
|
|
67
|
-
metadataVerification = ContentObjectVerification._VerifyPart({
|
|
68
|
-
partHash: metadataPartHash,
|
|
69
|
-
qpartsResponse: metadataPartResponse
|
|
70
|
-
});
|
|
71
|
-
if (metadataVerification.valid) {
|
|
72
|
-
response.qmd = {
|
|
73
|
-
valid: true
|
|
74
|
-
};
|
|
75
|
-
} else {
|
|
76
|
-
response.qmd = {
|
|
77
|
-
valid: false,
|
|
78
|
-
error: metadataVerification.error.message
|
|
79
|
-
};
|
|
80
|
-
}
|
|
81
|
-
response.qmd.hash = metadataPartHash;
|
|
82
|
-
if (!(response.qmd.valid && libraryId)) {
|
|
83
|
-
_context.next = 23;
|
|
84
|
-
break;
|
|
85
|
-
}
|
|
86
|
-
_context.next = 21;
|
|
87
|
-
return client.ContentObjectMetadata({
|
|
88
|
-
libraryId: libraryId,
|
|
89
|
-
objectId: objectId,
|
|
90
|
-
versionHash: partHash.replace("hqp_", "hq__")
|
|
91
|
-
});
|
|
92
|
-
case 21:
|
|
93
|
-
metadata = _context.sent;
|
|
94
|
-
response.qmd.check = ContentObjectVerification._VerifyMetadata({
|
|
95
|
-
metadataCbor: metadataVerification.cbor,
|
|
96
|
-
metadata: metadata
|
|
97
|
-
});
|
|
98
|
-
case 23:
|
|
99
|
-
// Validate Qstruct
|
|
100
|
-
qstructHash = partVerification.cbor.QstructHash.value;
|
|
101
|
-
structPartHash = "hqp_" + MultiHash.toB58String(qstructHash.slice(1, qstructHash.length));
|
|
102
|
-
_context.next = 27;
|
|
103
|
-
return client.QParts({
|
|
104
|
-
libraryId: libraryId,
|
|
105
|
-
objectId: objectId,
|
|
106
|
-
partHash: structPartHash,
|
|
107
|
-
format: "arrayBuffer"
|
|
108
|
-
}).then(function (response) {
|
|
109
|
-
return Buffer.from(response);
|
|
110
|
-
});
|
|
111
|
-
case 27:
|
|
112
|
-
structPartResponse = _context.sent;
|
|
113
|
-
structVerification = ContentObjectVerification._VerifyPart({
|
|
114
|
-
partHash: structPartHash,
|
|
115
|
-
qpartsResponse: structPartResponse
|
|
116
|
-
});
|
|
117
|
-
if (structVerification.valid) {
|
|
118
|
-
response.qstruct = {
|
|
119
|
-
valid: true
|
|
120
|
-
};
|
|
121
|
-
} else {
|
|
122
|
-
response.qstruct = {
|
|
123
|
-
valid: false,
|
|
124
|
-
error: structVerification.error.message
|
|
125
|
-
};
|
|
126
|
-
}
|
|
127
|
-
response.qstruct.hash = structPartHash;
|
|
128
|
-
if (response.qstruct.valid) {
|
|
129
|
-
response.qstruct.parts = ContentObjectVerification._FormatQStruct(structVerification.cbor.Parts);
|
|
130
|
-
}
|
|
131
|
-
case 32:
|
|
132
|
-
response.valid = response.qref.valid && response.qmd.valid && response.qstruct.valid && (!response.qmd.check || response.qmd.check.valid);
|
|
133
|
-
return _context.abrupt("return", response);
|
|
134
|
-
case 34:
|
|
135
|
-
case "end":
|
|
136
|
-
return _context.stop();
|
|
137
|
-
}
|
|
138
|
-
}, _callee);
|
|
139
|
-
}))();
|
|
140
|
-
},
|
|
141
|
-
// Content verification methods //
|
|
142
|
-
_FormatQStruct: function _FormatQStruct(structParts) {
|
|
143
|
-
if (!structParts) {
|
|
144
|
-
return [];
|
|
145
|
-
}
|
|
146
|
-
return structParts.map(function (structPart) {
|
|
147
|
-
return {
|
|
148
|
-
hash: "hqp_" + MultiHash.toB58String(structPart.Hash.value.slice(1, structPart.Hash.length)),
|
|
149
|
-
size: structPart.Size
|
|
150
|
-
};
|
|
151
|
-
});
|
|
152
|
-
},
|
|
153
|
-
_Hash: function _Hash(thing) {
|
|
154
|
-
function fromBits(arr) {
|
|
155
|
-
var out = [],
|
|
156
|
-
bl = SJCL.bitArray.bitLength(arr),
|
|
157
|
-
i,
|
|
158
|
-
tmp;
|
|
159
|
-
for (i = 0; i < bl / 8; i++) {
|
|
160
|
-
if ((i & 3) === 0) {
|
|
161
|
-
tmp = arr[i / 4];
|
|
162
|
-
}
|
|
163
|
-
out.push(tmp >>> 24);
|
|
164
|
-
tmp <<= 8;
|
|
165
|
-
}
|
|
166
|
-
return out;
|
|
167
|
-
}
|
|
168
|
-
function toBits(bytes) {
|
|
169
|
-
var out = [],
|
|
170
|
-
i,
|
|
171
|
-
tmp = 0;
|
|
172
|
-
for (i = 0; i < bytes.length; i++) {
|
|
173
|
-
tmp = tmp << 8 | bytes[i];
|
|
174
|
-
if ((i & 3) === 3) {
|
|
175
|
-
out.push(tmp);
|
|
176
|
-
tmp = 0;
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
if (i & 3) {
|
|
180
|
-
out.push(SJCL.bitArray.partial(8 * (i & 3), tmp));
|
|
181
|
-
}
|
|
182
|
-
return out;
|
|
183
|
-
}
|
|
184
|
-
var digest = SJCL.hash.sha256.hash(toBits(thing));
|
|
185
|
-
var bytes = fromBits(digest);
|
|
186
|
-
var out = Buffer.from(bytes, "binary");
|
|
187
|
-
return MultiHash.toB58String(MultiHash.encode(out, "sha2-256"));
|
|
188
|
-
},
|
|
189
|
-
_ParseCBOR: function _ParseCBOR(cborResponse) {
|
|
190
|
-
var buffer = cborResponse.slice(7, cborResponse.length);
|
|
191
|
-
var hex = buffer.toString("hex");
|
|
192
|
-
return CBOR.decodeFirstSync(hex);
|
|
193
|
-
},
|
|
194
|
-
_VerifyPart: function _VerifyPart(_ref2) {
|
|
195
|
-
var partHash = _ref2.partHash,
|
|
196
|
-
qpartsResponse = _ref2.qpartsResponse;
|
|
197
|
-
try {
|
|
198
|
-
if (ContentObjectVerification._Hash(qpartsResponse) !== partHash.replace("hqp_", "")) {
|
|
199
|
-
throw Error("Hashes do not match");
|
|
200
|
-
}
|
|
201
|
-
var cbor = ContentObjectVerification._ParseCBOR(qpartsResponse);
|
|
202
|
-
return {
|
|
203
|
-
valid: true,
|
|
204
|
-
cbor: cbor
|
|
205
|
-
};
|
|
206
|
-
} catch (error) {
|
|
207
|
-
return {
|
|
208
|
-
valid: false,
|
|
209
|
-
error: error
|
|
210
|
-
};
|
|
211
|
-
}
|
|
212
|
-
},
|
|
213
|
-
_VerifyMetadata: function _VerifyMetadata(_ref3) {
|
|
214
|
-
var metadataCbor = _ref3.metadataCbor,
|
|
215
|
-
metadata = _ref3.metadata;
|
|
216
|
-
if (!metadataCbor) {
|
|
217
|
-
metadataCbor = {};
|
|
218
|
-
}
|
|
219
|
-
if (!metadata) {
|
|
220
|
-
metadata = {};
|
|
221
|
-
}
|
|
222
|
-
var response = {
|
|
223
|
-
valid: true,
|
|
224
|
-
invalidValues: []
|
|
225
|
-
};
|
|
226
|
-
var cborKeys = Object.keys(metadataCbor);
|
|
227
|
-
var metadataKeys = Object.keys(metadata);
|
|
228
|
-
|
|
229
|
-
// Find any difference between top level keys
|
|
230
|
-
var differentKeys = cborKeys.filter(function (x) {
|
|
231
|
-
return !metadataKeys.includes(x);
|
|
232
|
-
}).concat(metadataKeys.filter(function (x) {
|
|
233
|
-
return !cborKeys.includes(x);
|
|
234
|
-
}));
|
|
235
|
-
var _iterator = _createForOfIteratorHelper(differentKeys),
|
|
236
|
-
_step;
|
|
237
|
-
try {
|
|
238
|
-
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
239
|
-
var key = _step.value;
|
|
240
|
-
var cborValue = metadataCbor[key];
|
|
241
|
-
var metadataValue = metadata[key];
|
|
242
|
-
response.invalidValues.push({
|
|
243
|
-
key: key,
|
|
244
|
-
cborValue: cborValue,
|
|
245
|
-
metadataValue: metadataValue
|
|
246
|
-
});
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
// Deep comparison of up to 5 keys
|
|
250
|
-
} catch (err) {
|
|
251
|
-
_iterator.e(err);
|
|
252
|
-
} finally {
|
|
253
|
-
_iterator.f();
|
|
254
|
-
}
|
|
255
|
-
var _iterator2 = _createForOfIteratorHelper(Object.keys(metadataCbor).slice(0, 5)),
|
|
256
|
-
_step2;
|
|
257
|
-
try {
|
|
258
|
-
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
259
|
-
var fieldToValidate = _step2.value;
|
|
260
|
-
var _cborValue = metadataCbor[fieldToValidate];
|
|
261
|
-
var _metadataValue = metadata[fieldToValidate];
|
|
262
|
-
if (!DeepEqual(_cborValue, _metadataValue)) {
|
|
263
|
-
response.invalidValues.push({
|
|
264
|
-
key: fieldToValidate,
|
|
265
|
-
cborValue: _cborValue,
|
|
266
|
-
metadataValue: _metadataValue
|
|
267
|
-
});
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
} catch (err) {
|
|
271
|
-
_iterator2.e(err);
|
|
272
|
-
} finally {
|
|
273
|
-
_iterator2.f();
|
|
274
|
-
}
|
|
275
|
-
if (response.invalidValues.length !== 0) {
|
|
276
|
-
response.valid = false;
|
|
277
|
-
}
|
|
278
|
-
return response;
|
|
279
|
-
}
|
|
280
|
-
};
|
|
281
|
-
module.exports = ContentObjectVerification;
|