@openkey/sdk 0.12.0 → 0.12.1-beta.1

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/index.js CHANGED
@@ -387,6 +387,7 @@ var IframeModal = class {
387
387
  root;
388
388
  shadow;
389
389
  iframe;
390
+ card;
390
391
  onClose;
391
392
  onMessage;
392
393
  messageHandler;
@@ -398,6 +399,11 @@ var IframeModal = class {
398
399
  // only uncorrelated resizes from this iframe are accepted (TC-647).
399
400
  expectedRequestId = null;
400
401
  expectedProtocolVersion = null;
402
+ phaseV2 = false;
403
+ currentLayoutId = 0;
404
+ displayedHeight = 0;
405
+ hasDisplayedLayout = false;
406
+ revealTimer;
401
407
  constructor(opts) {
402
408
  this.host = opts.host;
403
409
  this.onClose = opts.onClose;
@@ -428,24 +434,34 @@ var IframeModal = class {
428
434
  backdrop.addEventListener("click", (e) => {
429
435
  if (e.target === backdrop) this.close();
430
436
  });
431
- const card = document.createElement("div");
432
- card.className = "ok-card";
437
+ this.card = document.createElement("div");
438
+ this.card.className = "ok-card";
439
+ if (opts.hideUntilLayout) {
440
+ this.card.inert = true;
441
+ this.card.style.opacity = "0";
442
+ this.card.style.pointerEvents = "none";
443
+ this.card.style.animation = "none";
444
+ }
433
445
  if (isMobile) {
434
446
  const handle = document.createElement("div");
435
447
  handle.className = "ok-handle";
436
- card.appendChild(handle);
448
+ this.card.appendChild(handle);
437
449
  }
438
450
  const closeBtn = document.createElement("button");
439
451
  closeBtn.className = "ok-close";
440
452
  closeBtn.textContent = "\xD7";
441
453
  closeBtn.addEventListener("click", () => this.close());
442
- card.appendChild(closeBtn);
454
+ this.card.appendChild(closeBtn);
443
455
  this.iframe = document.createElement("iframe");
444
456
  this.iframe.src = opts.url;
445
457
  this.iframe.setAttribute("allow", "clipboard-write *; publickey-credentials-get *; publickey-credentials-create *");
446
458
  this.iframe.setAttribute("sandbox", "allow-scripts allow-same-origin allow-forms allow-popups allow-popups-to-escape-sandbox");
447
- card.appendChild(this.iframe);
448
- backdrop.appendChild(card);
459
+ if (opts.hideUntilLayout) {
460
+ this.iframe.style.opacity = "0";
461
+ this.iframe.style.pointerEvents = "none";
462
+ }
463
+ this.card.appendChild(this.iframe);
464
+ backdrop.appendChild(this.card);
449
465
  this.shadow.appendChild(style);
450
466
  this.shadow.appendChild(backdrop);
451
467
  this.messageHandler = (event) => {
@@ -459,16 +475,64 @@ var IframeModal = class {
459
475
  viewportHeight: window.innerHeight
460
476
  });
461
477
  if (h === null) return;
462
- this.iframe.style.height = `${h}px`;
478
+ if (this.phaseV2) {
479
+ if (typeof data.layoutId !== "number" || !Number.isSafeInteger(data.layoutId) || data.layoutId <= this.currentLayoutId) return;
480
+ this.currentLayoutId = data.layoutId;
481
+ this.iframe.style.transition = "none";
482
+ }
483
+ if (!this.phaseV2 || !this.hasDisplayedLayout) {
484
+ this.iframe.style.height = `${h}px`;
485
+ if (this.phaseV2) this.displayedHeight = h;
486
+ }
487
+ if (this.phaseV2) {
488
+ this.revealFrame();
489
+ this.postMessage({
490
+ type: "openkey:layout-applied",
491
+ requestId: this.expectedRequestId,
492
+ protocolVersion: 2,
493
+ layoutId: data.layoutId,
494
+ height: this.hasDisplayedLayout ? this.displayedHeight : h
495
+ });
496
+ }
463
497
  return;
464
498
  }
465
- if (data.type === "openkey:close") {
499
+ if (data.type === "openkey:layout-ready" || data.type === "openkey:layout-invalidated") {
500
+ if (!this.phaseV2 || data.requestId !== this.expectedRequestId || data.protocolVersion !== this.expectedProtocolVersion || data.layoutId !== this.currentLayoutId) return;
501
+ if (data.type === "openkey:layout-ready") {
502
+ this.hasDisplayedLayout = true;
503
+ }
504
+ return;
466
505
  }
467
506
  this.onMessage(data);
468
507
  };
469
508
  window.addEventListener("message", this.messageHandler);
470
509
  document.body.appendChild(this.root);
471
510
  }
511
+ activatePhase(requestId, protocolVersion) {
512
+ this.setExpectedCorrelation(requestId, protocolVersion);
513
+ this.phaseV2 = true;
514
+ this.revealTimer = setTimeout(() => this.revealFrame(), 5e3);
515
+ }
516
+ isVersionedPhase() {
517
+ return this.phaseV2;
518
+ }
519
+ revealFrame() {
520
+ clearTimeout(this.revealTimer);
521
+ this.revealTimer = void 0;
522
+ this.card.inert = false;
523
+ this.iframe.style.opacity = "1";
524
+ this.iframe.style.pointerEvents = "auto";
525
+ this.card.style.opacity = "1";
526
+ this.card.style.pointerEvents = "auto";
527
+ this.iframe.style.visibility = "visible";
528
+ this.card.style.visibility = "visible";
529
+ }
530
+ revealLegacy() {
531
+ this.revealFrame();
532
+ }
533
+ hasDisplayedCurrentPhase() {
534
+ return this.hasDisplayedLayout;
535
+ }
472
536
  postMessage(message) {
473
537
  this.iframe.contentWindow?.postMessage(message, this.host);
474
538
  }
@@ -488,6 +552,7 @@ var IframeModal = class {
488
552
  this.expectedProtocolVersion = protocolVersion;
489
553
  }
490
554
  destroy() {
555
+ clearTimeout(this.revealTimer);
491
556
  window.removeEventListener("message", this.messageHandler);
492
557
  this.root.remove();
493
558
  }
@@ -1074,7 +1139,7 @@ var OpenKey = class {
1074
1139
  return this.openFlow("sign", {
1075
1140
  type: "openkey:sign:request",
1076
1141
  message: request.message,
1077
- keyId: request.keyId
1142
+ keyId: request.keyId ?? this.lastAuth?.keyId
1078
1143
  }, mode);
1079
1144
  }
1080
1145
  signTypedDataWithOpenKey(request, mode) {
@@ -1301,10 +1366,13 @@ var OpenKey = class {
1301
1366
  return new Promise(() => {
1302
1367
  });
1303
1368
  }
1304
- const url = `${this.host}/widget/embed/${action}?origin=${origin}${eoaFlag}${passkeysFlag}`;
1305
- return this.openIframeModal(url, action, message, origin);
1369
+ const selectedKeyId = action === "sign" && "keyId" in message ? message.keyId : null;
1370
+ const phase = action === "connect" || action === "sign" && typeof selectedKeyId === "string" ? { requestId: crypto.randomUUID(), protocolVersion: 2 } : null;
1371
+ const keyId = action === "sign" && "keyId" in message && typeof message.keyId === "string" ? `&keyId=${encodeURIComponent(message.keyId)}` : "";
1372
+ const url = `${this.host}/widget/embed/${action}?origin=${origin}${eoaFlag}${passkeysFlag}${phase ? `&requestId=${encodeURIComponent(phase.requestId)}&protocolVersion=2${keyId}` : ""}`;
1373
+ return this.openIframeModal(url, action, message, origin, phase);
1306
1374
  }
1307
- openIframeModal(url, action, message, origin) {
1375
+ openIframeModal(url, action, message, origin, phase = null) {
1308
1376
  const outgoingRequestId = message.requestId;
1309
1377
  const outgoingProtocolVersion = message.protocolVersion;
1310
1378
  const isVersionedRequest = typeof outgoingRequestId === "string" && typeof outgoingProtocolVersion === "number" && outgoingProtocolVersion >= 1;
@@ -1328,6 +1396,7 @@ var OpenKey = class {
1328
1396
  modal = new IframeModal({
1329
1397
  url,
1330
1398
  host: this.host,
1399
+ hideUntilLayout: action === "sign" && !!phase,
1331
1400
  onClose: () => {
1332
1401
  settle(() => {
1333
1402
  cleanup();
@@ -1335,16 +1404,35 @@ var OpenKey = class {
1335
1404
  });
1336
1405
  },
1337
1406
  onMessage: (data) => {
1407
+ if (settled) return;
1338
1408
  if (data.type === "openkey:ready") {
1409
+ if (readyReceived) return;
1410
+ if (phase && data.protocolVersion === 2) {
1411
+ if (data.requestId !== phase.requestId) return;
1412
+ modal?.activatePhase(phase.requestId, phase.protocolVersion);
1413
+ modal?.postMessage({
1414
+ ...message,
1415
+ ...phase,
1416
+ ...action === "sign" && isVersionedRequest && outgoingProtocolVersion === 1 ? { authorizationProtocolVersion: 1 } : {}
1417
+ });
1418
+ } else if (phase && data.protocolVersion !== void 0 && data.protocolVersion !== 1) {
1419
+ return;
1420
+ } else {
1421
+ modal?.setExpectedCorrelation(
1422
+ isVersionedRequest ? outgoingRequestId : null,
1423
+ isVersionedRequest ? outgoingProtocolVersion : null
1424
+ );
1425
+ modal?.revealLegacy();
1426
+ modal?.postMessage(message);
1427
+ }
1339
1428
  readyReceived = true;
1340
- modal?.postMessage(message);
1341
1429
  return;
1342
1430
  }
1343
- if (isVersionedRequest) {
1344
- const respRequestId = data.requestId;
1345
- const respVersion = data.protocolVersion;
1346
- if (respRequestId !== outgoingRequestId) return;
1347
- if (respVersion !== outgoingProtocolVersion) return;
1431
+ if (!readyReceived) return;
1432
+ const activeRequestId = phase && modal?.isVersionedPhase() ? phase.requestId : isVersionedRequest ? outgoingRequestId : null;
1433
+ const activeVersion = phase && modal?.isVersionedPhase() ? phase.protocolVersion : isVersionedRequest ? outgoingProtocolVersion : null;
1434
+ if (activeRequestId !== null) {
1435
+ if (!("requestId" in data) || data.requestId !== activeRequestId || !("protocolVersion" in data) || data.protocolVersion !== activeVersion) return;
1348
1436
  }
1349
1437
  if (data.type === "openkey:close") {
1350
1438
  settle(() => {
@@ -1354,7 +1442,7 @@ var OpenKey = class {
1354
1442
  return;
1355
1443
  }
1356
1444
  if (data.type === "openkey:link-wallet:delegate") {
1357
- this.handleWalletLinkDelegation(modal);
1445
+ this.handleWalletLinkDelegation(modal, modal?.isVersionedPhase() ? phase : null);
1358
1446
  return;
1359
1447
  }
1360
1448
  if (data.type === "openkey:auth:use-external-wallet") {
@@ -1362,6 +1450,7 @@ var OpenKey = class {
1362
1450
  this.handleExternalWalletConnect(resolve, reject);
1363
1451
  return;
1364
1452
  }
1453
+ if (action === "sign" && modal?.isVersionedPhase() && !modal.hasDisplayedCurrentPhase() && this.isResponseForAction(action, data)) return;
1365
1454
  if (this.isResponseForAction(action, data)) {
1366
1455
  settle(() => {
1367
1456
  cleanup();
@@ -1439,8 +1528,8 @@ var OpenKey = class {
1439
1528
  if (action === "sign-out") return type === "openkey:sign-out:response";
1440
1529
  return false;
1441
1530
  }
1442
- handleWalletLinkDelegation(modal) {
1443
- const sendResult = (result) => modal.postMessage(result);
1531
+ handleWalletLinkDelegation(modal, phase = null) {
1532
+ const sendResult = (result) => modal.postMessage({ ...result, ...phase });
1444
1533
  new WalletPicker({
1445
1534
  providers: this.discoveredProviders,
1446
1535
  onCancel: () => {