@seams/wallet 0.6.0 → 0.6.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.
Files changed (128) hide show
  1. package/dist/.build-inputs.sha256 +1 -1
  2. package/dist/esm/SeamsWeb/SeamsWeb.js +1 -0
  3. package/dist/esm/SeamsWeb/operations/registration/registration.js +170 -33
  4. package/dist/esm/SeamsWeb/operations/registration/registrationTiming.js +33 -2
  5. package/dist/esm/SeamsWeb/signingSurface/BrowserSigningSurface.js +3 -0
  6. package/dist/esm/SeamsWeb/walletIframe/client/overlay/overlay-controller.js +63 -10
  7. package/dist/esm/core/rpcClients/relayer/walletRegistration.js +88 -4
  8. package/dist/esm/core/signingEngine/session/passkey/prfCache.js +24 -4
  9. package/dist/esm/core/signingEngine/uiConfirm/PasskeyMpcSessionDurableState.js +5 -3
  10. package/dist/esm/core/signingEngine/uiConfirm/PasskeyMpcSessionManager.js +40 -3
  11. package/dist/esm/core/signingEngine/uiConfirm/ui/preact/TransactionReceipt.js +31 -35
  12. package/dist/esm/core/signingEngine/uiConfirm/ui/preact/mountConfirmationSurface.js +64 -10
  13. package/dist/esm/core/signingEngine/walletCustody/ceremonyDriver.js +1 -1
  14. package/dist/esm/react/SeamsWeb/SeamsWeb.js +1 -0
  15. package/dist/esm/react/SeamsWeb/operations/registration/registration.js +170 -33
  16. package/dist/esm/react/SeamsWeb/operations/registration/registrationTiming.js +33 -2
  17. package/dist/esm/react/SeamsWeb/signingSurface/BrowserSigningSurface.js +3 -0
  18. package/dist/esm/react/SeamsWeb/walletIframe/client/overlay/overlay-controller.js +63 -10
  19. package/dist/esm/react/core/rpcClients/relayer/walletRegistration.js +88 -4
  20. package/dist/esm/react/core/signingEngine/session/passkey/prfCache.js +24 -4
  21. package/dist/esm/react/core/signingEngine/uiConfirm/PasskeyMpcSessionDurableState.js +5 -3
  22. package/dist/esm/react/core/signingEngine/uiConfirm/PasskeyMpcSessionManager.js +40 -3
  23. package/dist/esm/react/core/signingEngine/uiConfirm/ui/preact/TransactionReceipt.js +31 -35
  24. package/dist/esm/react/core/signingEngine/uiConfirm/ui/preact/mountConfirmationSurface.js +64 -10
  25. package/dist/esm/react/core/signingEngine/walletCustody/ceremonyDriver.js +1 -1
  26. package/dist/esm/react/shared-ts/src/utils/routerAbEd25519Yao.js +13 -1
  27. package/dist/esm/sdk/{adapters-Dgy69gf0.js → adapters-LgE4nnos.js} +95 -45
  28. package/dist/esm/sdk/{defaultConfigs-DJCLCrg9.js → defaultConfigs-CyNOW4Sy.js} +1 -1
  29. package/dist/{public/sdk/ecdsaCapabilityManifest-DA_fklIs.js → esm/sdk/ecdsaCapabilityManifest-C8itxV9S.js} +1 -1
  30. package/dist/{public/sdk/ecdsaPresignLifecycle-D_KCktCj.js → esm/sdk/ecdsaPresignLifecycle-CnSnzoRJ.js} +13 -1
  31. package/dist/esm/sdk/{ed25519SeedMaterial-0VmS6K9P.js → ed25519SeedMaterial-Cghz8-XB.js} +2 -2
  32. package/dist/esm/sdk/{exactSessionState-C2aAv_ED.js → exactSessionState-Bt0HforB.js} +64 -11
  33. package/dist/esm/sdk/{export-viewer-host-NhjFdpm-.js → export-viewer-host-B3K81QGA.js} +1 -1
  34. package/dist/esm/sdk/{host-DACTruOj.js → host-Y_xmIzPO.js} +2 -2
  35. package/dist/esm/sdk/{localOnly-DTNq69fJ.js → localOnly-B5TYHJiq.js} +2 -2
  36. package/dist/{public/sdk/nearEd25519YaoMaterialActivation-4AuGG2DG.js → esm/sdk/nearEd25519YaoMaterialActivation-BLxVE6E5.js} +89 -5
  37. package/dist/esm/sdk/{nearEd25519YaoSigningPreparation-jiGcQylO.js → nearEd25519YaoSigningPreparation-DX6xG-IW.js} +1 -1
  38. package/dist/esm/sdk/{prfCache-Dwwauj4v.js → prfCache-CgAr-VEU.js} +24 -4
  39. package/dist/{public/sdk/recovery-entrypoint-CFTX6PFZ.js → esm/sdk/recovery-entrypoint-D39R1avB.js} +3 -3
  40. package/dist/{public/sdk/registration-CuP1WmQu.js → esm/sdk/registration-BtPLgKHk.js} +1 -1
  41. package/dist/esm/sdk/{registration-D8nYJKec.js → registration-D-istkMZ.js} +253 -38
  42. package/dist/esm/sdk/{registrationPreparationPreload-DDe0sbZi.js → registrationPreparationPreload-CvnlDCVn.js} +2 -2
  43. package/dist/{public/sdk/router-DeX_cJ2f.js → esm/sdk/router-CeFS9SgT.js} +3 -3
  44. package/dist/{public/sdk/routerAbNormalSigning-BGpRKRAj.js → esm/sdk/routerAbNormalSigning-DktZKnf1.js} +1 -1
  45. package/dist/{public/sdk/runtime-auth-Ch00YcH5.js → esm/sdk/runtime-auth-B7z1ANNp.js} +8 -8
  46. package/dist/esm/sdk/{runtime-device-link-CEhVZYAw.js → runtime-device-link-B8HGDakg.js} +4 -4
  47. package/dist/esm/sdk/{runtime-ecdsa-tempo-B-qMRrmx.js → runtime-ecdsa-tempo-DKdS5-us.js} +5 -5
  48. package/dist/{public/sdk/runtime-email-otp-giyMPib8.js → esm/sdk/runtime-email-otp-D5bxhdyG.js} +4 -4
  49. package/dist/{public/sdk/runtime-export-CV-6G1Oy.js → esm/sdk/runtime-export--hvNrx8l.js} +4 -4
  50. package/dist/{public/sdk/runtime-near-DoDcS88O.js → esm/sdk/runtime-near-CEexHoug.js} +4 -4
  51. package/dist/{public/sdk/runtime-preferences-Canyenle.js → esm/sdk/runtime-preferences-BiqPp1lV.js} +4 -4
  52. package/dist/esm/sdk/{runtime-recovery-lWyILD1g.js → runtime-recovery-BYu1gDq_.js} +4 -4
  53. package/dist/esm/sdk/{runtimeContext-BdTaYxJD.js → runtimeContext-CH97jPZ0.js} +80 -37
  54. package/dist/{public/sdk/runtimeLoader-Dxn8UA8B.js → esm/sdk/runtimeLoader-BFAmJAbu.js} +9 -9
  55. package/dist/esm/sdk/{secp256k1-CQFsI3qQ.js → secp256k1-Cr1jBW1n.js} +3 -3
  56. package/dist/esm/sdk/{signEvmFamily-CZLET02E.js → signEvmFamily-Dxk4sBPY.js} +7 -7
  57. package/dist/esm/sdk/{signNear-BeUWiWm_.js → signNear-B0OCVKoH.js} +6 -6
  58. package/dist/esm/sdk/{signerLoader-C_w8vuhm.js → signerLoader-D0WU1jq_.js} +1 -1
  59. package/dist/{public/sdk/transactionState-Dd13hMoY.js → esm/sdk/transactionState-Bpm4GamO.js} +2 -2
  60. package/dist/esm/sdk/tx-confirm-ui.js +134 -93
  61. package/dist/esm/sdk/wallet-iframe-host-ecdsa.js +1 -1
  62. package/dist/esm/sdk/wallet-iframe-host-full.js +1 -1
  63. package/dist/esm/sdk/wallet-iframe-host-near.js +1 -1
  64. package/dist/esm/sdk/wallet-iframe-host-runtime.js +1 -1
  65. package/dist/esm/sdk/wallet-ui.css +85 -31
  66. package/dist/{public/sdk/walletRecoveryCommit-DNvzgeIX.js → esm/sdk/walletRecoveryCommit-G6w6N5RV.js} +3 -3
  67. package/dist/esm/sdk/{warmSessionHydration-CCKeEIIy.js → warmSessionHydration-DDNYdTCz.js} +1 -1
  68. package/dist/esm/shared-ts/src/utils/routerAbEd25519Yao.js +13 -1
  69. package/dist/public/headers.manifest.json +1 -1
  70. package/dist/public/sdk/{adapters-Dgy69gf0.js → adapters-LgE4nnos.js} +95 -45
  71. package/dist/public/sdk/{defaultConfigs-DJCLCrg9.js → defaultConfigs-CyNOW4Sy.js} +1 -1
  72. package/dist/{esm/sdk/ecdsaCapabilityManifest-DA_fklIs.js → public/sdk/ecdsaCapabilityManifest-C8itxV9S.js} +1 -1
  73. package/dist/{esm/sdk/ecdsaPresignLifecycle-D_KCktCj.js → public/sdk/ecdsaPresignLifecycle-CnSnzoRJ.js} +13 -1
  74. package/dist/public/sdk/{ed25519SeedMaterial-0VmS6K9P.js → ed25519SeedMaterial-Cghz8-XB.js} +2 -2
  75. package/dist/public/sdk/{exactSessionState-C2aAv_ED.js → exactSessionState-Bt0HforB.js} +64 -11
  76. package/dist/public/sdk/{export-viewer-host-NhjFdpm-.js → export-viewer-host-B3K81QGA.js} +1 -1
  77. package/dist/public/sdk/{host-DACTruOj.js → host-Y_xmIzPO.js} +2 -2
  78. package/dist/public/sdk/{localOnly-DTNq69fJ.js → localOnly-B5TYHJiq.js} +2 -2
  79. package/dist/{esm/sdk/nearEd25519YaoMaterialActivation-4AuGG2DG.js → public/sdk/nearEd25519YaoMaterialActivation-BLxVE6E5.js} +89 -5
  80. package/dist/public/sdk/{nearEd25519YaoSigningPreparation-jiGcQylO.js → nearEd25519YaoSigningPreparation-DX6xG-IW.js} +1 -1
  81. package/dist/public/sdk/{prfCache-Dwwauj4v.js → prfCache-CgAr-VEU.js} +24 -4
  82. package/dist/{esm/sdk/recovery-entrypoint-CFTX6PFZ.js → public/sdk/recovery-entrypoint-D39R1avB.js} +3 -3
  83. package/dist/{esm/sdk/registration-CuP1WmQu.js → public/sdk/registration-BtPLgKHk.js} +1 -1
  84. package/dist/public/sdk/{registration-D8nYJKec.js → registration-D-istkMZ.js} +253 -38
  85. package/dist/public/sdk/{registrationPreparationPreload-DDe0sbZi.js → registrationPreparationPreload-CvnlDCVn.js} +2 -2
  86. package/dist/{esm/sdk/router-DeX_cJ2f.js → public/sdk/router-CeFS9SgT.js} +3 -3
  87. package/dist/{esm/sdk/routerAbNormalSigning-BGpRKRAj.js → public/sdk/routerAbNormalSigning-DktZKnf1.js} +1 -1
  88. package/dist/{esm/sdk/runtime-auth-Ch00YcH5.js → public/sdk/runtime-auth-B7z1ANNp.js} +8 -8
  89. package/dist/public/sdk/{runtime-device-link-CEhVZYAw.js → runtime-device-link-B8HGDakg.js} +4 -4
  90. package/dist/public/sdk/{runtime-ecdsa-tempo-B-qMRrmx.js → runtime-ecdsa-tempo-DKdS5-us.js} +5 -5
  91. package/dist/{esm/sdk/runtime-email-otp-giyMPib8.js → public/sdk/runtime-email-otp-D5bxhdyG.js} +4 -4
  92. package/dist/{esm/sdk/runtime-export-CV-6G1Oy.js → public/sdk/runtime-export--hvNrx8l.js} +4 -4
  93. package/dist/{esm/sdk/runtime-near-DoDcS88O.js → public/sdk/runtime-near-CEexHoug.js} +4 -4
  94. package/dist/{esm/sdk/runtime-preferences-Canyenle.js → public/sdk/runtime-preferences-BiqPp1lV.js} +4 -4
  95. package/dist/public/sdk/{runtime-recovery-lWyILD1g.js → runtime-recovery-BYu1gDq_.js} +4 -4
  96. package/dist/public/sdk/{runtimeContext-BdTaYxJD.js → runtimeContext-CH97jPZ0.js} +80 -37
  97. package/dist/{esm/sdk/runtimeLoader-Dxn8UA8B.js → public/sdk/runtimeLoader-BFAmJAbu.js} +9 -9
  98. package/dist/public/sdk/{secp256k1-CQFsI3qQ.js → secp256k1-Cr1jBW1n.js} +3 -3
  99. package/dist/public/sdk/{signEvmFamily-CZLET02E.js → signEvmFamily-Dxk4sBPY.js} +7 -7
  100. package/dist/public/sdk/{signNear-BeUWiWm_.js → signNear-B0OCVKoH.js} +6 -6
  101. package/dist/public/sdk/{signerLoader-C_w8vuhm.js → signerLoader-D0WU1jq_.js} +1 -1
  102. package/dist/{esm/sdk/transactionState-Dd13hMoY.js → public/sdk/transactionState-Bpm4GamO.js} +2 -2
  103. package/dist/public/sdk/tx-confirm-ui.js +134 -93
  104. package/dist/public/sdk/wallet-iframe-host-ecdsa.js +1 -1
  105. package/dist/public/sdk/wallet-iframe-host-full.js +1 -1
  106. package/dist/public/sdk/wallet-iframe-host-near.js +1 -1
  107. package/dist/public/sdk/wallet-iframe-host-runtime.js +1 -1
  108. package/dist/public/sdk/wallet-ui.css +85 -31
  109. package/dist/{esm/sdk/walletRecoveryCommit-DNvzgeIX.js → public/sdk/walletRecoveryCommit-G6w6N5RV.js} +3 -3
  110. package/dist/public/sdk/{warmSessionHydration-CCKeEIIy.js → warmSessionHydration-DDNYdTCz.js} +1 -1
  111. package/dist/public/sdk/workers/passkey-mpc-session.worker.js +92 -8
  112. package/dist/public/wallet-assets.manifest.json +74 -74
  113. package/dist/public/wallet-service/index.html +4 -4
  114. package/dist/types/wallet/src/SeamsWeb/operations/registration/registration.d.ts +15 -0
  115. package/dist/types/wallet/src/SeamsWeb/operations/registration/registrationTiming.d.ts +11 -1
  116. package/dist/types/wallet/src/SeamsWeb/signingSurface/BrowserSigningSurface.d.ts +6 -0
  117. package/dist/types/wallet/src/SeamsWeb/signingSurface/ports.d.ts +8 -2
  118. package/dist/types/wallet/src/core/rpcClients/relayer/walletRegistration.d.ts +49 -10
  119. package/dist/types/wallet/src/core/signingEngine/session/passkey/prfCache.d.ts +7 -9
  120. package/dist/types/wallet/src/core/signingEngine/session/passkey/warmSessionHydration.d.ts +7 -8
  121. package/dist/types/wallet/src/core/signingEngine/session/passkey/warmSessionMaterialWriter.d.ts +9 -9
  122. package/dist/types/wallet/src/core/signingEngine/session/warmCapabilities/public.d.ts +7 -8
  123. package/dist/types/wallet/src/core/signingEngine/uiConfirm/PasskeyMpcSessionDurableState.d.ts +3 -0
  124. package/dist/types/wallet/src/core/signingEngine/uiConfirm/uiConfirm.types.d.ts +6 -0
  125. package/dist/types/wallet/src/core/signingEngine/workerManager/workers/shamir3pass/clientSealPreparation.d.ts +2 -0
  126. package/dist/types/wallet/src/core/types/secure-confirm-worker.d.ts +15 -1
  127. package/dist/workers/passkey-mpc-session.worker.js +92 -8
  128. package/package.json +1 -1
@@ -12,7 +12,7 @@ import { parseSdkEcdsaDerivationSigningRootId, parseSdkEcdsaDerivationSigningRoo
12
12
  import { parseCorrelationId, parseDigestB64u, parseIsoTimestamp } from "../../../shared-ts/src/utils/canonicalPrimitives.js";
13
13
  import { parseCanonicalEcdsaServerActivationRequest } from "../../../shared-ts/src/utils/ecdsaCapabilityActivation.js";
14
14
  import { findRegistrationSignerPlanEvmFamilyEcdsaBranch, findRegistrationSignerPlanNearEd25519Branch, parseNearEd25519SigningKeyId, registrationSignerPlanFromSelection, walletIdFromString } from "../../../shared-ts/src/utils/registrationIntent.js";
15
- import { ROUTER_AB_ED25519_YAO_EMAIL_OTP_RECOVERY_BOOTSTRAP_KIND_V1 } from "../../../shared-ts/src/utils/routerAbEd25519Yao.js";
15
+ import { ROUTER_AB_ED25519_YAO_EMAIL_OTP_RECOVERY_BOOTSTRAP_KIND_V1, sameRouterAbEd25519YaoRegistrationAdmissionRequestV1 } from "../../../shared-ts/src/utils/routerAbEd25519Yao.js";
16
16
  import { buildEmailOtpWalletAuthAuthority, parseEmailOtpWalletAuthAuthority, walletAuthAuthorityRef } from "../../../shared-ts/src/utils/walletAuthAuthority.js";
17
17
  import { parseRouterAbEcdsaVerifiedClientActivationFactsV1 } from "../../../shared-ts/src/utils/routerAbEcdsaDerivation.js";
18
18
  import { thresholdEcdsaChainTargetFromChainFamily, toWalletId } from "../../../core/signingEngine/interfaces/ecdsaChainTarget.js";
@@ -39,7 +39,7 @@ import { planPendingNearRegistration, preparePendingNearRegistration } from "../
39
39
  import { walletSessionAuthorizations } from "../../../core/indexedDB/seamsWalletDB/walletSessionAuthorizationStore.js";
40
40
  import { IndexedDBManager } from "../../../core/indexedDB/index.js";
41
41
  import { nearEd25519YaoMaterialActivationFromMetadata } from "../../../core/signingEngine/session/material/nearEd25519YaoMaterialActivation.js";
42
- import { activateWalletRegistration, completeWalletRegistrationNearProvisioning, createWalletAddSignerIntent, finalizeWalletAddSigner, isEmailOtpWalletRegistrationFinalizeResponse, parseWalletRegistrationEcdsaDerivationRespond, respondWalletRegistration, setupWalletRegistration, startWalletAddSigner } from "../../../core/rpcClients/relayer/walletRegistration.js";
42
+ import { activateWalletRegistration, authorizeWalletRegistrationNearAdmission, completeWalletRegistrationNearProvisioning, createWalletAddSignerIntent, finalizeWalletAddSigner, isEmailOtpWalletRegistrationFinalizeResponse, parseWalletRegistrationEcdsaDerivationRespond, respondWalletRegistration, setupWalletRegistration, startWalletAddSigner } from "../../../core/rpcClients/relayer/walletRegistration.js";
43
43
  import { persistPasskeyEd25519YaoSignerMaterialV1 } from "../../../core/signingEngine/session/passkey/ed25519YaoLocalMaterial.js";
44
44
  import { buildPasskeyEd25519RestoreMetadata } from "../../../core/signingEngine/session/passkey/ed25519YaoSealedSession.js";
45
45
  import { prepareWalletEcdsaRegistrationPublication, prepareWalletEd25519RegistrationPublication, prepareWalletEmailOtpEd25519RegistrationPublication } from "../../../core/signingEngine/flows/registration/accountLifecycle.js";
@@ -48,7 +48,7 @@ import { establishUnlockedWalletEd25519ExportRootCapabilityV1, walletCustodyCere
48
48
  import { rememberPasskeyCustodySessionEnvelope } from "../../../core/signingEngine/session/passkey/passkeyCustodySessionCache.js";
49
49
  import { listConfiguredThresholdEcdsaPublicationTargets } from "../session/thresholdEcdsaProvisioning.js";
50
50
  import { openWalletCustodyEd25519ActiveClientV1, walletCustodyCacheEnvelopeFromRecordV1 } from "../../../core/signingEngine/walletCustody/openCustodyCache.js";
51
- import { RegistrationTimingRecorder, assertNever, createFailedRegistrationTimingSummary, createSucceededRegistrationTimingSummary, emitNearRegistrationTiming, emitRegistrationTimingSpan, emitRegistrationTimingSummary, recordNearRegistrationSessionTiming, recordStrictEcdsaServerTimingBuckets, registrationTimingSignerSetFromPlan, roundDurationMs, zeroEmailOtpYaoPrewarmDiagnostics } from "./registrationTiming.js";
51
+ import { RegistrationTimingRecorder, assertNever, createFailedRegistrationTimingSummary, createSucceededRegistrationTimingSummary, emitNearRegistrationTiming, emitRegistrationTimingSpan, emitRegistrationTimingSummary, recordNearRegistrationSessionTiming, recordRegistrationServerTimingBuckets, recordStrictEcdsaServerTimingBuckets, registrationTimingSignerSetFromPlan, roundDurationMs, zeroEmailOtpYaoPrewarmDiagnostics } from "./registrationTiming.js";
52
52
  import { joinCustodyWireFromEnvelopeRecord } from "../../../core/signingEngine/walletCustody/joinCustodyWire.js";
53
53
  import { buildStrictRegistrationClientBootstrap, closeStrictEcdsaRegistrationCeremony, finalizeStrictEcdsaFamilyLocalActivation, measureStrictEcdsaCeremonyStep, registrationRouteHeaders, requireIssuedRegistrationEstablishedSession, runStrictEcdsaFamilyCeremony } from "./registrationStrictEcdsa.js";
54
54
  import { admitDeferredNearRegistration, buildRegistrationEmailOtpEd25519SessionState, passkeyWalletAuthAuthorityFromCredential, registrationEd25519MaterialFacts, registrationEstablishedEd25519Session, requireEd25519YaoRegistrationPublicResultMatches, requireEmailOtpEd25519YaoRegistrationPublicResultMatches, requireEmailOtpRegistrationEnrollmentMaterial, requirePasskeyRegistrationIntent } from "./registrationEd25519Yao.js";
@@ -472,6 +472,49 @@ function registrationThreeRouteAuthorityPayload(authority) {
472
472
  default: return assertNever(authority);
473
473
  }
474
474
  }
475
+ async function startEarlyNearRegistrationAdmission(args) {
476
+ const startedAt = performance.now();
477
+ try {
478
+ const deferredNear = (await authorizeWalletRegistrationNearAdmission({
479
+ relayerUrl: args.relayerUrl,
480
+ headers: registrationRouteHeaders(args.traceContext),
481
+ registrationCeremonyId: args.registrationCeremonyId,
482
+ signedSetup: args.signedSetup,
483
+ ...registrationThreeRouteAuthorityPayload(args.authority)
484
+ })).ed25519;
485
+ const admissionReceipt = await admitDeferredNearRegistration(deferredNear, {
486
+ routerOrigin: new URL(args.relayerUrl).origin,
487
+ authorization: {
488
+ kind: "bearer",
489
+ value: `Bearer ${args.signedSetup}`
490
+ },
491
+ fetch: globalThis.fetch,
492
+ ...args.traceContext ? { traceContext: args.traceContext } : {}
493
+ });
494
+ emitNearRegistrationTiming({
495
+ ceremonyId: args.registrationCeremonyId,
496
+ stage: "early_admission",
497
+ startedAt,
498
+ outcome: "success"
499
+ });
500
+ return {
501
+ deferredNear,
502
+ admissionReceipt
503
+ };
504
+ } catch (error) {
505
+ emitNearRegistrationTiming({
506
+ ceremonyId: args.registrationCeremonyId,
507
+ stage: "early_admission",
508
+ startedAt,
509
+ outcome: "failure"
510
+ });
511
+ throw error;
512
+ }
513
+ }
514
+ function requireEarlyNearRegistrationAdmission(admission) {
515
+ if (!admission) throw new Error("Mixed registration did not start NEAR admission");
516
+ return admission;
517
+ }
475
518
  function registrationEd25519LaneAuthorization(auth, passkeyCredentialIdB64u, session) {
476
519
  switch (auth.kind) {
477
520
  case "passkey": return { auth: {
@@ -602,6 +645,32 @@ async function setupRegistrationForPasskeyExecution(args) {
602
645
  }) !== state.binding || String(intent.walletId) !== String(args.passkeyExecution.prepared.walletId) || challengeB64u !== args.passkeyExecution.prepared.challengeB64u) throw new Error("Hosted passkey registration preparation binding changed");
603
646
  return setup;
604
647
  }
648
+ function ecdsaRegistrationClientCeremonyForExecution(args) {
649
+ if (args.passkeyExecution.kind === "collect_during_registration") return { kind: "create_after_authority" };
650
+ const state = hostedPasskeyRegistrationState(args.passkeyExecution.prepared);
651
+ if (state.ecdsaClientCeremony.kind !== "started" || state.ecdsaClientCeremony.ceremonyId !== args.ceremonyId) throw new Error("Hosted passkey registration has no matching ECDSA client ceremony");
652
+ return {
653
+ kind: "use_hosted_preparation",
654
+ ceremonyId: state.ecdsaClientCeremony.ceremonyId,
655
+ operation: state.ecdsaClientCeremony.operation
656
+ };
657
+ }
658
+ async function awaitHostedPreparedEcdsaClientCeremony(operation) {
659
+ return await operation;
660
+ }
661
+ function ecdsaRegistrationClientCeremonyOperation(args) {
662
+ switch (args.clientCeremony.kind) {
663
+ case "create_after_authority": return args.context.signingEngine.createRouterAbEcdsaRegistrationCeremony.bind(args.context.signingEngine, {
664
+ kind: "create_router_ab_ecdsa_registration_ceremony_v1",
665
+ ceremonyId: args.ceremonyId,
666
+ registration: args.registration
667
+ });
668
+ case "use_hosted_preparation":
669
+ if (args.clientCeremony.ceremonyId !== args.ceremonyId) throw new Error("Prepared ECDSA client ceremony identity changed");
670
+ return awaitHostedPreparedEcdsaClientCeremony.bind(void 0, args.clientCeremony.operation);
671
+ default: return assertNever(args.clientCeremony);
672
+ }
673
+ }
605
674
  async function runEcdsaEnabledThreeRouteRegistrationCeremony(args) {
606
675
  const [firstChainTarget, ...remainingChainTargets] = args.ecdsaPrepare.chainTargets;
607
676
  if (!firstChainTarget) throw new Error("Strict ECDSA ceremony requires at least one EVM-family target");
@@ -612,12 +681,21 @@ async function runEcdsaEnabledThreeRouteRegistrationCeremony(args) {
612
681
  const created = await measureStrictEcdsaCeremonyStep({
613
682
  registrationTiming: args.registrationTiming,
614
683
  bucket: "ecdsaRegistrationClientCreateMs",
615
- operation: args.context.signingEngine.createRouterAbEcdsaRegistrationCeremony.bind(args.context.signingEngine, {
616
- kind: "create_router_ab_ecdsa_registration_ceremony_v1",
684
+ operation: ecdsaRegistrationClientCeremonyOperation({
685
+ context: args.context,
617
686
  ceremonyId,
618
- registration: args.ecdsaPrepare.strictRegistration
687
+ registration: args.ecdsaPrepare.strictRegistration,
688
+ clientCeremony: args.clientCeremony
619
689
  })
620
690
  });
691
+ const earlyNearAdmission = args.signerPlanKind === "near_ed25519_and_evm_family_ecdsa" ? startEarlyNearRegistrationAdmission({
692
+ relayerUrl: args.relayerUrl,
693
+ registrationCeremonyId: ceremonyId,
694
+ signedSetup: args.signedSetup,
695
+ authority: args.authority,
696
+ traceContext: args.traceContext
697
+ }) : null;
698
+ earlyNearAdmission?.catch(ignoreNearCustodyFailure);
621
699
  const responded = await measureStrictEcdsaCeremonyStep({
622
700
  registrationTiming: args.registrationTiming,
623
701
  bucket: "ecdsaRegistrationGatewayRespondMs",
@@ -699,6 +777,7 @@ async function runEcdsaEnabledThreeRouteRegistrationCeremony(args) {
699
777
  });
700
778
  deferredNearCustodyWork = args.startDeferredNearCustody({
701
779
  deferredNear,
780
+ earlyAdmission: requireEarlyNearRegistrationAdmission(earlyNearAdmission),
702
781
  establishedEvmCustodyCommit: bootstrap.preActivationCommitPayload
703
782
  });
704
783
  deferredNearCustodyWork.catch(ignoreNearCustodyFailure);
@@ -996,13 +1075,23 @@ async function startDeferredNearWalletCustody(base, input) {
996
1075
  operation: "near_provisioning"
997
1076
  });
998
1077
  if (!pending || pending.operation !== "near_provisioning" || pending.phase !== "planned") throw new Error("NEAR registration has no planned continuation");
1078
+ let earlyAdmissionReceipt;
1079
+ try {
1080
+ const early = await input.earlyAdmission;
1081
+ if (!sameRouterAbEd25519YaoRegistrationAdmissionRequestV1(early.deferredNear.admissionRequest, pending.admissionRequest)) throw new Error("Early NEAR admission changed the authorized request");
1082
+ earlyAdmissionReceipt = early.admissionReceipt;
1083
+ } catch (error) {
1084
+ if (error instanceof Error && error.message === "Early NEAR admission changed the authorized request") throw error;
1085
+ earlyAdmissionReceipt = void 0;
1086
+ }
999
1087
  const { joined, admissionReceipt } = await continueNearRegistrationCustody({
1000
1088
  pending,
1001
1089
  signingEngine: base.context.signingEngine,
1002
1090
  relayerUrl: base.relayerUrl,
1003
1091
  credential: base.signedSetup,
1004
1092
  traceContext: base.traceContext,
1005
- factorSecret
1093
+ factorSecret,
1094
+ ...earlyAdmissionReceipt ? { admitted: earlyAdmissionReceipt } : {}
1006
1095
  });
1007
1096
  outcome = "success";
1008
1097
  return {
@@ -1028,16 +1117,12 @@ async function startDeferredNearWalletCustody(base, input) {
1028
1117
  });
1029
1118
  }
1030
1119
  }
1031
- async function continueNearRegistrationCustody(args) {
1032
- const journal = args.pending;
1033
- if (journal.phase === "joined" && journal.completion.kind !== "encrypted_checkpoint") throw new Error("Joined material has no encrypted execution checkpoint");
1034
- const pending = journal.phase === "joined" && journal.completion.kind === "encrypted_checkpoint" ? journal.completion.prepared : journal;
1035
- if (pending.phase === "joined") throw new Error("Invalid NEAR continuation phase");
1036
- const admission = pending.admissionRequest;
1037
- const admissionStartedAt = performance.now();
1038
- const admissionReceipt = pending.phase === "execution_prepared" ? pending.admissionReceipt : await admitDeferredNearRegistration({
1120
+ async function resolveNearRegistrationAdmissionReceipt(args) {
1121
+ if (args.pending.phase === "execution_prepared") return args.pending.admissionReceipt;
1122
+ if (args.admitted) return args.admitted;
1123
+ return await admitDeferredNearRegistration({
1039
1124
  status: "deferred",
1040
- admissionRequest: pending.admissionRequest
1125
+ admissionRequest: args.pending.admissionRequest
1041
1126
  }, {
1042
1127
  routerOrigin: new URL(args.relayerUrl).origin,
1043
1128
  authorization: {
@@ -1047,6 +1132,21 @@ async function continueNearRegistrationCustody(args) {
1047
1132
  fetch: globalThis.fetch,
1048
1133
  traceContext: args.traceContext
1049
1134
  });
1135
+ }
1136
+ async function continueNearRegistrationCustody(args) {
1137
+ const journal = args.pending;
1138
+ if (journal.phase === "joined" && journal.completion.kind !== "encrypted_checkpoint") throw new Error("Joined material has no encrypted execution checkpoint");
1139
+ const pending = journal.phase === "joined" && journal.completion.kind === "encrypted_checkpoint" ? journal.completion.prepared : journal;
1140
+ if (pending.phase === "joined") throw new Error("Invalid NEAR continuation phase");
1141
+ const admission = pending.admissionRequest;
1142
+ const admissionStartedAt = performance.now();
1143
+ const admissionReceipt = await resolveNearRegistrationAdmissionReceipt({
1144
+ pending,
1145
+ relayerUrl: args.relayerUrl,
1146
+ credential: args.credential,
1147
+ traceContext: args.traceContext,
1148
+ ...args.admitted ? { admitted: args.admitted } : {}
1149
+ });
1050
1150
  recordWalletCustodyTiming(pending.registrationCeremonyId, "admission", admissionStartedAt);
1051
1151
  const joined = await args.signingEngine.joinWalletCustodyNearEd25519KeySet({
1052
1152
  ...pending.phase === "planned" ? {
@@ -1217,6 +1317,7 @@ async function resumeNearRegistrationAfterUnlock(args) {
1217
1317
  walletId: pending.walletId,
1218
1318
  commit: {
1219
1319
  context: args.context,
1320
+ registrationTiming: null,
1220
1321
  registrationStartedAt: startedAt,
1221
1322
  clientPrewarm: Promise.resolve(),
1222
1323
  relayerUrl,
@@ -1466,8 +1567,30 @@ async function commitDeferredEd25519Registration(args) {
1466
1567
  thresholdSessionId: joined.metadata.scope.threshold_session_id,
1467
1568
  prfFirstB64u: auth.prfFirstB64u
1468
1569
  });
1570
+ let preparedSessionSeal;
1571
+ if (preparation.kind === "preparing") {
1572
+ const preparationWaitStartedAt = performance.now();
1573
+ const prepared = await preparation.result;
1574
+ emitNearRegistrationTiming({
1575
+ ceremonyId: args.registrationCeremonyId,
1576
+ stage: "session_seal_preparation_wait",
1577
+ startedAt: preparationWaitStartedAt,
1578
+ outcome: prepared.kind === "completed" ? "success" : "failure"
1579
+ });
1580
+ if (prepared.kind === "failed") throw prepared.error;
1581
+ await requireCurrentNearRegistrationSession(args.sessionAuthority);
1582
+ const clientSeal = await args.context.signingEngine.readPreparedSigningSessionHydration({
1583
+ thresholdSessionId: preparation.thresholdSessionId,
1584
+ preparationId: preparation.preparationId
1585
+ });
1586
+ preparedSessionSeal = {
1587
+ preparationId: preparation.preparationId,
1588
+ thresholdSessionId: preparation.thresholdSessionId,
1589
+ ciphertext: clientSeal.ciphertext
1590
+ };
1591
+ }
1469
1592
  const finalizationStartedAt = performance.now();
1470
- const completed = await completeWalletRegistrationNearProvisioning({
1593
+ const nearProvisioningRequest = {
1471
1594
  relayerUrl: args.relayerUrl,
1472
1595
  registrationCeremonyId: args.registrationCeremonyId,
1473
1596
  signedSetup: args.signedSetup,
@@ -1477,8 +1600,23 @@ async function commitDeferredEd25519Registration(args) {
1477
1600
  },
1478
1601
  idempotencyKey: nearProvisioningIdempotencyKey,
1479
1602
  ed25519: { activationReference },
1480
- auth: args.authMaterial,
1481
- walletCustodyCommit: joined.commitPayload
1603
+ walletCustodyCommit: joined.commitPayload,
1604
+ onServerTiming: recordRegistrationServerTimingBuckets.bind(void 0, args.registrationTiming)
1605
+ };
1606
+ let completed;
1607
+ if (preparedSessionSeal) {
1608
+ if (args.authMaterial.kind !== "passkey") throw new Error("Prepared session sealing requires a passkey authority");
1609
+ completed = await completeWalletRegistrationNearProvisioning({
1610
+ ...nearProvisioningRequest,
1611
+ auth: { kind: "passkey" },
1612
+ sessionSeal: {
1613
+ thresholdSessionId: preparedSessionSeal.thresholdSessionId,
1614
+ ciphertext: preparedSessionSeal.ciphertext
1615
+ }
1616
+ });
1617
+ } else completed = await completeWalletRegistrationNearProvisioning({
1618
+ ...nearProvisioningRequest,
1619
+ auth: args.authMaterial
1482
1620
  });
1483
1621
  if (!completed.ok) throw new Error("Deferred NEAR provisioning did not complete");
1484
1622
  const finalized = completed;
@@ -1487,6 +1625,7 @@ async function commitDeferredEd25519Registration(args) {
1487
1625
  const status = finalized.walletCustody?.status ?? "not_reported";
1488
1626
  throw new Error(`Deferred NEAR custody join did not commit (${status})`);
1489
1627
  }
1628
+ if (preparedSessionSeal && !finalized.sessionSeal) throw new Error("Deferred NEAR finalization did not return the prepared session seal");
1490
1629
  emitNearRegistrationTiming({
1491
1630
  ceremonyId: args.registrationCeremonyId,
1492
1631
  stage: "server_finalize",
@@ -1567,18 +1706,6 @@ async function commitDeferredEd25519Registration(args) {
1567
1706
  });
1568
1707
  await requireCurrentNearRegistrationSession(args.sessionAuthority);
1569
1708
  if (args.authMaterial.kind === "passkey" && registrationSession.remainingUses > 0) {
1570
- if (preparation.kind === "preparing") {
1571
- const preparationWaitStartedAt = performance.now();
1572
- const prepared = await preparation.result;
1573
- emitNearRegistrationTiming({
1574
- ceremonyId: args.registrationCeremonyId,
1575
- stage: "session_seal_preparation_wait",
1576
- startedAt: preparationWaitStartedAt,
1577
- outcome: prepared.kind === "completed" ? "success" : "failure"
1578
- });
1579
- if (prepared.kind === "failed") throw prepared.error;
1580
- await requireCurrentNearRegistrationSession(args.sessionAuthority);
1581
- }
1582
1709
  const registrationEd25519Session = registrationEstablishedEd25519Session(registrationSession);
1583
1710
  hydration = hydrateDeferredNearRegistrationSession({
1584
1711
  signingEngine: args.context.signingEngine,
@@ -1589,6 +1716,10 @@ async function commitDeferredEd25519Registration(args) {
1589
1716
  prfFirstB64u: args.authMaterial.prfFirstB64u,
1590
1717
  expiresAtMs: registrationSession.expiresAtMs,
1591
1718
  remainingUses: registrationSession.remainingUses,
1719
+ ...preparedSessionSeal && finalized.sessionSeal ? { preparedServerSeal: {
1720
+ preparationId: preparedSessionSeal.preparationId,
1721
+ ...finalized.sessionSeal
1722
+ } } : {},
1592
1723
  transport: {
1593
1724
  curve: "ed25519",
1594
1725
  authMethod: "passkey",
@@ -1887,7 +2018,11 @@ async function registerEcdsaOrMixedWallet(args) {
1887
2018
  warmup: prepared.registrationWarmup
1888
2019
  });
1889
2020
  const { relayerUrl, setup } = prepared;
1890
- const ecdsaSetup = requireEcdsaRegistrationSetup(setup, args.kind);
2021
+ const ecdsaPrepare = materializeWalletRegistrationSetupEcdsaPrepare(requireEcdsaRegistrationSetup(setup, args.kind).ecdsa);
2022
+ const ecdsaClientCeremony = ecdsaRegistrationClientCeremonyForExecution({
2023
+ passkeyExecution: args.passkeyExecution,
2024
+ ceremonyId: setup.registrationCeremonyId
2025
+ });
1891
2026
  const intentResponse = {
1892
2027
  intent: setup.intent,
1893
2028
  registrationIntentDigestB64u: setup.registrationIntentDigestB64u
@@ -2022,7 +2157,8 @@ async function registerEcdsaOrMixedWallet(args) {
2022
2157
  registrationCeremonyId: setup.registrationCeremonyId,
2023
2158
  signerPlanKind: args.kind,
2024
2159
  signedSetup: setup.signedSetup,
2025
- ecdsaPrepare: materializeWalletRegistrationSetupEcdsaPrepare(ecdsaSetup.ecdsa),
2160
+ ecdsaPrepare,
2161
+ clientCeremony: ecdsaClientCeremony,
2026
2162
  authority: startAuthority,
2027
2163
  materialAuthority,
2028
2164
  idempotencyKey: finalizeIdempotencyKey,
@@ -2223,6 +2359,7 @@ async function registerEcdsaOrMixedWallet(args) {
2223
2359
  walletId: deferredWalletId,
2224
2360
  commit: {
2225
2361
  context,
2362
+ registrationTiming,
2226
2363
  registrationStartedAt: startedAt,
2227
2364
  clientPrewarm,
2228
2365
  relayerUrl,
@@ -62,7 +62,14 @@ const YAO_SERVER_TIMING_BUCKET_BY_METRIC = new Map(Object.entries({
62
62
  ecdsa_b_total: "ecdsaDeriverBTotalMs",
63
63
  ecdsa_sw_parse: "ecdsaSigningWorkerParseMs",
64
64
  ecdsa_sw_activate: "ecdsaSigningWorkerActivateMs",
65
- ecdsa_sw_total: "ecdsaSigningWorkerTotalMs"
65
+ ecdsa_sw_total: "ecdsaSigningWorkerTotalMs",
66
+ near_finalize_authority: "nearFinalizeAuthorityMs",
67
+ near_finalize_fingerprint: "nearFinalizeFingerprintMs",
68
+ near_finalize_side_effect: "nearFinalizeSideEffectMs",
69
+ near_finalize_cleanup: "nearFinalizeCleanupMs",
70
+ near_finalize_session_projection: "nearFinalizeSessionProjectionMs",
71
+ near_finalize_session_seal: "nearFinalizeSessionSealMs",
72
+ near_finalize_total: "nearFinalizeTotalMs"
66
73
  }));
67
74
  /**
68
75
  * Parses a `Server-Timing` header into bucket durations. Diagnostics only: a
@@ -84,6 +91,9 @@ function recordStrictEcdsaServerTimingBuckets(recorder, leg, header) {
84
91
  });
85
92
  recordServerTimingBuckets(recorder, header);
86
93
  }
94
+ function recordRegistrationServerTimingBuckets(recorder, header) {
95
+ recordServerTimingBuckets(recorder, header);
96
+ }
87
97
  function parseYaoServerTimingBuckets(header) {
88
98
  if (!header) return [];
89
99
  const parsed = [];
@@ -304,6 +314,13 @@ function createZeroRegistrationTimingBucketValues() {
304
314
  ecdsaSigningWorkerParseMs: 0,
305
315
  ecdsaSigningWorkerActivateMs: 0,
306
316
  ecdsaSigningWorkerTotalMs: 0,
317
+ nearFinalizeAuthorityMs: 0,
318
+ nearFinalizeFingerprintMs: 0,
319
+ nearFinalizeSideEffectMs: 0,
320
+ nearFinalizeCleanupMs: 0,
321
+ nearFinalizeSessionProjectionMs: 0,
322
+ nearFinalizeSessionSealMs: 0,
323
+ nearFinalizeTotalMs: 0,
307
324
  walletRegisterStartMs: 0,
308
325
  ecdsaClientBootstrapMs: 0,
309
326
  ecdsaRegistrationTotalMs: 0,
@@ -428,6 +445,13 @@ function copyRegistrationTimingBucketValues(buckets) {
428
445
  ecdsaSigningWorkerParseMs: buckets.ecdsaSigningWorkerParseMs,
429
446
  ecdsaSigningWorkerActivateMs: buckets.ecdsaSigningWorkerActivateMs,
430
447
  ecdsaSigningWorkerTotalMs: buckets.ecdsaSigningWorkerTotalMs,
448
+ nearFinalizeAuthorityMs: buckets.nearFinalizeAuthorityMs,
449
+ nearFinalizeFingerprintMs: buckets.nearFinalizeFingerprintMs,
450
+ nearFinalizeSideEffectMs: buckets.nearFinalizeSideEffectMs,
451
+ nearFinalizeCleanupMs: buckets.nearFinalizeCleanupMs,
452
+ nearFinalizeSessionProjectionMs: buckets.nearFinalizeSessionProjectionMs,
453
+ nearFinalizeSessionSealMs: buckets.nearFinalizeSessionSealMs,
454
+ nearFinalizeTotalMs: buckets.nearFinalizeTotalMs,
431
455
  walletRegisterStartMs: buckets.walletRegisterStartMs,
432
456
  ecdsaClientBootstrapMs: buckets.ecdsaClientBootstrapMs,
433
457
  ecdsaRegistrationTotalMs: buckets.ecdsaRegistrationTotalMs,
@@ -769,6 +793,13 @@ function buildRegistrationTimingBuckets(input) {
769
793
  ecdsaSigningWorkerParseMs: buckets.ecdsaSigningWorkerParseMs,
770
794
  ecdsaSigningWorkerActivateMs: buckets.ecdsaSigningWorkerActivateMs,
771
795
  ecdsaSigningWorkerTotalMs: buckets.ecdsaSigningWorkerTotalMs,
796
+ nearFinalizeAuthorityMs: buckets.nearFinalizeAuthorityMs,
797
+ nearFinalizeFingerprintMs: buckets.nearFinalizeFingerprintMs,
798
+ nearFinalizeSideEffectMs: buckets.nearFinalizeSideEffectMs,
799
+ nearFinalizeCleanupMs: buckets.nearFinalizeCleanupMs,
800
+ nearFinalizeSessionProjectionMs: buckets.nearFinalizeSessionProjectionMs,
801
+ nearFinalizeSessionSealMs: buckets.nearFinalizeSessionSealMs,
802
+ nearFinalizeTotalMs: buckets.nearFinalizeTotalMs,
772
803
  walletRegisterStartMs: buckets.walletRegisterStartMs,
773
804
  ecdsaClientBootstrapMs: buckets.ecdsaClientBootstrapMs,
774
805
  ecdsaRegistrationTotalMs: buckets.ecdsaRegistrationTotalMs,
@@ -991,6 +1022,6 @@ function emitRegistrationTimingSpan(input) {
991
1022
  } catch {}
992
1023
  }
993
1024
  //#endregion
994
- export { REGISTRATION_TIMING_LABEL, RegistrationTimingRecorder, WALLET_IFRAME_TRANSPORT_TIMING_LABEL, assertNever, createFailedRegistrationTimingSummary, createSucceededRegistrationTimingSummary, emitNearRegistrationTiming, emitRegistrationTimingSpan, emitRegistrationTimingSummary, parseYaoServerTimingBuckets, recordNearRegistrationSessionTiming, recordStrictEcdsaServerTimingBuckets, registrationTimingSignerSetFromPlan, roundDurationMs, zeroEmailOtpYaoPrewarmDiagnostics };
1025
+ export { REGISTRATION_TIMING_LABEL, RegistrationTimingRecorder, WALLET_IFRAME_TRANSPORT_TIMING_LABEL, assertNever, createFailedRegistrationTimingSummary, createSucceededRegistrationTimingSummary, emitNearRegistrationTiming, emitRegistrationTimingSpan, emitRegistrationTimingSummary, parseYaoServerTimingBuckets, recordNearRegistrationSessionTiming, recordRegistrationServerTimingBuckets, recordStrictEcdsaServerTimingBuckets, registrationTimingSignerSetFromPlan, roundDurationMs, zeroEmailOtpYaoPrewarmDiagnostics };
995
1026
 
996
1027
  //# sourceMappingURL=registrationTiming.js.map
@@ -3376,6 +3376,9 @@ var BrowserSigningSurface = class {
3376
3376
  prepareSigningSessionHydration(input) {
3377
3377
  return this.passkeyMpcSession.prepareSigningSessionHydration(input);
3378
3378
  }
3379
+ readPreparedSigningSessionHydration(input) {
3380
+ return this.passkeyMpcSession.readPreparedSigningSessionHydration(input);
3381
+ }
3379
3382
  discardSigningSessionHydration(input) {
3380
3383
  return this.passkeyMpcSession.discardSigningSessionHydration(input);
3381
3384
  }
@@ -2,6 +2,7 @@ import { walletIframeSurfaceGeometryEqual } from "../surface/geometry.js";
2
2
  import { OverlayStyleClasses, clearDialogGeometry, clearTransactionReviewAppearance, ensureOverlayDialog, pinDialogIframe, releaseDialogIframe, setDialogAuthMenu, setDialogGeometry, setDialogPresentation, setHidden, setTransactionReviewAppearance, setVisible } from "./overlay-styles.js";
3
3
  //#region src/SeamsWeb/walletIframe/client/overlay/overlay-controller.ts
4
4
  const SURFACE_RESIZE_DURATION_MS = 180;
5
+ const REVIEW_HANDOFF_DURATION_MS = 320;
5
6
  function finiteSurfaceRect(rect) {
6
7
  if (!Number.isFinite(rect.top) || !Number.isFinite(rect.left) || !Number.isFinite(rect.width) || !Number.isFinite(rect.height) || rect.width <= 0 || rect.height <= 0) return null;
7
8
  return {
@@ -208,6 +209,11 @@ var OverlayController = class {
208
209
  }
209
210
  applyVisible(mode) {
210
211
  const { dialog, iframe } = this.ensureDialog();
212
+ const iframeSize = {
213
+ widthCssPx: iframe.clientWidth,
214
+ heightCssPx: iframe.clientHeight
215
+ };
216
+ let requestResizeDestination = null;
211
217
  const identityChanged = !sameIdentity(this.mode, mode);
212
218
  const handoffFromReview = !identityChanged && this.mode.kind === "compact_transaction_review" && mode.kind === "compact_request_modal";
213
219
  const returnToReview = !identityChanged && this.mode.kind === "compact_request_modal" && mode.kind === "compact_transaction_review";
@@ -243,8 +249,8 @@ var OverlayController = class {
243
249
  setDialogGeometry(dialog, mode.geometry, authMenu ? this.authMenuVisualScale : 1);
244
250
  this.lastAppliedGeometry = mode.geometry;
245
251
  this.lastAppliedAuthMenuVisualScale = authMenu ? this.authMenuVisualScale : 1;
246
- const requestResizeDestination = requestResizeOrigin ? finiteSurfaceRect(dialog.getBoundingClientRect()) : null;
247
- if (requestResizeOrigin && requestResizeDestination) this.startSurfaceResize(requestResizeOrigin, requestResizeDestination);
252
+ requestResizeDestination = requestResizeOrigin ? finiteSurfaceRect(dialog.getBoundingClientRect()) : null;
253
+ if (requestResizeOrigin && requestResizeDestination) this.startSurfaceResize(requestResizeOrigin, requestResizeDestination, handoffFromReview || returnToReview ? REVIEW_HANDOFF_DURATION_MS : SURFACE_RESIZE_DURATION_MS);
248
254
  if (requestResizeOrigin) releaseDialogIframe(dialog);
249
255
  }
250
256
  const reviewing = mode.kind === "compact_transaction_review";
@@ -253,6 +259,10 @@ var OverlayController = class {
253
259
  if (handoffFromReview) this.startReviewHandoff("wallet");
254
260
  if (returnToReview) this.startReviewHandoff("review");
255
261
  const handingOff = this.reviewHandoff.kind === "animating";
262
+ if (handingOff && requestResizeDestination) pinDialogIframe(dialog, reviewing ? iframeSize : {
263
+ widthCssPx: requestResizeDestination.width,
264
+ heightCssPx: requestResizeDestination.height
265
+ });
256
266
  iframe.inert = reviewing || handingOff;
257
267
  iframe.classList.toggle("seams-review-wallet-inactive", reviewing);
258
268
  iframe.setAttribute("aria-hidden", String(reviewing || handingOff));
@@ -282,22 +292,63 @@ var OverlayController = class {
282
292
  this.cancelReviewHandoff();
283
293
  if (!this.iframe || window.matchMedia("(prefers-reduced-motion: reduce)").matches) return;
284
294
  const options = {
285
- duration: SURFACE_RESIZE_DURATION_MS,
286
- easing: "linear",
295
+ duration: REVIEW_HANDOFF_DURATION_MS,
296
+ easing: "cubic-bezier(0.22, 1, 0.36, 1)",
287
297
  fill: "both"
288
298
  };
289
299
  const review = this.getTransactionReviewSlot().firstElementChild;
290
300
  if (!review) return;
291
301
  const outgoingElement = destination === "wallet" ? review : this.iframe;
292
302
  const incomingElement = destination === "wallet" ? this.iframe : review;
293
- const outgoing = outgoingElement.animate([{ opacity: 1 }, { opacity: 0 }], options);
294
- const incoming = incomingElement.animate([{ opacity: 0 }, { opacity: 1 }], options);
303
+ const direction = destination === "wallet" ? 1 : -1;
304
+ const outgoing = outgoingElement.animate([
305
+ {
306
+ opacity: 1,
307
+ transform: "translateY(0)"
308
+ },
309
+ {
310
+ opacity: 0,
311
+ transform: `translateY(${-8 * direction}px)`,
312
+ offset: .55
313
+ },
314
+ {
315
+ opacity: 0,
316
+ transform: `translateY(${-8 * direction}px)`
317
+ }
318
+ ], options);
319
+ const incoming = incomingElement.animate([{
320
+ opacity: 0,
321
+ transform: `translateY(${12 * direction}px)`
322
+ }, {
323
+ opacity: 1,
324
+ transform: "translateY(0)"
325
+ }], options);
326
+ const sections = [];
327
+ let order = 0;
328
+ for (const section of review.children) {
329
+ const entering = destination === "review";
330
+ const delay = Math.min(order, 3) * 25;
331
+ sections.push(section.animate([{
332
+ opacity: entering ? 0 : 1,
333
+ transform: entering ? "translateY(8px)" : "translateY(0)"
334
+ }, {
335
+ opacity: entering ? 1 : 0,
336
+ transform: entering ? "translateY(0)" : "translateY(-6px)"
337
+ }], {
338
+ duration: entering ? 220 : 140,
339
+ delay,
340
+ easing: "ease-out",
341
+ fill: "both"
342
+ }));
343
+ order += 1;
344
+ }
295
345
  this.reviewHandoff = {
296
346
  kind: "animating",
297
347
  destination,
298
348
  outgoing,
299
349
  incoming,
300
- timer: setTimeout(this.finishReviewHandoff.bind(this), SURFACE_RESIZE_DURATION_MS),
350
+ sections,
351
+ timer: setTimeout(this.finishReviewHandoff.bind(this), REVIEW_HANDOFF_DURATION_MS),
301
352
  onReady: null
302
353
  };
303
354
  incoming.addEventListener("finish", this.handleReviewHandoffFinished, { once: true });
@@ -327,22 +378,24 @@ var OverlayController = class {
327
378
  clearTimeout(this.reviewHandoff.timer);
328
379
  this.reviewHandoff.outgoing.cancel();
329
380
  this.reviewHandoff.incoming.cancel();
381
+ for (const animation of this.reviewHandoff.sections) animation.cancel();
382
+ if (this.dialog) releaseDialogIframe(this.dialog);
330
383
  this.reviewHandoff = { kind: "idle" };
331
384
  }
332
385
  scheduleMeasuredReveal() {
333
386
  this.cancelPendingReveal();
334
387
  this.pendingRevealFrame = window.requestAnimationFrame(this.revealMeasuredSurface);
335
388
  }
336
- startSurfaceResize(origin, destination) {
389
+ startSurfaceResize(origin, destination, duration) {
337
390
  const dialog = this.dialog;
338
391
  if (!dialog || window.matchMedia("(prefers-reduced-motion: reduce)").matches) return;
339
392
  this.cancelSurfaceResize();
340
393
  const animation = dialog.animate(surfaceResizeKeyframes(origin, destination), {
341
- duration: SURFACE_RESIZE_DURATION_MS,
394
+ duration,
342
395
  easing: "cubic-bezier(0.2, 0.7, 0.2, 1)"
343
396
  });
344
397
  this.surfaceResizeAnimation = animation;
345
- this.surfaceResizeTimer = setTimeout(this.cancelSurfaceResize.bind(this), SURFACE_RESIZE_DURATION_MS);
398
+ this.surfaceResizeTimer = setTimeout(this.cancelSurfaceResize.bind(this), duration);
346
399
  animation.addEventListener("finish", this.handleSurfaceResizeFinished, { once: true });
347
400
  }
348
401
  cancelPendingReveal() {