@lumiapassport/ui-kit 1.8.1 → 1.9.0

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/README.md CHANGED
@@ -340,6 +340,62 @@ function DirectTransactionExample() {
340
340
  - ✅ Use `useSendTransaction()` hook for React components (automatic session management)
341
341
  - ✅ Use `sendUserOperation()` function for custom logic, utility functions, or non-React code
342
342
 
343
+ ### deployAccount - Deploy Smart Account (Optional)
344
+
345
+ Deploy the smart account contract immediately after registration. This is **optional** - accounts are automatically deployed on first transaction.
346
+
347
+ **Smart behavior:** Automatically checks if account is already deployed and skips transaction to save gas.
348
+
349
+ ```tsx
350
+ import { deployAccount, useLumiaPassportSession } from '@lumiapassport/ui-kit';
351
+
352
+ function DeployAccountExample() {
353
+ const { session } = useLumiaPassportSession();
354
+
355
+ const handleDeploy = async () => {
356
+ if (!session) return;
357
+
358
+ try {
359
+ // Deploy account with minimal gas cost (skips if already deployed)
360
+ const userOpHash = await deployAccount(session, 'economy');
361
+
362
+ if (userOpHash) {
363
+ console.log('Account deployed:', userOpHash);
364
+ } else {
365
+ console.log('Account already deployed, skipped');
366
+ }
367
+ } catch (error) {
368
+ console.error('Deployment failed:', error);
369
+ }
370
+ };
371
+
372
+ return <button onClick={handleDeploy}>Deploy Account</button>;
373
+ }
374
+ ```
375
+
376
+ **Return values:**
377
+ - Returns `userOpHash` (string) - if deployment was needed and executed
378
+ - Returns `null` - if account already deployed (saves gas)
379
+
380
+ **Advanced usage:**
381
+ ```tsx
382
+ // Force deployment even if already deployed (not recommended)
383
+ const hash = await deployAccount(session, 'economy', { force: true });
384
+ ```
385
+
386
+ **Why use this?**
387
+ - ✅ **Pre-deploy** account before first real transaction
388
+ - ✅ **No user consent** required (safe minimal operation)
389
+ - ✅ **Cleaner UX** - separate deployment from first payment
390
+ - ✅ **Smart gas savings** - auto-skips if already deployed
391
+ - ⚠️ **Optional** - accounts auto-deploy on first transaction anyway
392
+
393
+ **How it works:**
394
+ 1. Checks if smart account contract exists on-chain
395
+ 2. If exists: returns `null` immediately (no gas cost)
396
+ 3. If not exists: sends minimal UserOperation (`to=0x0, value=0, data=0x`)
397
+ 4. Factory deploys contract without user confirmation
398
+
343
399
  ### signTypedData - Sign EIP712 Structured Messages
344
400
 
345
401
  Sign structured data according to [EIP-712](https://eips.ethereum.org/EIPS/eip-712) standard. This is commonly used for off-chain signatures in dApps (e.g., NFT marketplace orders, gasless transactions, permit signatures).
@@ -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.8.1</title>
18
+ <title>Lumia Passport Secure Wallet - iframe version 1.9.0</title>
19
19
 
20
20
  <!-- Styles will be injected by build process -->
21
21
  <style>
@@ -2618,6 +2618,34 @@ var SigningManager = class extends TokenRefreshApiClient {
2618
2618
  throw new Error("Failed to initialize signing WASM module");
2619
2619
  }
2620
2620
  }
2621
+ /**
2622
+ * Check if transaction is a minimal safe operation (account deployment)
2623
+ *
2624
+ * Minimal operations are safe to auto-approve without user consent:
2625
+ * - to: 0x0000000000000000000000000000000000000000 (burn address)
2626
+ * - value: 0 (no funds transfer)
2627
+ * - data: 0x (no contract call)
2628
+ *
2629
+ * This is used for smart account deployment without spending any funds.
2630
+ */
2631
+ isMinimalSafeOperation(transaction) {
2632
+ const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
2633
+ const ZERO_VALUE = "0";
2634
+ const EMPTY_DATA = "0x";
2635
+ const to = transaction.to?.toLowerCase();
2636
+ const value = transaction.value?.toString() || "0";
2637
+ const data = transaction.data?.toLowerCase() || "0x";
2638
+ const isMinimal = to === ZERO_ADDRESS.toLowerCase() && (value === ZERO_VALUE || value === "0x0") && (data === EMPTY_DATA || data === "0x0");
2639
+ if (isMinimal) {
2640
+ console.log("[iframe][Sign] Detected minimal safe operation:", {
2641
+ to,
2642
+ value,
2643
+ data,
2644
+ reason: "Account deployment - no funds at risk"
2645
+ });
2646
+ }
2647
+ return isMinimal;
2648
+ }
2621
2649
  /**
2622
2650
  * Fetch project metadata from public API (with caching)
2623
2651
  */
@@ -2629,9 +2657,7 @@ var SigningManager = class extends TokenRefreshApiClient {
2629
2657
  return cached.data;
2630
2658
  }
2631
2659
  try {
2632
- const response = await fetch(`${this.METADATA_API_URL}/${projectId}/metadata`, {
2633
- credentials: "include"
2634
- });
2660
+ const response = await fetch(`${this.METADATA_API_URL}/${projectId}/metadata`);
2635
2661
  if (!response.ok) {
2636
2662
  console.warn(`[iframe][Sign] Failed to fetch project metadata: ${response.status}`);
2637
2663
  return null;
@@ -2666,8 +2692,9 @@ var SigningManager = class extends TokenRefreshApiClient {
2666
2692
  website: origin,
2667
2693
  domains: [origin]
2668
2694
  };
2695
+ const isMinimalOperation = this.isMinimalSafeOperation(transaction);
2669
2696
  const isTrusted = this.trustedApps.isTrusted(userId, projectId, origin);
2670
- if (!isTrusted) {
2697
+ if (!isTrusted && !isMinimalOperation) {
2671
2698
  const risk = await this.assessRisk(transaction);
2672
2699
  const confirmResult = await this.showConfirmationDialog(
2673
2700
  userId,
@@ -2683,6 +2710,8 @@ var SigningManager = class extends TokenRefreshApiClient {
2683
2710
  if (confirmResult.trustApp) {
2684
2711
  this.trustedApps.addTrustedApp(userId, projectId, origin);
2685
2712
  }
2713
+ } else if (isMinimalOperation) {
2714
+ console.log("[iframe][Sign] Auto-approving minimal safe operation (account deployment)");
2686
2715
  }
2687
2716
  const digest32 = transaction.digest32 || this.computeTransactionHash(transaction);
2688
2717
  const signature = await this.performMPCSigning(userId, keyshareData, digest32, projectId, accessToken);
@@ -3189,9 +3218,7 @@ var AuthorizationManager = class {
3189
3218
  return cached.data;
3190
3219
  }
3191
3220
  try {
3192
- const response = await fetch(`${this.METADATA_API_URL}/${projectId}/metadata`, {
3193
- credentials: "include"
3194
- });
3221
+ const response = await fetch(`${this.METADATA_API_URL}/${projectId}/metadata`);
3195
3222
  if (!response.ok) {
3196
3223
  console.warn(`[iframe][Auth] Failed to fetch project metadata: ${response.status}`);
3197
3224
  return null;
@@ -3928,7 +3955,7 @@ var BackupManager = class {
3928
3955
  };
3929
3956
 
3930
3957
  // src/iframe/main.ts
3931
- var IFRAME_VERSION = "1.8.1";
3958
+ var IFRAME_VERSION = "1.9.0";
3932
3959
  var IframeWallet = class {
3933
3960
  constructor() {
3934
3961
  console.log("=".repeat(60));