@lumiapassport/ui-kit 1.14.1 → 1.14.2

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.
@@ -15,7 +15,7 @@
15
15
  <meta http-equiv="X-Content-Type-Options" content="nosniff" />
16
16
  <meta http-equiv="Referrer-Policy" content="strict-origin-when-cross-origin" />
17
17
 
18
- <title>Lumia Passport Secure Wallet - iframe version 1.14.1</title>
18
+ <title>Lumia Passport Secure Wallet - iframe version 1.14.2</title>
19
19
 
20
20
  <!-- Styles will be injected by build process -->
21
21
  <style>
@@ -64,8 +64,8 @@
64
64
  /* font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Helvetica', 'Arial', sans-serif; */
65
65
  font-family: -apple-system, BlinkMacSystemFont, 'Inter', system-ui, sans-serif;
66
66
 
67
- background: var(--iframe-bg);
68
- backdrop-filter: blur(10px);
67
+ background: #000000;
68
+ /* backdrop-filter: blur(10px); */
69
69
 
70
70
  color: var(--iframe-text);
71
71
 
@@ -84,21 +84,6 @@
84
84
  justify-content: center;
85
85
  }
86
86
 
87
- /* OK */
88
- @keyframes details-open {
89
- from {
90
- max-height: 0;
91
- }
92
- to {
93
- max-height: 148px; /* Adjust as needed based on content size */
94
- }
95
- }
96
-
97
- /* OK */
98
- details[open] > div[data-details-content] {
99
- animation: details-open 300ms ease;
100
- }
101
-
102
87
  /* Ready Indicator START */
103
88
  /* OK */
104
89
  .ready-indicator {
@@ -107,6 +92,7 @@
107
92
  padding: var(--iframe-pd);
108
93
  border-radius: var(--iframe-bdrs);
109
94
  max-width: 320px;
95
+ width: calc(100% - 40px);
110
96
  display: flex;
111
97
  flex-direction: column;
112
98
  align-items: center;
@@ -1267,7 +1267,7 @@ var TemplateEngine = class {
1267
1267
  };
1268
1268
 
1269
1269
  // src/iframe/templates/html/authorization.html
1270
- var authorization_default = '<div class="modal-overlay">\n <div class="modal-content" style="display: flex; flex-direction: column; gap: var(--iframe-gap); align-items: center">\n <div style="display: flex; align-items: center; gap: var(--iframe-gap); justify-content: center">\n <img\n src="./lumia-logo.svg"\n alt="Lumia Passport"\n style="width: 40px; height: 40px; border-radius: 20px; object-fit: cover"\n />\n\n <span\n style="display: block; font-size: var(--iframe-h1-fz); font-weight: var(--iframe-heading-fw); line-height: 150%"\n >Authorize</span\n >\n </div>\n\n <div style="display: flex; align-items: center; gap: var(--iframe-gap); justify-content: center">\n {{#if displayLogo}}\n <img\n src="{{displayLogo}}"\n alt="{{displayName}}"\n style="width: 32px; height: 32px; border-radius: 16px; object-fit: cover"\n />\n {{else}}\n <span style="font-size: 14px; font-weight: 600">{{displayName}}</span>\n {{/if}}\n\n <span\n style="display: block; font-size: var(--iframe-h2-fz); font-weight: var(--iframe-heading-fw); line-height: 150%"\n >{{displayName}}</span\n >\n </div>\n\n <div class="domain-info {{domainStatusClass}}" style="font-size: 12px; text-align: center">\n <span style="font-family: monospace">{{domainStatusIcon}} {{domainStatusText}} {{origin}}</span>\n </div>\n\n <!-- Permissions box -->\n <details style="display: flex; flex-direction: column; width: 100%">\n <summary\n style="\n cursor: pointer;\n text-align: center;\n list-style: none;\n padding: 0 var(--iframe-pd);\n user-select: none;\n font-size: 12px;\n line-height: 20px;\n "\n >\n Show Permissions\n </summary>\n <div\n data-details-content="true"\n style="\n width: 100%;\n padding: var(--iframe-gap);\n border-radius: var(--iframe-el-bdrs);\n background: var(--iframe-info);\n font-size: 10px;\n "\n >\n <div style="margin-bottom: var(--iframe-gap)">\n <strong>{{displayName}}</strong> by <span class="project-owner">{{displayName}}</span> wants to access your\n <strong>Lumia Passport</strong> account\n </div>\n\n <div style="margin-bottom: var(--iframe-gap)">\n <strong style="margin-bottom: var(--iframe-gap)">Personal user data</strong>\n <ul style="list-style: none">\n <li style="padding-left: var(--iframe-pd)">Wallet address (read-only)</li>\n <li style="padding-left: var(--iframe-pd)">Public transaction history (read-only)</li>\n </ul>\n </div>\n\n <div style="width: 100%">\n <strong style="margin-bottom: var(--iframe-gap)">Permissions</strong>\n <ul style="list-style: none">\n <li style="padding-left: var(--iframe-pd)">Request transaction signatures</li>\n <li style="padding-left: var(--iframe-pd)">Initiate blockchain operations</li>\n </ul>\n </div>\n </div>\n </details>\n\n {{#if showSecurityWarning}}\n <div class="security-warning">\n <strong>\u26A0\uFE0F Warning:</strong> This domain is not verified for {{displayName}}\n <div>Expected: {{expectedDomains}}</div>\n <div>Actual: {{origin}}</div>\n </div>\n {{else}}\n <span style="font-size: 10px; color: var(--iframe-text-secondary)"\n >By continuing you allow the app to use these permissions.</span\n >\n {{/if}}\n\n <!-- Action buttons -->\n <div style="display: flex; gap: var(--iframe-gap); width: 100%; align-items: center">\n <button class="cancel-btn">Cancel</button>\n <button class="authorize-btn" {{authorizeButtonState}}>Continue</button>\n </div>\n\n <!-- Footer notice -->\n <div\n style="\n color: var(--iframe-text-secondary);\n font-size: 10px;\n display: flex;\n flex-direction: column;\n gap: 4px;\n align-items: center;\n text-align: center;\n "\n >\n <span>Authorizing will redirect to <strong>{{origin}}</strong></span>\n <span>You can revoke access at any time in your Lumia Passport settings.</span>\n </div>\n </div>\n</div>\n';
1270
+ var authorization_default = '<div\n style="\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 10000;\n background: #000000;\n "\n>\n <div\n style="\n display: flex;\n flex-direction: column;\n gap: var(--iframe-gap);\n align-items: center;\n background: var(--iframe-modal-bg);\n border-radius: 20px;\n padding: 20px;\n max-width: 320px;\n width: calc(100% - 40px);\n max-height: 90vh;\n overflow-y: auto;\n "\n >\n <div style="display: flex; align-items: center; gap: var(--iframe-gap); justify-content: center">\n {{#if userAvatar}}\n <img\n src="{{userAvatar}}"\n alt="{{userName}}"\n style="width: 48px; height: 48px; border-radius: 24px; object-fit: cover"\n />\n {{else}}\n <span\n style="\n display: flex;\n align-items: center;\n justify-content: center;\n width: 48px;\n height: 48px;\n border-radius: 24px;\n background-color: var(--iframe-button-bg);\n color: var(--iframe-button-text);\n font-size: 14px;\n font-weight: 600;\n "\n >U</span\n >\n {{/if}}\n\n <!-- ------------------------------------------------------------ -->\n <svg\n xmlns="http://www.w3.org/2000/svg"\n width="24"\n height="24"\n viewBox="0 0 24 24"\n fill="none"\n stroke="var(--iframe-text-secondary)"\n stroke-width="2"\n stroke-linecap="round"\n stroke-linejoin="round"\n >\n <path d="M5 12h14" />\n <path d="m12 5 7 7-7 7" />\n </svg>\n <!-- ------------------------------------------------------------ -->\n\n {{#if displayLogo}}\n <img\n src="{{displayLogo}}"\n alt="{{displayName}}"\n style="width: 48px; height: 48px; border-radius: 24px; object-fit: cover"\n />\n {{else}}\n <span\n style="\n display: flex;\n align-items: center;\n justify-content: center;\n width: 48px;\n height: 48px;\n border-radius: 24px;\n background-color: var(--iframe-button-bg);\n color: var(--iframe-button-text);\n font-size: 14px;\n font-weight: 600;\n "\n >A</span\n >\n {{/if}}\n </div>\n\n <div style="display: flex; align-items: center; gap: var(--iframe-gap); justify-content: center">\n <span\n style="\n width: fit-content;\n font-size: var(--iframe-h2-fz);\n font-weight: var(--iframe-heading-fw);\n line-height: 150%;\n text-align: center;\n "\n >{{displayName}}</span\n >\n </div>\n\n <div class="domain-info {{domainStatusClass}}">\n <span style="display: block; width: 100%; font-size: 12px; text-align: center; font-family: monospace"\n >{{domainStatusIcon}} {{origin}}</span\n >\n </div>\n\n <!-- Permissions box -->\n <div\n id="data-auth-permissions-block"\n aria-expanded="false"\n style="display: flex; flex-direction: column; width: 100%"\n >\n <div\n id="data-auth-permissions-toggler"\n style="\n cursor: pointer;\n text-align: center;\n list-style: none;\n padding: 0 var(--iframe-pd);\n user-select: none;\n font-size: 12px;\n line-height: 20px;\n "\n >\n Show Permissions \u25BC\n </div>\n\n <div\n id="data-auth-permissions-content"\n style="width: 100%; height: var(--iframe-permissions-h, 0); overflow: hidden; transition: height 300ms ease"\n >\n <div\n style="\n width: 100%;\n padding: var(--iframe-gap);\n border-radius: var(--iframe-el-bdrs);\n background: var(--iframe-info);\n font-size: 10px;\n "\n >\n <div style="margin-bottom: var(--iframe-gap)">\n <strong>{{displayName}}</strong> by <span class="project-owner">{{displayName}}</span> wants to access your\n <strong>Lumia Passport</strong> account\n </div>\n\n <div style="margin-bottom: var(--iframe-gap)">\n <strong style="margin-bottom: var(--iframe-gap)">Personal user data</strong>\n <ul style="list-style: none">\n <li style="padding-left: var(--iframe-pd)">Wallet address (read-only)</li>\n <li style="padding-left: var(--iframe-pd)">Public transaction history (read-only)</li>\n </ul>\n </div>\n\n <div style="width: 100%">\n <strong style="margin-bottom: var(--iframe-gap)">Permissions</strong>\n <ul style="list-style: none">\n <li style="padding-left: var(--iframe-pd)">Request transaction signatures</li>\n <li style="padding-left: var(--iframe-pd)">Initiate blockchain operations</li>\n </ul>\n </div>\n </div>\n </div>\n </div>\n\n {{#if showSecurityWarning}}\n <div class="security-warning">\n <strong>\u26A0\uFE0F Warning:</strong> This domain is not verified for {{displayName}}\n <div>Expected: {{expectedDomains}}</div>\n <div>Actual: {{origin}}</div>\n </div>\n {{else}}\n <span style="display: block; text-align: center; font-size: 10px; color: var(--iframe-text-secondary)"\n >By continuing you allow the app to use these permissions, you can revoke access at any time.</span\n >\n {{/if}}\n\n <!-- Action buttons -->\n <div style="display: flex; gap: var(--iframe-gap); width: 100%; align-items: center">\n <button class="cancel-btn">Cancel</button>\n <button class="authorize-btn" {{authorizeButtonState}}>Continue</button>\n </div>\n </div>\n</div>\n';
1271
1271
 
1272
1272
  // src/iframe/templates/html/ready-indicator.html
1273
1273
  var ready_indicator_default = '<div class="ready-indicator">\n <div class="status-icon">\u2713</div>\n <h2>Secure Wallet Ready</h2>\n <p>Lumia Passport is ready for secure operations</p>\n <div class="info">\n <div class="info-row">\n <strong>Origin:</strong>\n <span>{{origin}}</span>\n </div>\n <div class="info-row">\n <strong>Status:</strong>\n <span class="status-active">Active</span>\n </div>\n <div class="info-row">\n <strong>Version:</strong>\n <span>{{iframeVersion}}</span>\n </div>\n <div class="info-row">\n <strong>Documentation:</strong>\n <a\n href="https://docs.lumiapassport.com/"\n target="_blank"\n rel="noopener noreferrer"\n style="color: #667eea; text-decoration: none"\n >docs.lumiapassport.com</a\n >\n </div>\n </div>\n</div>\n';
@@ -3774,11 +3774,17 @@ var SigningManager = class extends TokenRefreshApiClient {
3774
3774
  }
3775
3775
  let clientState = clientSignStartResult[0];
3776
3776
  const clientMsg1 = clientSignStartResult[1];
3777
- const serverStartResponse = await this.apiCall("POST", `/api/tss/${userId}/sign/start`, {
3778
- sessionId,
3779
- digest32,
3780
- chainPath: CHAIN_PATH
3781
- }, projectId, accessToken);
3777
+ const serverStartResponse = await this.apiCall(
3778
+ "POST",
3779
+ `/api/tss/${userId}/sign/start`,
3780
+ {
3781
+ sessionId,
3782
+ digest32,
3783
+ chainPath: CHAIN_PATH
3784
+ },
3785
+ projectId,
3786
+ accessToken
3787
+ );
3782
3788
  const serverMsg1 = serverStartResponse.msg1;
3783
3789
  if (!serverMsg1?.kind || !serverMsg1.data_b64) {
3784
3790
  throw new Error("Invalid server msg1 format");
@@ -3789,10 +3795,16 @@ var SigningManager = class extends TokenRefreshApiClient {
3789
3795
  );
3790
3796
  clientState = clientR2Result[0];
3791
3797
  const clientMsg2 = clientR2Result[1];
3792
- const serverR2Response = await this.apiCall("POST", `/api/tss/${userId}/sign/round`, {
3793
- sessionId,
3794
- clientMsg: clientMsg1
3795
- }, projectId, accessToken);
3798
+ const serverR2Response = await this.apiCall(
3799
+ "POST",
3800
+ `/api/tss/${userId}/sign/round`,
3801
+ {
3802
+ sessionId,
3803
+ clientMsg: clientMsg1
3804
+ },
3805
+ projectId,
3806
+ accessToken
3807
+ );
3796
3808
  const serverMsg2 = this.extractServerMessage(serverR2Response);
3797
3809
  const clientR3Result = sign_handle(
3798
3810
  JSON.stringify({ bytes_b64: clientState.bytes_b64 }),
@@ -3800,10 +3812,16 @@ var SigningManager = class extends TokenRefreshApiClient {
3800
3812
  );
3801
3813
  clientState = clientR3Result[0];
3802
3814
  const clientMsg3 = clientR3Result[1];
3803
- const serverR3Response = await this.apiCall("POST", `/api/tss/${userId}/sign/round`, {
3804
- sessionId,
3805
- clientMsg: clientMsg2
3806
- }, projectId, accessToken);
3815
+ const serverR3Response = await this.apiCall(
3816
+ "POST",
3817
+ `/api/tss/${userId}/sign/round`,
3818
+ {
3819
+ sessionId,
3820
+ clientMsg: clientMsg2
3821
+ },
3822
+ projectId,
3823
+ accessToken
3824
+ );
3807
3825
  const serverMsg3 = this.extractServerMessage(serverR3Response);
3808
3826
  const clientFinalResult = sign_handle(
3809
3827
  JSON.stringify({ bytes_b64: clientState.bytes_b64 }),
@@ -3813,10 +3831,16 @@ var SigningManager = class extends TokenRefreshApiClient {
3813
3831
  throw new Error("Invalid final sign_handle result");
3814
3832
  }
3815
3833
  const clientSignature = clientFinalResult[2];
3816
- await this.apiCall("POST", `/api/tss/${userId}/sign/round`, {
3817
- sessionId,
3818
- clientMsg: clientMsg3
3819
- }, projectId, accessToken);
3834
+ await this.apiCall(
3835
+ "POST",
3836
+ `/api/tss/${userId}/sign/round`,
3837
+ {
3838
+ sessionId,
3839
+ clientMsg: clientMsg3
3840
+ },
3841
+ projectId,
3842
+ accessToken
3843
+ );
3820
3844
  const signature = this.formatSignature(clientSignature);
3821
3845
  return signature;
3822
3846
  }
@@ -3827,7 +3851,16 @@ var SigningManager = class extends TokenRefreshApiClient {
3827
3851
  this.showIframe();
3828
3852
  const metadata = await this.fetchProjectMetadata(projectId);
3829
3853
  return new Promise((resolve) => {
3830
- const modal = this.createConfirmationModal(userId, projectId, project, origin, transaction, risk, metadata, userProfile);
3854
+ const modal = this.createConfirmationModal(
3855
+ userId,
3856
+ projectId,
3857
+ project,
3858
+ origin,
3859
+ transaction,
3860
+ risk,
3861
+ metadata,
3862
+ userProfile
3863
+ );
3831
3864
  const confirmBtn = modal.querySelector(".confirm-btn");
3832
3865
  const cancelBtn = modal.querySelector(".cancel-btn");
3833
3866
  const trustCheckbox = modal.querySelector(".trust-app-checkbox");
@@ -4062,7 +4095,12 @@ var SigningManager = class extends TokenRefreshApiClient {
4062
4095
  * Sign EIP712 typed data with user confirmation
4063
4096
  */
4064
4097
  async signTypedData(userId, projectId, origin, typedData, digest32, accessToken, userProfile) {
4065
- console.log("[iframe][Sign] EIP712 signing request:", { userId, projectId, origin, primaryType: typedData.primaryType });
4098
+ console.log("[iframe][Sign] EIP712 signing request:", {
4099
+ userId,
4100
+ projectId,
4101
+ origin,
4102
+ primaryType: typedData.primaryType
4103
+ });
4066
4104
  await this.initialize();
4067
4105
  const projectInfo = {
4068
4106
  id: projectId,
@@ -4103,7 +4141,15 @@ var SigningManager = class extends TokenRefreshApiClient {
4103
4141
  this.showIframe();
4104
4142
  const metadata = await this.fetchProjectMetadata(projectId);
4105
4143
  return new Promise((resolve) => {
4106
- const modal = this.createEIP712ConfirmationModal(userId, projectId, project, origin, typedData, metadata, userProfile);
4144
+ const modal = this.createEIP712ConfirmationModal(
4145
+ userId,
4146
+ projectId,
4147
+ project,
4148
+ origin,
4149
+ typedData,
4150
+ metadata,
4151
+ userProfile
4152
+ );
4107
4153
  const confirmBtn = modal.querySelector(".confirm-btn");
4108
4154
  const cancelBtn = modal.querySelector(".cancel-btn");
4109
4155
  const trustCheckbox = modal.querySelector(".trust-app-checkbox");
@@ -4144,18 +4190,22 @@ var SigningManager = class extends TokenRefreshApiClient {
4144
4190
  }
4145
4191
  return String(value);
4146
4192
  };
4147
- const messageFields = Object.entries(typedData.message).map(([key, value]) => `
4193
+ const messageFields = Object.entries(typedData.message).map(
4194
+ ([key, value]) => `
4148
4195
  <div class="eip712-field">
4149
4196
  <div class="field-name">${key}:</div>
4150
4197
  <div class="field-value">${formatFieldValue(value)}</div>
4151
4198
  </div>
4152
- `).join("");
4153
- const domainFields = Object.entries(typedData.domain).filter(([_, value]) => value !== void 0).map(([key, value]) => `
4199
+ `
4200
+ ).join("");
4201
+ const domainFields = Object.entries(typedData.domain).filter(([_, value]) => value !== void 0).map(
4202
+ ([key, value]) => `
4154
4203
  <div class="eip712-field">
4155
4204
  <div class="field-name">${key}:</div>
4156
4205
  <div class="field-value">${formatFieldValue(value)}</div>
4157
4206
  </div>
4158
- `).join("");
4207
+ `
4208
+ ).join("");
4159
4209
  modal.innerHTML = `
4160
4210
  <div class="modal-overlay">
4161
4211
  <div class="modal-content eip712-modal">
@@ -4236,7 +4286,7 @@ var SigningManager = class extends TokenRefreshApiClient {
4236
4286
  };
4237
4287
 
4238
4288
  // src/iframe/main.ts
4239
- var IFRAME_VERSION = "1.14.1";
4289
+ var IFRAME_VERSION = "1.14.2";
4240
4290
  var IframeWallet = class {
4241
4291
  constructor() {
4242
4292
  console.log("=".repeat(60));
@@ -4888,6 +4938,22 @@ var IframeWallet = class {
4888
4938
  this.displayReadyIndicator();
4889
4939
  }
4890
4940
  };
4941
+ function toggleAuthPermissions(e) {
4942
+ const isToggler = e.target.id === "data-auth-permissions-toggler";
4943
+ if (!isToggler) return;
4944
+ const details = document.getElementById("data-auth-permissions-block");
4945
+ const isOpen = details.hasAttribute("aria-expanded") && details.getAttribute("aria-expanded") === "true";
4946
+ const toggler = details.querySelector("#data-auth-permissions-toggler");
4947
+ if (isOpen) {
4948
+ details.setAttribute("aria-expanded", "false");
4949
+ details.style.setProperty("--iframe-permissions-h", "0px");
4950
+ toggler.innerHTML = "Show Permissions \u25BC";
4951
+ } else {
4952
+ details.setAttribute("aria-expanded", "true");
4953
+ details.style.setProperty("--iframe-permissions-h", "148px");
4954
+ toggler.innerHTML = "Hide Permissions \u25B2";
4955
+ }
4956
+ }
4891
4957
  function initWallet() {
4892
4958
  const wallet = new IframeWallet();
4893
4959
  wallet.initialize().catch((error) => {
@@ -4903,6 +4969,7 @@ function initWallet() {
4903
4969
  `;
4904
4970
  }
4905
4971
  });
4972
+ document.addEventListener("click", toggleAuthPermissions);
4906
4973
  }
4907
4974
  if (document.readyState === "loading") {
4908
4975
  document.addEventListener("DOMContentLoaded", initWallet);