@eluvio/elv-client-js 3.1.76 → 3.1.80

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.
@@ -880,7 +880,7 @@ exports.RemoveLibraryContentType = function _callee9(_ref12) {
880
880
 
881
881
 
882
882
  exports.CreateContentObject = function _callee10(_ref13) {
883
- var libraryId, objectId, _ref13$options, options, typeId, type, _ref14, contractAddress, path, createResponse;
883
+ var libraryId, objectId, _ref13$options, options, typeId, type, currentAccountAddress, canContribute, _ref14, contractAddress, path, createResponse;
884
884
 
885
885
  return _regeneratorRuntime.async(function _callee10$(_context11) {
886
886
  while (1) {
@@ -957,65 +957,88 @@ exports.CreateContentObject = function _callee10(_ref13) {
957
957
 
958
958
  case 26:
959
959
  if (objectId) {
960
- _context11.next = 36;
960
+ _context11.next = 44;
961
961
  break;
962
962
  }
963
963
 
964
+ _context11.next = 29;
965
+ return _regeneratorRuntime.awrap(this.CurrentAccountAddress());
966
+
967
+ case 29:
968
+ currentAccountAddress = _context11.sent;
969
+ _context11.next = 32;
970
+ return _regeneratorRuntime.awrap(this.CallContractMethod({
971
+ contractAddress: this.utils.HashToAddress(libraryId),
972
+ methodName: "canContribute",
973
+ methodArgs: [currentAccountAddress]
974
+ }));
975
+
976
+ case 32:
977
+ canContribute = _context11.sent;
978
+
979
+ if (canContribute) {
980
+ _context11.next = 35;
981
+ break;
982
+ }
983
+
984
+ throw Error("Current user does not have permission to create content in library ".concat(libraryId));
985
+
986
+ case 35:
964
987
  this.Log("Deploying contract...");
965
- _context11.next = 30;
988
+ _context11.next = 38;
966
989
  return _regeneratorRuntime.awrap(this.authClient.CreateContentObject({
967
990
  libraryId: libraryId,
968
991
  typeId: typeId
969
992
  }));
970
993
 
971
- case 30:
994
+ case 38:
972
995
  _ref14 = _context11.sent;
973
996
  contractAddress = _ref14.contractAddress;
974
997
  objectId = this.utils.AddressToObjectId(contractAddress);
975
998
  this.Log("Contract deployed: ".concat(contractAddress, " ").concat(objectId));
976
- _context11.next = 43;
999
+ _context11.next = 51;
977
1000
  break;
978
1001
 
979
- case 36:
1002
+ case 44:
980
1003
  _context11.t0 = this;
981
1004
  _context11.t1 = "Contract already deployed for contract type: ";
982
- _context11.next = 40;
1005
+ _context11.next = 48;
983
1006
  return _regeneratorRuntime.awrap(this.AccessType({
984
1007
  id: objectId
985
1008
  }));
986
1009
 
987
- case 40:
1010
+ case 48:
988
1011
  _context11.t2 = _context11.sent;
989
1012
  _context11.t3 = _context11.t1.concat.call(_context11.t1, _context11.t2);
990
1013
 
991
1014
  _context11.t0.Log.call(_context11.t0, _context11.t3);
992
1015
 
993
- case 43:
1016
+ case 51:
994
1017
  if (!options.visibility) {
995
- _context11.next = 47;
1018
+ _context11.next = 55;
996
1019
  break;
997
1020
  }
998
1021
 
999
1022
  this.Log("Setting visibility to ".concat(options.visibility));
1000
- _context11.next = 47;
1023
+ _context11.next = 55;
1001
1024
  return _regeneratorRuntime.awrap(this.SetVisibility({
1002
1025
  id: objectId,
1003
1026
  visibility: options.visibility
1004
1027
  }));
1005
1028
 
1006
- case 47:
1029
+ case 55:
1007
1030
  path = UrlJoin("qid", objectId);
1008
1031
  _context11.t4 = _regeneratorRuntime;
1009
1032
  _context11.t5 = this.utils;
1010
1033
  _context11.t6 = this.HttpClient;
1011
- _context11.next = 53;
1034
+ _context11.next = 61;
1012
1035
  return _regeneratorRuntime.awrap(this.authClient.AuthorizationHeader({
1013
1036
  libraryId: libraryId,
1014
1037
  objectId: objectId,
1015
1038
  update: true
1016
1039
  }));
1017
1040
 
1018
- case 53:
1041
+ case 61:
1019
1042
  _context11.t7 = _context11.sent;
1020
1043
  _context11.t8 = path;
1021
1044
  _context11.t9 = options;
@@ -1027,10 +1050,10 @@ exports.CreateContentObject = function _callee10(_ref13) {
1027
1050
  };
1028
1051
  _context11.t11 = _context11.t6.Request.call(_context11.t6, _context11.t10);
1029
1052
  _context11.t12 = _context11.t5.ResponseToJson.call(_context11.t5, _context11.t11);
1030
- _context11.next = 61;
1053
+ _context11.next = 69;
1031
1054
  return _context11.t4.awrap.call(_context11.t4, _context11.t12);
1032
1055
 
1033
- case 61:
1056
+ case 69:
1034
1057
  createResponse = _context11.sent;
1035
1058
  // Record the node used in creating this write token
1036
1059
  this.HttpClient.RecordWriteToken(createResponse.write_token);
@@ -1038,7 +1061,7 @@ exports.CreateContentObject = function _callee10(_ref13) {
1038
1061
  createResponse.objectId = createResponse.id;
1039
1062
  return _context11.abrupt("return", createResponse);
1040
1063
 
1041
- case 66:
1064
+ case 74:
1042
1065
  case "end":
1043
1066
  return _context11.stop();
1044
1067
  }
package/package-lock.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eluvio/elv-client-js",
3
- "version": "3.1.76",
3
+ "version": "3.1.80",
4
4
  "lockfileVersion": 1,
5
5
  "requires": true,
6
6
  "dependencies": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eluvio/elv-client-js",
3
- "version": "3.1.76",
3
+ "version": "3.1.80",
4
4
  "description": "Javascript client for the Eluvio Content Fabric",
5
5
  "main": "src/ElvClient.js",
6
6
  "author": "Kevin Talmadge",
@@ -84,6 +84,16 @@ class AuthorizationClient {
84
84
  this.providers = {};
85
85
  }
86
86
 
87
+ CreateStaticToken({libraryId}) {
88
+ let token = { qspace_id: this.client.contentSpaceId };
89
+
90
+ if(libraryId) {
91
+ token.qlib_id = libraryId;
92
+ }
93
+
94
+ return Utils.B64(JSON.stringify(token));
95
+ }
96
+
87
97
  // Return authorization token in appropriate headers
88
98
  async AuthorizationHeader(params) {
89
99
  const authorizationToken = await this.AuthorizationToken(params);
@@ -150,6 +160,10 @@ class AuthorizationClient {
150
160
  oauthToken
151
161
  });
152
162
  } else {
163
+ if(noAuth) {
164
+ return this.CreateStaticToken({libraryId});
165
+ }
166
+
153
167
  authorizationToken = await this.GenerateAuthorizationToken({
154
168
  libraryId,
155
169
  objectId,
@@ -177,7 +191,7 @@ class AuthorizationClient {
177
191
  if(encryption && encryption !== "none" && objectId && await this.AccessType(objectId) === ACCESS_TYPES.OBJECT) {
178
192
  const owner = await this.Owner({id: objectId});
179
193
  const ownerCapKey = `eluv.caps.iusr${Utils.AddressToHash(this.client.signer.address)}`;
180
- const ownerCap = await client.ContentObjectMetadata({libraryId, objectId, metadataSubtree: ownerCapKey});
194
+ const ownerCap = await this.client.ContentObjectMetadata({libraryId, objectId, metadataSubtree: ownerCapKey});
181
195
 
182
196
  if(!Utils.EqualAddress(owner, this.client.signer.address) && !ownerCap) {
183
197
  const cap = await this.ReEncryptionConk({libraryId, objectId});
@@ -613,6 +627,10 @@ class AuthorizationClient {
613
627
  }
614
628
 
615
629
  async IsV3({id}) {
630
+ if(this.client.assumeV3) {
631
+ return true;
632
+ }
633
+
616
634
  const contractName = await this.client.ethClient.ContractName(Utils.HashToAddress(id), true);
617
635
 
618
636
  if(!this.accessVersions[contractName]) {
package/src/ElvClient.js CHANGED
@@ -148,7 +148,8 @@ class ElvClient {
148
148
  trustAuthorityId,
149
149
  staticToken,
150
150
  noCache=false,
151
- noAuth=false
151
+ noAuth=false,
152
+ assumeV3=false
152
153
  }) {
153
154
  this.utils = Utils;
154
155
 
@@ -171,6 +172,7 @@ class ElvClient {
171
172
 
172
173
  this.noCache = noCache;
173
174
  this.noAuth = noAuth;
175
+ this.assumeV3 = assumeV3;
174
176
 
175
177
  this.debug = false;
176
178
 
@@ -270,7 +272,8 @@ class ElvClient {
270
272
  staticToken,
271
273
  ethereumContractTimeout=10,
272
274
  noCache=false,
273
- noAuth=false
275
+ noAuth=false,
276
+ assumeV3
274
277
  }) {
275
278
  const configUrl = networks[networkName];
276
279
 
@@ -283,7 +286,8 @@ class ElvClient {
283
286
  staticToken,
284
287
  ethereumContractTimeout,
285
288
  noCache,
286
- noAuth
289
+ noAuth,
290
+ assumeV3
287
291
  });
288
292
  }
289
293
 
@@ -309,7 +313,8 @@ class ElvClient {
309
313
  staticToken,
310
314
  ethereumContractTimeout=10,
311
315
  noCache=false,
312
- noAuth=false
316
+ noAuth=false,
317
+ assumeV3=false
313
318
  }) {
314
319
  const {
315
320
  contentSpaceId,
@@ -336,7 +341,8 @@ class ElvClient {
336
341
  trustAuthorityId,
337
342
  staticToken,
338
343
  noCache,
339
- noAuth
344
+ noAuth,
345
+ assumeV3
340
346
  });
341
347
 
342
348
  client.configUrl = configUrl;
package/src/EthClient.js CHANGED
@@ -285,6 +285,8 @@ class EthClient {
285
285
  const latestBlock = await this.MakeProviderCall({methodName: "getBlock", args: ["latest"]});
286
286
  overrides.gasLimit = latestBlock.gasLimit;
287
287
  overrides.gasPrice = overrides.gasPrice ? overrides.gasPrice * 1.50 : 8000000000;
288
+ } else if(error.code === "NONCE_EXPIRED" && error.reason === "nonce has already been used") {
289
+ this.Log(`Retrying method call ${methodName}`);
288
290
  } else if(!(error.message || error).includes("invalid response")) {
289
291
  this.Log(typeof error === "object" ? JSON.stringify(error, null, 2) : error, true);
290
292
  throw error;
@@ -56,6 +56,8 @@ await client.userProfileClient.UserMetadata()
56
56
  this.client = client;
57
57
  this.debug = debug;
58
58
  this.userWalletAddresses = {};
59
+ this.walletAddress = undefined;
60
+ this.walletAddressRetrieved = false;
59
61
  }
60
62
 
61
63
  async CreateWallet() {
@@ -130,13 +132,17 @@ await client.userProfileClient.UserMetadata()
130
132
  * @return {Promise<string>} - The contract address of the current user's wallet contract
131
133
  */
132
134
  async WalletAddress(autoCreate=true) {
133
- if(this.walletAddress) { return this.walletAddress; }
135
+ if(this.walletAddress || this.walletAddressRetrieved) { return this.walletAddress; }
134
136
 
135
- const walletAddress = await this.client.CallContractMethod({
136
- contractAddress: Utils.HashToAddress(this.client.contentSpaceId),
137
- methodName: "userWallets",
138
- methodArgs: [this.client.signer.address]
139
- });
137
+ if(!this.walletAddressPromise) {
138
+ this.walletAddressPromise = this.client.CallContractMethod({
139
+ contractAddress: Utils.HashToAddress(this.client.contentSpaceId),
140
+ methodName: "userWallets",
141
+ methodArgs: [this.client.signer.address]
142
+ });
143
+ }
144
+
145
+ const walletAddress = await this.walletAddressPromise;
140
146
 
141
147
  if(!Utils.EqualAddress(walletAddress, Utils.nullAddress)) {
142
148
  this.walletAddress = walletAddress;
@@ -146,6 +152,8 @@ await client.userProfileClient.UserMetadata()
146
152
  await this.CreateWallet();
147
153
  }
148
154
 
155
+ this.walletAddressRetrieved = true;
156
+
149
157
  return this.walletAddress;
150
158
  }
151
159
 
@@ -6,6 +6,7 @@
6
6
  * @module ElvClient/ABRPublishing
7
7
  */
8
8
 
9
+ const R = require("ramda");
9
10
  const UrlJoin = require("url-join");
10
11
  const HttpClient = require("../HttpClient");
11
12
 
@@ -355,8 +356,6 @@ exports.CreateABRMezzanine = async function({
355
356
  ...metadata.public.asset_metadata
356
357
  };
357
358
 
358
- metadata.elv_created_at = new Date().getTime();
359
-
360
359
  if(name || !existingMez) {
361
360
  metadata.name = name || `${masterName} Mezzanine`;
362
361
  metadata.public.name = name || `${masterName} Mezzanine`;
@@ -367,7 +366,23 @@ exports.CreateABRMezzanine = async function({
367
366
  metadata.public.description = description || "";
368
367
  }
369
368
 
370
- await this.MergeMetadata({
369
+ // retrieve existing metadata to merge with updated metadata
370
+ const existingMetadata = await this.ContentObjectMetadata({
371
+ libraryId,
372
+ objectId: id,
373
+ writeToken: write_token,
374
+ });
375
+ // newer metadata values replace existing metadata, unless both new and old values are objects,
376
+ // in which case their keys are merged recursively
377
+ metadata = R.mergeDeepRight(existingMetadata, metadata);
378
+
379
+ if(!existingMez) {
380
+ // set creation date
381
+ metadata.elv_created_at = new Date().getTime();
382
+ }
383
+
384
+ // write metadata to mezzanine object
385
+ await this.ReplaceMetadata({
371
386
  libraryId,
372
387
  objectId: id,
373
388
  writeToken: write_token,
@@ -760,17 +760,22 @@ exports.MetadataAuth = async function({
760
760
  objectId,
761
761
  versionHash,
762
762
  path="/",
763
- channelAuth=false
763
+ channelAuth=false,
764
+ noAuth=false
764
765
  }) {
765
766
  ValidateParameters({libraryId, objectId, versionHash});
766
767
 
767
768
  if(versionHash) { objectId = this.utils.DecodeVersionHash(versionHash).objectId; }
768
769
 
769
- const visibility = await this.Visibility({id: objectId});
770
- const accessType = await this.AccessType({id: objectId});
771
- const isPublic = (path || "").replace(/^\/+/, "").startsWith("public");
772
-
773
- let noAuth = visibility >= 10 || (isPublic && visibility >= 1);
770
+ noAuth = this.noAuth || noAuth;
771
+ let isPublic = noAuth;
772
+ let accessType;
773
+ if(!noAuth) {
774
+ const visibility = await this.Visibility({id: objectId});
775
+ accessType = await this.AccessType({id: objectId});
776
+ isPublic = (path || "").replace(/^\/+/, "").startsWith("public");
777
+ noAuth = visibility >= 10 || (isPublic && visibility >= 1);
778
+ }
774
779
 
775
780
  if(this.oauthToken) {
776
781
  // Check that KMS is set on this object
@@ -823,6 +828,7 @@ exports.MetadataAuth = async function({
823
828
  * - Note: Selection is relative to "metadataSubtree". For example, metadataSubtree="public" and select=["name", "description"] would select "public/name" and "public/description"
824
829
  * @param {Array<string>=} remove - Exclude the specified items from the retrieved metadata
825
830
  * @param {string=} authorizationToken - Additional authorization token for this request
831
+ * @param {string=} noAuth=false - If specified, the normal authorization flow will be skipped. Useful if you know the metadata you're retrieving is publicly accessible
826
832
  * @param {boolean=} resolveLinks=false - If specified, links in the metadata will be resolved
827
833
  * @param {boolean=} resolveIncludeSource=false - If specified, resolved links will include the hash of the link at the root of the metadata
828
834
 
@@ -857,6 +863,7 @@ exports.ContentObjectMetadata = async function({
857
863
  select=[],
858
864
  remove=[],
859
865
  authorizationToken,
866
+ noAuth=false,
860
867
  resolveLinks=false,
861
868
  resolveIncludeSource=false,
862
869
  resolveIgnoreErrors=false,
@@ -877,7 +884,7 @@ exports.ContentObjectMetadata = async function({
877
884
  let path = UrlJoin("q", writeToken || versionHash || objectId, "meta", metadataSubtree);
878
885
 
879
886
  // Main authorization
880
- let defaultAuthToken = await this.MetadataAuth({libraryId, objectId, versionHash, path: metadataSubtree});
887
+ let defaultAuthToken = await this.MetadataAuth({libraryId, objectId, versionHash, path: metadataSubtree, noAuth});
881
888
 
882
889
  // All authorization
883
890
  const authTokens = [authorizationToken, queryParams.authorization, defaultAuthToken].flat().filter(token => token);
@@ -2259,9 +2266,7 @@ exports.LinkUrl = async function({
2259
2266
  }
2260
2267
 
2261
2268
  let authorization = [ authorizationToken ];
2262
- if(!noAuth) {
2263
- authorization.push(await this.MetadataAuth({libraryId, objectId, versionHash, path: linkPath, channelAuth}));
2264
- }
2269
+ authorization.push(await this.MetadataAuth({libraryId, objectId, versionHash, path: linkPath, channelAuth, noAuth}));
2265
2270
 
2266
2271
  if(queryParams.authorization) {
2267
2272
  authorization.push(queryParams.authorization);
@@ -567,6 +567,17 @@ exports.CreateContentObject = async function({libraryId, objectId, options={}})
567
567
  }
568
568
 
569
569
  if(!objectId) {
570
+ const currentAccountAddress = await this.CurrentAccountAddress();
571
+ const canContribute = await this.CallContractMethod({
572
+ contractAddress: this.utils.HashToAddress(libraryId),
573
+ methodName: "canContribute",
574
+ methodArgs: [currentAccountAddress]
575
+ });
576
+
577
+ if(!canContribute) {
578
+ throw Error(`Current user does not have permission to create content in library ${libraryId}`);
579
+ }
580
+
570
581
  this.Log("Deploying contract...");
571
582
  const { contractAddress } = await this.authClient.CreateContentObject({libraryId, typeId});
572
583
 
@@ -270,7 +270,6 @@ const Create = async ({
270
270
  Report(createResponse);
271
271
 
272
272
  const objectId = createResponse.id;
273
- await client.SetVisibility({id: objectId, visibility: 0});
274
273
 
275
274
  console.log("Starting Mezzanine Job(s)");
276
275
 
@@ -0,0 +1,49 @@
1
+ /* eslint-disable no-console */
2
+
3
+ // Removes HLS playout options from an existing offering of a mezzanine
4
+
5
+ const ScriptOffering = require("./parentClasses/ScriptOffering");
6
+
7
+ class OfferingRemoveDash extends ScriptOffering {
8
+
9
+ async body() {
10
+ const client = await this.client();
11
+
12
+ const libraryId = this.args.libraryId;
13
+ const objectId = this.args.objectId;
14
+ const offeringKey = this.args.offeringKey;
15
+
16
+ let dashFound = false;
17
+
18
+ let metadata = await client.ContentObjectMetadata({
19
+ libraryId,
20
+ objectId
21
+ });
22
+
23
+ this.validateOffering(metadata, offeringKey);
24
+
25
+ // loop through playout formats, delete ones where protocol is Dash
26
+ const playoutFormatKeys = Object.keys(metadata.offerings[offeringKey].playout.playout_formats);
27
+ for(let i = 0; i < playoutFormatKeys.length; i++) {
28
+ const key = playoutFormatKeys[i];
29
+ if(metadata.offerings[offeringKey].playout.playout_formats[key].protocol.type === "ProtoDash") {
30
+ console.log("Found Dash playout format '" + key + "', removing...");
31
+ delete metadata.offerings[offeringKey].playout.playout_formats[key];
32
+ dashFound = true;
33
+ }
34
+ }
35
+
36
+ if(dashFound) {
37
+ await this.metadataWrite(metadata);
38
+ } else {
39
+ console.log("No playout formats found with Dash");
40
+ }
41
+ }
42
+
43
+ header() {
44
+ return "Removing playout formats with Dash from mezzanine offering '" + this.args.offeringKey + "'... ";
45
+ }
46
+ }
47
+
48
+ const script = new OfferingRemoveDash;
49
+ script.run();