@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.mjs CHANGED
@@ -352,6 +352,7 @@ var IframeModal = class {
352
352
  root;
353
353
  shadow;
354
354
  iframe;
355
+ card;
355
356
  onClose;
356
357
  onMessage;
357
358
  messageHandler;
@@ -363,6 +364,11 @@ var IframeModal = class {
363
364
  // only uncorrelated resizes from this iframe are accepted (TC-647).
364
365
  expectedRequestId = null;
365
366
  expectedProtocolVersion = null;
367
+ phaseV2 = false;
368
+ currentLayoutId = 0;
369
+ displayedHeight = 0;
370
+ hasDisplayedLayout = false;
371
+ revealTimer;
366
372
  constructor(opts) {
367
373
  this.host = opts.host;
368
374
  this.onClose = opts.onClose;
@@ -393,24 +399,34 @@ var IframeModal = class {
393
399
  backdrop.addEventListener("click", (e) => {
394
400
  if (e.target === backdrop) this.close();
395
401
  });
396
- const card = document.createElement("div");
397
- card.className = "ok-card";
402
+ this.card = document.createElement("div");
403
+ this.card.className = "ok-card";
404
+ if (opts.hideUntilLayout) {
405
+ this.card.inert = true;
406
+ this.card.style.opacity = "0";
407
+ this.card.style.pointerEvents = "none";
408
+ this.card.style.animation = "none";
409
+ }
398
410
  if (isMobile) {
399
411
  const handle = document.createElement("div");
400
412
  handle.className = "ok-handle";
401
- card.appendChild(handle);
413
+ this.card.appendChild(handle);
402
414
  }
403
415
  const closeBtn = document.createElement("button");
404
416
  closeBtn.className = "ok-close";
405
417
  closeBtn.textContent = "\xD7";
406
418
  closeBtn.addEventListener("click", () => this.close());
407
- card.appendChild(closeBtn);
419
+ this.card.appendChild(closeBtn);
408
420
  this.iframe = document.createElement("iframe");
409
421
  this.iframe.src = opts.url;
410
422
  this.iframe.setAttribute("allow", "clipboard-write *; publickey-credentials-get *; publickey-credentials-create *");
411
423
  this.iframe.setAttribute("sandbox", "allow-scripts allow-same-origin allow-forms allow-popups allow-popups-to-escape-sandbox");
412
- card.appendChild(this.iframe);
413
- backdrop.appendChild(card);
424
+ if (opts.hideUntilLayout) {
425
+ this.iframe.style.opacity = "0";
426
+ this.iframe.style.pointerEvents = "none";
427
+ }
428
+ this.card.appendChild(this.iframe);
429
+ backdrop.appendChild(this.card);
414
430
  this.shadow.appendChild(style);
415
431
  this.shadow.appendChild(backdrop);
416
432
  this.messageHandler = (event) => {
@@ -424,16 +440,64 @@ var IframeModal = class {
424
440
  viewportHeight: window.innerHeight
425
441
  });
426
442
  if (h === null) return;
427
- this.iframe.style.height = `${h}px`;
443
+ if (this.phaseV2) {
444
+ if (typeof data.layoutId !== "number" || !Number.isSafeInteger(data.layoutId) || data.layoutId <= this.currentLayoutId) return;
445
+ this.currentLayoutId = data.layoutId;
446
+ this.iframe.style.transition = "none";
447
+ }
448
+ if (!this.phaseV2 || !this.hasDisplayedLayout) {
449
+ this.iframe.style.height = `${h}px`;
450
+ if (this.phaseV2) this.displayedHeight = h;
451
+ }
452
+ if (this.phaseV2) {
453
+ this.revealFrame();
454
+ this.postMessage({
455
+ type: "openkey:layout-applied",
456
+ requestId: this.expectedRequestId,
457
+ protocolVersion: 2,
458
+ layoutId: data.layoutId,
459
+ height: this.hasDisplayedLayout ? this.displayedHeight : h
460
+ });
461
+ }
428
462
  return;
429
463
  }
430
- if (data.type === "openkey:close") {
464
+ if (data.type === "openkey:layout-ready" || data.type === "openkey:layout-invalidated") {
465
+ if (!this.phaseV2 || data.requestId !== this.expectedRequestId || data.protocolVersion !== this.expectedProtocolVersion || data.layoutId !== this.currentLayoutId) return;
466
+ if (data.type === "openkey:layout-ready") {
467
+ this.hasDisplayedLayout = true;
468
+ }
469
+ return;
431
470
  }
432
471
  this.onMessage(data);
433
472
  };
434
473
  window.addEventListener("message", this.messageHandler);
435
474
  document.body.appendChild(this.root);
436
475
  }
476
+ activatePhase(requestId, protocolVersion) {
477
+ this.setExpectedCorrelation(requestId, protocolVersion);
478
+ this.phaseV2 = true;
479
+ this.revealTimer = setTimeout(() => this.revealFrame(), 5e3);
480
+ }
481
+ isVersionedPhase() {
482
+ return this.phaseV2;
483
+ }
484
+ revealFrame() {
485
+ clearTimeout(this.revealTimer);
486
+ this.revealTimer = void 0;
487
+ this.card.inert = false;
488
+ this.iframe.style.opacity = "1";
489
+ this.iframe.style.pointerEvents = "auto";
490
+ this.card.style.opacity = "1";
491
+ this.card.style.pointerEvents = "auto";
492
+ this.iframe.style.visibility = "visible";
493
+ this.card.style.visibility = "visible";
494
+ }
495
+ revealLegacy() {
496
+ this.revealFrame();
497
+ }
498
+ hasDisplayedCurrentPhase() {
499
+ return this.hasDisplayedLayout;
500
+ }
437
501
  postMessage(message) {
438
502
  this.iframe.contentWindow?.postMessage(message, this.host);
439
503
  }
@@ -453,6 +517,7 @@ var IframeModal = class {
453
517
  this.expectedProtocolVersion = protocolVersion;
454
518
  }
455
519
  destroy() {
520
+ clearTimeout(this.revealTimer);
456
521
  window.removeEventListener("message", this.messageHandler);
457
522
  this.root.remove();
458
523
  }
@@ -1039,7 +1104,7 @@ var OpenKey = class {
1039
1104
  return this.openFlow("sign", {
1040
1105
  type: "openkey:sign:request",
1041
1106
  message: request.message,
1042
- keyId: request.keyId
1107
+ keyId: request.keyId ?? this.lastAuth?.keyId
1043
1108
  }, mode);
1044
1109
  }
1045
1110
  signTypedDataWithOpenKey(request, mode) {
@@ -1266,10 +1331,13 @@ var OpenKey = class {
1266
1331
  return new Promise(() => {
1267
1332
  });
1268
1333
  }
1269
- const url = `${this.host}/widget/embed/${action}?origin=${origin}${eoaFlag}${passkeysFlag}`;
1270
- return this.openIframeModal(url, action, message, origin);
1334
+ const selectedKeyId = action === "sign" && "keyId" in message ? message.keyId : null;
1335
+ const phase = action === "connect" || action === "sign" && typeof selectedKeyId === "string" ? { requestId: crypto.randomUUID(), protocolVersion: 2 } : null;
1336
+ const keyId = action === "sign" && "keyId" in message && typeof message.keyId === "string" ? `&keyId=${encodeURIComponent(message.keyId)}` : "";
1337
+ const url = `${this.host}/widget/embed/${action}?origin=${origin}${eoaFlag}${passkeysFlag}${phase ? `&requestId=${encodeURIComponent(phase.requestId)}&protocolVersion=2${keyId}` : ""}`;
1338
+ return this.openIframeModal(url, action, message, origin, phase);
1271
1339
  }
1272
- openIframeModal(url, action, message, origin) {
1340
+ openIframeModal(url, action, message, origin, phase = null) {
1273
1341
  const outgoingRequestId = message.requestId;
1274
1342
  const outgoingProtocolVersion = message.protocolVersion;
1275
1343
  const isVersionedRequest = typeof outgoingRequestId === "string" && typeof outgoingProtocolVersion === "number" && outgoingProtocolVersion >= 1;
@@ -1293,6 +1361,7 @@ var OpenKey = class {
1293
1361
  modal = new IframeModal({
1294
1362
  url,
1295
1363
  host: this.host,
1364
+ hideUntilLayout: action === "sign" && !!phase,
1296
1365
  onClose: () => {
1297
1366
  settle(() => {
1298
1367
  cleanup();
@@ -1300,16 +1369,35 @@ var OpenKey = class {
1300
1369
  });
1301
1370
  },
1302
1371
  onMessage: (data) => {
1372
+ if (settled) return;
1303
1373
  if (data.type === "openkey:ready") {
1374
+ if (readyReceived) return;
1375
+ if (phase && data.protocolVersion === 2) {
1376
+ if (data.requestId !== phase.requestId) return;
1377
+ modal?.activatePhase(phase.requestId, phase.protocolVersion);
1378
+ modal?.postMessage({
1379
+ ...message,
1380
+ ...phase,
1381
+ ...action === "sign" && isVersionedRequest && outgoingProtocolVersion === 1 ? { authorizationProtocolVersion: 1 } : {}
1382
+ });
1383
+ } else if (phase && data.protocolVersion !== void 0 && data.protocolVersion !== 1) {
1384
+ return;
1385
+ } else {
1386
+ modal?.setExpectedCorrelation(
1387
+ isVersionedRequest ? outgoingRequestId : null,
1388
+ isVersionedRequest ? outgoingProtocolVersion : null
1389
+ );
1390
+ modal?.revealLegacy();
1391
+ modal?.postMessage(message);
1392
+ }
1304
1393
  readyReceived = true;
1305
- modal?.postMessage(message);
1306
1394
  return;
1307
1395
  }
1308
- if (isVersionedRequest) {
1309
- const respRequestId = data.requestId;
1310
- const respVersion = data.protocolVersion;
1311
- if (respRequestId !== outgoingRequestId) return;
1312
- if (respVersion !== outgoingProtocolVersion) return;
1396
+ if (!readyReceived) return;
1397
+ const activeRequestId = phase && modal?.isVersionedPhase() ? phase.requestId : isVersionedRequest ? outgoingRequestId : null;
1398
+ const activeVersion = phase && modal?.isVersionedPhase() ? phase.protocolVersion : isVersionedRequest ? outgoingProtocolVersion : null;
1399
+ if (activeRequestId !== null) {
1400
+ if (!("requestId" in data) || data.requestId !== activeRequestId || !("protocolVersion" in data) || data.protocolVersion !== activeVersion) return;
1313
1401
  }
1314
1402
  if (data.type === "openkey:close") {
1315
1403
  settle(() => {
@@ -1319,7 +1407,7 @@ var OpenKey = class {
1319
1407
  return;
1320
1408
  }
1321
1409
  if (data.type === "openkey:link-wallet:delegate") {
1322
- this.handleWalletLinkDelegation(modal);
1410
+ this.handleWalletLinkDelegation(modal, modal?.isVersionedPhase() ? phase : null);
1323
1411
  return;
1324
1412
  }
1325
1413
  if (data.type === "openkey:auth:use-external-wallet") {
@@ -1327,6 +1415,7 @@ var OpenKey = class {
1327
1415
  this.handleExternalWalletConnect(resolve, reject);
1328
1416
  return;
1329
1417
  }
1418
+ if (action === "sign" && modal?.isVersionedPhase() && !modal.hasDisplayedCurrentPhase() && this.isResponseForAction(action, data)) return;
1330
1419
  if (this.isResponseForAction(action, data)) {
1331
1420
  settle(() => {
1332
1421
  cleanup();
@@ -1404,8 +1493,8 @@ var OpenKey = class {
1404
1493
  if (action === "sign-out") return type === "openkey:sign-out:response";
1405
1494
  return false;
1406
1495
  }
1407
- handleWalletLinkDelegation(modal) {
1408
- const sendResult = (result) => modal.postMessage(result);
1496
+ handleWalletLinkDelegation(modal, phase = null) {
1497
+ const sendResult = (result) => modal.postMessage({ ...result, ...phase });
1409
1498
  new WalletPicker({
1410
1499
  providers: this.discoveredProviders,
1411
1500
  onCancel: () => {