@eluvio/elv-client-js 4.2.20 → 4.2.22

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.
@@ -244,6 +244,53 @@ exports.DeleteNTPInstance = /*#__PURE__*/function () {
244
244
  };
245
245
  }();
246
246
 
247
+ /**
248
+ * Generate a report for the specified NTP instance.
249
+ *
250
+ * @methodGroup NTP Instances
251
+ * @namedParams
252
+ * @param {string} tenantId - The ID of the tenant in which this NTP instance was created
253
+ * @param {string} ntpId - The ID of the NTP instance
254
+ * @param {string} password - The code associated with the NTP instance
255
+ * @param {string=} email - Email address associated with the code
256
+ */
257
+ exports.ReportNTPInstance = /*#__PURE__*/function () {
258
+ var _ref10 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee5(_ref9) {
259
+ var tenantId, ntpId, password, email, paramsJSON, res;
260
+ return _regeneratorRuntime.wrap(function _callee5$(_context5) {
261
+ while (1) switch (_context5.prev = _context5.next) {
262
+ case 0:
263
+ tenantId = _ref9.tenantId, ntpId = _ref9.ntpId, password = _ref9.password, email = _ref9.email;
264
+ ValidatePresence("tenantId", tenantId);
265
+ ValidatePresence("ntpId", ntpId);
266
+ paramsJSON = [];
267
+ if (password) {
268
+ paramsJSON.push("pwd:".concat(password));
269
+ }
270
+ if (email) {
271
+ paramsJSON.push("eml:".concat(email));
272
+ }
273
+ _context5.next = 8;
274
+ return this.authClient.MakeKMSCall({
275
+ tenantId: tenantId,
276
+ methodName: "elv_updateOTPInstance",
277
+ params: [tenantId, ntpId, "report", JSON.stringify(paramsJSON), Date.now()],
278
+ paramTypes: ["string", "string", "string", "string", "int"]
279
+ });
280
+ case 8:
281
+ res = _context5.sent;
282
+ return _context5.abrupt("return", res || {});
283
+ case 10:
284
+ case "end":
285
+ return _context5.stop();
286
+ }
287
+ }, _callee5, this);
288
+ }));
289
+ return function (_x5) {
290
+ return _ref10.apply(this, arguments);
291
+ };
292
+ }();
293
+
247
294
  /**
248
295
  * Retrieve info for NTP instances in the specified tenant
249
296
  *
@@ -256,14 +303,14 @@ exports.DeleteNTPInstance = /*#__PURE__*/function () {
256
303
  * @return {Object} - List of NTP instances along with pagination information
257
304
  */
258
305
  exports.ListNTPInstances = /*#__PURE__*/function () {
259
- var _ref10 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee5(_ref9) {
260
- var tenantId, _ref9$count, count, _ref9$offset, offset, _yield$this$authClien2, Defs, Total;
261
- return _regeneratorRuntime.wrap(function _callee5$(_context5) {
262
- while (1) switch (_context5.prev = _context5.next) {
306
+ var _ref12 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee6(_ref11) {
307
+ var tenantId, _ref11$count, count, _ref11$offset, offset, _yield$this$authClien2, Defs, Total;
308
+ return _regeneratorRuntime.wrap(function _callee6$(_context6) {
309
+ while (1) switch (_context6.prev = _context6.next) {
263
310
  case 0:
264
- tenantId = _ref9.tenantId, _ref9$count = _ref9.count, count = _ref9$count === void 0 ? 10 : _ref9$count, _ref9$offset = _ref9.offset, offset = _ref9$offset === void 0 ? 0 : _ref9$offset;
311
+ tenantId = _ref11.tenantId, _ref11$count = _ref11.count, count = _ref11$count === void 0 ? 10 : _ref11$count, _ref11$offset = _ref11.offset, offset = _ref11$offset === void 0 ? 0 : _ref11$offset;
265
312
  ValidatePresence("tenantId", tenantId);
266
- _context5.next = 4;
313
+ _context6.next = 4;
267
314
  return this.authClient.MakeKMSCall({
268
315
  tenantId: tenantId,
269
316
  methodName: "elv_listOTPInfo",
@@ -272,10 +319,10 @@ exports.ListNTPInstances = /*#__PURE__*/function () {
272
319
  signature: false
273
320
  });
274
321
  case 4:
275
- _yield$this$authClien2 = _context5.sent;
322
+ _yield$this$authClien2 = _context6.sent;
276
323
  Defs = _yield$this$authClien2.Defs;
277
324
  Total = _yield$this$authClien2.Total;
278
- return _context5.abrupt("return", {
325
+ return _context6.abrupt("return", {
279
326
  ntpInstances: Object.values(Defs || {}).map(FormatNTPInfo),
280
327
  start: offset,
281
328
  end: Math.min(Total, offset + count),
@@ -283,12 +330,12 @@ exports.ListNTPInstances = /*#__PURE__*/function () {
283
330
  });
284
331
  case 8:
285
332
  case "end":
286
- return _context5.stop();
333
+ return _context6.stop();
287
334
  }
288
- }, _callee5, this);
335
+ }, _callee6, this);
289
336
  }));
290
- return function (_x5) {
291
- return _ref10.apply(this, arguments);
337
+ return function (_x6) {
338
+ return _ref12.apply(this, arguments);
292
339
  };
293
340
  }();
294
341
 
@@ -303,16 +350,16 @@ exports.ListNTPInstances = /*#__PURE__*/function () {
303
350
  * @return {Object} - Info about the NTP instance
304
351
  */
305
352
  exports.NTPInstance = /*#__PURE__*/function () {
306
- var _ref12 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee6(_ref11) {
353
+ var _ref14 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee7(_ref13) {
307
354
  var tenantId, ntpId;
308
- return _regeneratorRuntime.wrap(function _callee6$(_context6) {
309
- while (1) switch (_context6.prev = _context6.next) {
355
+ return _regeneratorRuntime.wrap(function _callee7$(_context7) {
356
+ while (1) switch (_context7.prev = _context7.next) {
310
357
  case 0:
311
- tenantId = _ref11.tenantId, ntpId = _ref11.ntpId;
358
+ tenantId = _ref13.tenantId, ntpId = _ref13.ntpId;
312
359
  ValidatePresence("tenantId", tenantId);
313
360
  ValidatePresence("ntpId", ntpId);
314
- _context6.t0 = FormatNTPInfo;
315
- _context6.next = 6;
361
+ _context7.t0 = FormatNTPInfo;
362
+ _context7.next = 6;
316
363
  return this.authClient.MakeKMSCall({
317
364
  tenantId: tenantId,
318
365
  methodName: "elv_getOTPInfo",
@@ -321,16 +368,16 @@ exports.NTPInstance = /*#__PURE__*/function () {
321
368
  signature: false
322
369
  });
323
370
  case 6:
324
- _context6.t1 = _context6.sent;
325
- return _context6.abrupt("return", (0, _context6.t0)(_context6.t1));
371
+ _context7.t1 = _context7.sent;
372
+ return _context7.abrupt("return", (0, _context7.t0)(_context7.t1));
326
373
  case 8:
327
374
  case "end":
328
- return _context6.stop();
375
+ return _context7.stop();
329
376
  }
330
- }, _callee6, this);
377
+ }, _callee7, this);
331
378
  }));
332
- return function (_x6) {
333
- return _ref12.apply(this, arguments);
379
+ return function (_x7) {
380
+ return _ref14.apply(this, arguments);
334
381
  };
335
382
  }();
336
383
 
@@ -351,12 +398,12 @@ exports.NTPInstance = /*#__PURE__*/function () {
351
398
  * @return {Promise<Object>} - The generated ticket code and additional information about the ticket.
352
399
  */
353
400
  exports.IssueNTPCode = /*#__PURE__*/function () {
354
- var _ref14 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee7(_ref13) {
401
+ var _ref16 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee8(_ref15) {
355
402
  var tenantId, ntpId, email, maxRedemptions, options, params, paramTypes;
356
- return _regeneratorRuntime.wrap(function _callee7$(_context7) {
357
- while (1) switch (_context7.prev = _context7.next) {
403
+ return _regeneratorRuntime.wrap(function _callee8$(_context8) {
404
+ while (1) switch (_context8.prev = _context8.next) {
358
405
  case 0:
359
- tenantId = _ref13.tenantId, ntpId = _ref13.ntpId, email = _ref13.email, maxRedemptions = _ref13.maxRedemptions;
406
+ tenantId = _ref15.tenantId, ntpId = _ref15.ntpId, email = _ref15.email, maxRedemptions = _ref15.maxRedemptions;
360
407
  ValidatePresence("tenantId", tenantId);
361
408
  ValidatePresence("ntpId", ntpId);
362
409
  options = [];
@@ -368,22 +415,22 @@ exports.IssueNTPCode = /*#__PURE__*/function () {
368
415
  }
369
416
  params = [tenantId, ntpId, JSON.stringify(options), Date.now()];
370
417
  paramTypes = ["string", "string", "string", "uint"];
371
- _context7.next = 10;
418
+ _context8.next = 10;
372
419
  return this.authClient.MakeKMSCall({
373
420
  methodName: "elv_issueOTPCode",
374
421
  params: params,
375
422
  paramTypes: paramTypes
376
423
  });
377
424
  case 10:
378
- return _context7.abrupt("return", _context7.sent);
425
+ return _context8.abrupt("return", _context8.sent);
379
426
  case 11:
380
427
  case "end":
381
- return _context7.stop();
428
+ return _context8.stop();
382
429
  }
383
- }, _callee7, this);
430
+ }, _callee8, this);
384
431
  }));
385
- return function (_x7) {
386
- return _ref14.apply(this, arguments);
432
+ return function (_x8) {
433
+ return _ref16.apply(this, arguments);
387
434
  };
388
435
  }();
389
436
 
@@ -404,13 +451,13 @@ exports.IssueNTPCode = /*#__PURE__*/function () {
404
451
  * @return {Promise<Object>} - The generated signed ticket code and additional information about the ticket.
405
452
  */
406
453
  exports.IssueSignedNTPCode = /*#__PURE__*/function () {
407
- var _ref16 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee8(_ref15) {
454
+ var _ref18 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee9(_ref17) {
408
455
  var tenantId, ntpId, email, maxRedemptions, result, signature, multiSig;
409
- return _regeneratorRuntime.wrap(function _callee8$(_context8) {
410
- while (1) switch (_context8.prev = _context8.next) {
456
+ return _regeneratorRuntime.wrap(function _callee9$(_context9) {
457
+ while (1) switch (_context9.prev = _context9.next) {
411
458
  case 0:
412
- tenantId = _ref15.tenantId, ntpId = _ref15.ntpId, email = _ref15.email, maxRedemptions = _ref15.maxRedemptions;
413
- _context8.next = 3;
459
+ tenantId = _ref17.tenantId, ntpId = _ref17.ntpId, email = _ref17.email, maxRedemptions = _ref17.maxRedemptions;
460
+ _context9.next = 3;
414
461
  return this.IssueNTPCode({
415
462
  tenantId: tenantId,
416
463
  ntpId: ntpId,
@@ -418,27 +465,75 @@ exports.IssueSignedNTPCode = /*#__PURE__*/function () {
418
465
  maxRedemptions: maxRedemptions
419
466
  });
420
467
  case 3:
421
- result = _context8.sent;
468
+ result = _context9.sent;
422
469
  if (!result.token) {
423
- _context8.next = 10;
470
+ _context9.next = 10;
424
471
  break;
425
472
  }
426
- _context8.next = 7;
473
+ _context9.next = 7;
427
474
  return this.authClient.Sign(Ethers.utils.keccak256(Ethers.utils.toUtf8Bytes(result.token)));
428
475
  case 7:
429
- signature = _context8.sent;
476
+ signature = _context9.sent;
430
477
  multiSig = this.utils.FormatSignature(signature);
431
478
  result.token = "".concat(result.token, ".").concat(this.utils.B64(multiSig));
432
479
  case 10:
433
- return _context8.abrupt("return", result);
480
+ return _context9.abrupt("return", result);
434
481
  case 11:
435
482
  case "end":
436
- return _context8.stop();
483
+ return _context9.stop();
437
484
  }
438
- }, _callee8, this);
485
+ }, _callee9, this);
439
486
  }));
440
- return function (_x8) {
441
- return _ref16.apply(this, arguments);
487
+ return function (_x9) {
488
+ return _ref18.apply(this, arguments);
489
+ };
490
+ }();
491
+
492
+ /**
493
+ * Check the status of the specified ticket/code without redeeming it.
494
+ *
495
+ * @methodGroup Tickets
496
+ * @namedParams
497
+ * @param {string} tenantId - The ID of the tenant from which the ticket was issued
498
+ * @param {string} ntpId - The ID of the NTP instance from which the ticket was issued
499
+ * @param {string} code - Access code
500
+ * @param {string=} email - Email address associated with the code
501
+ *
502
+ * @return {Promise<Object>} - Status information for the ticket
503
+ */
504
+ exports.NTPStatus = /*#__PURE__*/function () {
505
+ var _ref20 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee10(_ref19) {
506
+ var tenantId, ntpId, code, email, response;
507
+ return _regeneratorRuntime.wrap(function _callee10$(_context10) {
508
+ while (1) switch (_context10.prev = _context10.next) {
509
+ case 0:
510
+ tenantId = _ref19.tenantId, ntpId = _ref19.ntpId, code = _ref19.code, email = _ref19.email;
511
+ ValidatePresence("tenantId", tenantId);
512
+ ValidatePresence("ntpId", ntpId);
513
+ ValidatePresence("code", code);
514
+ _context10.next = 6;
515
+ return this.HttpClient.Request({
516
+ method: "POST",
517
+ path: UrlJoin("ks", "otp", "ntp", tenantId, ntpId, "status"),
518
+ body: {
519
+ "_PASSWORD": code,
520
+ "_EMAIL": email
521
+ }
522
+ });
523
+ case 6:
524
+ response = _context10.sent;
525
+ _context10.next = 9;
526
+ return response.json();
527
+ case 9:
528
+ return _context10.abrupt("return", _context10.sent);
529
+ case 10:
530
+ case "end":
531
+ return _context10.stop();
532
+ }
533
+ }, _callee10, this);
534
+ }));
535
+ return function (_x10) {
536
+ return _ref20.apply(this, arguments);
442
537
  };
443
538
  }();
444
539
 
@@ -457,12 +552,12 @@ exports.IssueSignedNTPCode = /*#__PURE__*/function () {
457
552
  * @return {Promise<string|Object>} - The object ID which the ticket is authorized to, or an object containing the object ID and NTP ID if `includeNTPId` is specified
458
553
  */
459
554
  exports.RedeemCode = /*#__PURE__*/function () {
460
- var _ref18 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee9(_ref17) {
461
- var issuer, tenantId, ntpId, code, email, _ref17$includeNTPId, includeNTPId, wallet, token, response, objectId, libraryId, Hash, codeHash, codeInfo, ak, sites, info, signer;
462
- return _regeneratorRuntime.wrap(function _callee9$(_context9) {
463
- while (1) switch (_context9.prev = _context9.next) {
555
+ var _ref22 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee11(_ref21) {
556
+ var issuer, tenantId, ntpId, code, email, _ref21$includeNTPId, includeNTPId, wallet, token, response, objectId, libraryId, Hash, codeHash, codeInfo, ak, sites, info, signer;
557
+ return _regeneratorRuntime.wrap(function _callee11$(_context11) {
558
+ while (1) switch (_context11.prev = _context11.next) {
464
559
  case 0:
465
- issuer = _ref17.issuer, tenantId = _ref17.tenantId, ntpId = _ref17.ntpId, code = _ref17.code, email = _ref17.email, _ref17$includeNTPId = _ref17.includeNTPId, includeNTPId = _ref17$includeNTPId === void 0 ? false : _ref17$includeNTPId;
560
+ issuer = _ref21.issuer, tenantId = _ref21.tenantId, ntpId = _ref21.ntpId, code = _ref21.code, email = _ref21.email, _ref21$includeNTPId = _ref21.includeNTPId, includeNTPId = _ref21$includeNTPId === void 0 ? false : _ref21$includeNTPId;
466
561
  wallet = this.GenerateWallet();
467
562
  issuer = issuer || "";
468
563
  if (!this.signer) {
@@ -473,15 +568,15 @@ exports.RedeemCode = /*#__PURE__*/function () {
473
568
  });
474
569
  }
475
570
  if (!issuer.startsWith("iq__")) {
476
- _context9.next = 8;
571
+ _context11.next = 8;
477
572
  break;
478
573
  }
479
574
  ValidateObject(issuer);
480
- _context9.next = 28;
575
+ _context11.next = 28;
481
576
  break;
482
577
  case 8:
483
578
  if (!(issuer && !issuer.replace(/^\//, "").startsWith("otp/ntp/iten"))) {
484
- _context9.next = 12;
579
+ _context11.next = 12;
485
580
  break;
486
581
  }
487
582
  throw Error("Invalid issuer: " + issuer);
@@ -492,38 +587,38 @@ exports.RedeemCode = /*#__PURE__*/function () {
492
587
  if (!issuer) {
493
588
  issuer = UrlJoin("/otp", "ntp", tenantId, ntpId || "");
494
589
  }
495
- _context9.prev = 14;
496
- _context9.next = 17;
590
+ _context11.prev = 14;
591
+ _context11.next = 17;
497
592
  return this.authClient.GenerateChannelContentToken({
498
593
  issuer: issuer,
499
594
  code: code,
500
595
  email: email
501
596
  });
502
597
  case 17:
503
- token = _context9.sent;
598
+ token = _context11.sent;
504
599
  this.SetStaticToken({
505
600
  token: token
506
601
  });
507
602
  response = JSON.parse(this.utils.FromB64(token));
508
- return _context9.abrupt("return", includeNTPId ? {
603
+ return _context11.abrupt("return", includeNTPId ? {
509
604
  objectId: response.qid,
510
605
  ntpId: response.oid
511
606
  } : response.qid);
512
607
  case 23:
513
- _context9.prev = 23;
514
- _context9.t0 = _context9["catch"](14);
608
+ _context11.prev = 23;
609
+ _context11.t0 = _context11["catch"](14);
515
610
  this.Log("Failed to redeem code:", true);
516
- this.Log(_context9.t0, true);
517
- throw _context9.t0;
611
+ this.Log(_context11.t0, true);
612
+ throw _context11.t0;
518
613
  case 28:
519
614
  // Site selector
520
615
  objectId = issuer;
521
- _context9.next = 31;
616
+ _context11.next = 31;
522
617
  return this.ContentObjectLibraryId({
523
618
  objectId: objectId
524
619
  });
525
620
  case 31:
526
- libraryId = _context9.sent;
621
+ libraryId = _context11.sent;
527
622
  Hash = function Hash(code) {
528
623
  var chars = code.split("").map(function (code) {
529
624
  return code.charCodeAt(0);
@@ -533,49 +628,49 @@ exports.RedeemCode = /*#__PURE__*/function () {
533
628
  }, 0).toString();
534
629
  };
535
630
  codeHash = Hash(code);
536
- _context9.next = 36;
631
+ _context11.next = 36;
537
632
  return this.ContentObjectMetadata({
538
633
  libraryId: libraryId,
539
634
  objectId: objectId,
540
635
  metadataSubtree: "public/codes/".concat(codeHash)
541
636
  });
542
637
  case 36:
543
- codeInfo = _context9.sent;
638
+ codeInfo = _context11.sent;
544
639
  if (codeInfo) {
545
- _context9.next = 40;
640
+ _context11.next = 40;
546
641
  break;
547
642
  }
548
643
  this.Log("Code redemption failed:\n\t".concat(issuer, "\n\t").concat(code));
549
644
  throw Error("Invalid code: " + code);
550
645
  case 40:
551
646
  ak = codeInfo.ak, sites = codeInfo.sites, info = codeInfo.info;
552
- _context9.next = 43;
647
+ _context11.next = 43;
553
648
  return wallet.AddAccountFromEncryptedPK({
554
649
  encryptedPrivateKey: this.utils.FromB64(ak),
555
650
  password: code
556
651
  });
557
652
  case 43:
558
- signer = _context9.sent;
653
+ signer = _context11.sent;
559
654
  this.SetSigner({
560
655
  signer: signer
561
656
  });
562
657
 
563
658
  // Ensure wallet is initialized
564
- _context9.next = 47;
659
+ _context11.next = 47;
565
660
  return this.userProfileClient.WalletAddress();
566
661
  case 47:
567
- return _context9.abrupt("return", {
662
+ return _context11.abrupt("return", {
568
663
  addr: this.utils.FormatAddress(signer.address),
569
664
  sites: sites,
570
665
  info: info || {}
571
666
  });
572
667
  case 48:
573
668
  case "end":
574
- return _context9.stop();
669
+ return _context11.stop();
575
670
  }
576
- }, _callee9, this, [[14, 23]]);
671
+ }, _callee11, this, [[14, 23]]);
577
672
  }));
578
- return function (_x9) {
579
- return _ref18.apply(this, arguments);
673
+ return function (_x11) {
674
+ return _ref22.apply(this, arguments);
580
675
  };
581
676
  }();
@@ -0,0 +1,45 @@
1
+ var LiveRecordingConfigDefault = {
2
+ drm_type: "clear",
3
+ recording_config: {
4
+ part_ttl: 86400,
5
+ reconnect_timeout: 3600,
6
+ connection_timeout: 3600,
7
+ copy_mpegts: false
8
+ },
9
+ profile: {
10
+ ladder_specs: {
11
+ audio: [{
12
+ bit_rate: 192000,
13
+ channels: 2,
14
+ codecs: "mp4a.40.2"
15
+ }, {
16
+ bit_rate: 384000,
17
+ channels: 6,
18
+ codecs: "mp4a.40.2"
19
+ }],
20
+ video: [{
21
+ bit_rate: 9500000,
22
+ codecs: "avc1.640028,mp4a.40.2",
23
+ height: 1080,
24
+ width: 1920
25
+ }, {
26
+ bit_rate: 4500000,
27
+ codecs: "avc1.640028,mp4a.40.2",
28
+ height: 720,
29
+ width: 1280
30
+ }, {
31
+ bit_rate: 2000000,
32
+ codecs: "avc1.640028,mp4a.40.2",
33
+ height: 540,
34
+ width: 960
35
+ }, {
36
+ bit_rate: 900000,
37
+ codecs: "avc1.640028,mp4a.40.2",
38
+ height: 540,
39
+ width: 960
40
+ }]
41
+ },
42
+ name: "Default"
43
+ }
44
+ };
45
+ module.exports = LiveRecordingConfigDefault;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eluvio/elv-client-js",
3
- "version": "4.2.20",
3
+ "version": "4.2.22",
4
4
  "description": "Javascript client for the Eluvio Content Fabric",
5
5
  "main": "src/index.js",
6
6
  "author": "Kevin Talmadge",
package/src/ElvClient.js CHANGED
@@ -1348,7 +1348,9 @@ class ElvClient {
1348
1348
 
1349
1349
  ValidatePresence("message", message);
1350
1350
 
1351
- return await this.Crypto.DecryptCap(message, this.signer._signingKey().privateKey);
1351
+ return this.signer.remoteSigner ?
1352
+ await this.signer.DecryptCap(message) :
1353
+ await this.Crypto.DecryptCap(message, this.signer._signingKey().privateKey);
1352
1354
  }
1353
1355
 
1354
1356
  /**
package/src/HttpClient.js CHANGED
@@ -96,6 +96,13 @@ class HttpClient {
96
96
  // Save current URI for all future requests involving this write token
97
97
  this.draftURIs[writeToken] = baseURI;
98
98
  }
99
+
100
+ // If write token is present in headers, we may get redirected even if we try and use the right node.
101
+ // When a network request is redirected, the authorization header is dropped, which will cause issues.
102
+ // Ensure it is present in query params as well
103
+ if((headers.Authorization || headers.authorization) && !queryParams.authorization) {
104
+ queryParams.authorization = headers.Authorization || headers.authorization;
105
+ }
99
106
  }
100
107
 
101
108
  let uri = baseURI
@@ -47,7 +47,7 @@ class RemoteSigner extends Ethers.Signer {
47
47
  body.code = this.userIdCode;
48
48
  }
49
49
 
50
- const {addr, eth, token} = await Utils.ResponseToJson(
50
+ const {addr, eth, token, pubkey} = await Utils.ResponseToJson(
51
51
  this.HttpClient.Request({
52
52
  path: UrlJoin("as", "wlt", "login", this.userIdCode ? "code" : "jwt"),
53
53
  method: "POST",
@@ -61,9 +61,10 @@ class RemoteSigner extends Ethers.Signer {
61
61
  this.authToken = token;
62
62
  this.address = Utils.FormatAddress(addr);
63
63
  this.id = eth;
64
+ this.publicKey = pubkey;
64
65
  }
65
66
 
66
- if(!this.address) {
67
+ if(!this.address || !this.publicKey) {
67
68
  const keys = await Utils.ResponseToJson(
68
69
  this.HttpClient.Request({
69
70
  method: "GET",
@@ -74,12 +75,18 @@ class RemoteSigner extends Ethers.Signer {
74
75
  })
75
76
  );
76
77
 
77
- const address = keys.eth[0];
78
+ if(!this.address) {
79
+ const address = keys.eth[0];
78
80
 
79
- if(address && address.startsWith("0x")) {
80
- this.address = address;
81
- } else {
82
- this.address = Utils.HashToAddress(keys.eth[0]);
81
+ if(address && address.startsWith("0x")) {
82
+ this.address = address;
83
+ } else {
84
+ this.address = Utils.HashToAddress(keys.eth[0]);
85
+ }
86
+ }
87
+
88
+ if(!this.publicKey) {
89
+ this.publicKey = keys.pubkey && keys.pubkey[0];
83
90
  }
84
91
  }
85
92
 
@@ -170,6 +177,63 @@ class RemoteSigner extends Ethers.Signer {
170
177
  return this.address;
171
178
  }
172
179
 
180
+ _normalizePublicKey(key) {
181
+ const with0x = key.startsWith("0x") ? key : `0x${key}`;
182
+ return with0x.length === 2 + 128 ? `0x04${with0x.slice(2)}` : with0x;
183
+ }
184
+
185
+ /**
186
+ * This signer's public key, as provided by the authd service
187
+ *
188
+ * @return {Promise<string>} - The public key, in uncompressed hex like SigningKey.publicKey
189
+ */
190
+ async PublicKey() {
191
+ if(!this.publicKey) {
192
+ throw Error("RemoteSigner: public key not available - call Initialize() first");
193
+ }
194
+
195
+ return this._normalizePublicKey(this.publicKey);
196
+ }
197
+
198
+ /** so remote signers can be used interchangeably with local signers */
199
+ _signingKey() {
200
+ if(!this.publicKey) {
201
+ throw Error("RemoteSigner: public key not available - call Initialize() first");
202
+ }
203
+
204
+ const publicKey = this._normalizePublicKey(this.publicKey);
205
+ return {
206
+ publicKey,
207
+ get privateKey() {
208
+ throw Error("RemoteSigner: remote signer does not have direct access to a private key");
209
+ }
210
+ };
211
+ }
212
+
213
+ /**
214
+ * Decrypt a secp256k1 ECIES-encrypted blob (e.g. a fabric encryption conk) that was wrapped
215
+ * for this signer's public key, via the authd service's generic decrypt endpoint.
216
+ *
217
+ * @param {string} encryptedData - Base64-encoded ECIES-encrypted blob
218
+ * @return {Promise<Object>} - The decrypted, JSON-parsed contents
219
+ */
220
+ async DecryptCap(encryptedData) {
221
+ const {data} = await Utils.ResponseToJson(
222
+ this.HttpClient.Request({
223
+ method: "POST",
224
+ path: UrlJoin("as", "wlt", "decrypt", "eth", this.id),
225
+ headers: {
226
+ Authorization: `Bearer ${this.authToken}`
227
+ },
228
+ body: {
229
+ data: encryptedData
230
+ }
231
+ })
232
+ );
233
+
234
+ return JSON.parse(Buffer.from(data, "base64").toString());
235
+ }
236
+
173
237
  async signDigest(digest) {
174
238
  if(!this.signatureCache[digest]) {
175
239
  this.signatureCache[digest] = new Promise(async (resolve, reject) => {
@@ -2718,7 +2718,7 @@ exports.LinkData = async function({libraryId, objectId, versionHash, writeToken,
2718
2718
 
2719
2719
  exports.CreateEncryptionConk = async function({libraryId, objectId, versionHash, writeToken, createKMSConk=true}) {
2720
2720
  if(this.signer.remoteSigner) {
2721
- return;
2721
+ await this.signer.PublicKey();
2722
2722
  }
2723
2723
 
2724
2724
  ValidateParameters({libraryId, objectId, versionHash});
@@ -2743,7 +2743,9 @@ exports.CreateEncryptionConk = async function({libraryId, objectId, versionHash,
2743
2743
  });
2744
2744
 
2745
2745
  if(existingUserCap) {
2746
- this.encryptionConks[objectId] = await this.Crypto.DecryptCap(existingUserCap, this.signer._signingKey().privateKey);
2746
+ this.encryptionConks[objectId] = this.signer.remoteSigner ?
2747
+ await this.signer.DecryptCap(existingUserCap) :
2748
+ await this.Crypto.DecryptCap(existingUserCap, this.signer._signingKey().privateKey);
2747
2749
  } else {
2748
2750
  this.encryptionConks[objectId] = await this.Crypto.GeneratePrimaryConk({
2749
2751
  spaceId: this.contentSpaceId,
@@ -2846,7 +2848,9 @@ exports.EncryptionConk = async function({libraryId, objectId, versionHash, write
2846
2848
  });
2847
2849
 
2848
2850
  if(existingUserCap) {
2849
- this.encryptionConks[objectId] = await this.Crypto.DecryptCap(existingUserCap, this.signer._signingKey().privateKey);
2851
+ this.encryptionConks[objectId] = this.signer.remoteSigner ?
2852
+ await this.signer.DecryptCap(existingUserCap) :
2853
+ await this.Crypto.DecryptCap(existingUserCap, this.signer._signingKey().privateKey);
2850
2854
  } else if(writeToken) {
2851
2855
  await this.CreateEncryptionConk({libraryId, objectId, versionHash, writeToken, createKMSConk: false});
2852
2856
  } else {