CroVault Logo
CroVault

CroVault Workflow Overview

This page describes the major steps and states in the CroVault DApp workflow, from first visiting the Vault page through connecting a wallet, deriving a key, creating a vault, unlocking the data, saving items, and handling idle timeouts.

1. Page Initialization

User visits the vault page:
The page loads vault.js and waits for DOMContentLoaded. Then:

  • Web3Modal is initialized.
  • If web3Modal.cachedProvider is found, the code attempts an auto-connect to the wallet.
  • A fallback read-only JsonRpcProvider is created to fetch the creation/upsert fees from the CostManager contract.
  • The DOM is updated to display these fees for the user’s reference.

If a wallet is not connected, a “Connect Wallet” button appears so the user can proceed.

2. Connect or View on CronoScan

When the user clicks “Connect Wallet”:

  • If walletAddress is not set (i.e., we are not yet connected):
    • Runs connectWallet(), which attempts repeated wallet connections.
    • On success, calls afterWalletConnect() to finalize the session.
    • On failure, sets the button text back to “Connect Wallet.”
  • If walletAddress is already set (meaning we’re connected):
    • Instead of re-connecting, it opens CronoScan in a new tab for the user’s address:
      https://cronoscan.com/address/<walletAddress>

3. afterWalletConnect (Establish Session)

  • We create an Ethers provider and signer.
  • We fetch the wallet’s address: (await signer.getAddress()).toLowerCase().
  • Update the UI button text to “Connected: 0x1234...ABCD.”
  • We add a listener for accountsChanged to detect if the user changes or disconnects their wallet:
    • This calls handleIdleTimeout(false) to forcibly lock/hide the vault if the account changes.
  • We attempt to switch or add the Cronos chain (chainId: 0x19).
  • We call hideOrShowCreateVault() to check for an existing vault in the factory:
    • If none, show the “Create Vault” button.
    • If found, we hide that button and load data via loadAndShowCredentials().

4. Create Vault (if needed)

If no vault exists for the user’s address, they see a “Create Vault” button. Clicking it calls createNewVault():

  • Calls factory.createVault() with value = creationCost.
  • On success, the transaction emits a “VaultCreated” event with the new vault address.
  • We store that address in userVault, hide the create button, and proceed (the user can set a password when they first add data).

5. Deriving the Wallet Key (Signature)

Before encrypting/decrypting data, we call deriveWalletKey(), which:

  • Asks the user to sign a special message:
    "I authorize access to my CroVault data on the blockchain"
  • Performs a SHA-256 hash on the resulting signature to form walletDerivedKey.
  • If the user refuses to sign, we keep prompting for a signature whenever encryption/decryption is needed.

6. Setting the Vault Password

If the user’s vault is new, or they have no data, they’ll eventually see a Set Password modal:

  • They must enter a 12+ character password meeting complexity rules.
  • This password is never sent to the server — it’s used client-side to derive encryption keys (AES-GCM) in combination with walletDerivedKey.
  • Once set, it cannot be changed (the only way to reset is to delete all vault data or deploy a new vault).

If the vault already has data, the user sees an Unlock modal: They must enter the correct password to decrypt existing data. If it’s wrong, showWrongPasswordModal() appears, letting them retry or cancel.

7. Viewing, Adding, Editing, or Deleting Data

  • Read from chain: readCredentials(), readNote(), and readWalletAddress() retrieve each item as an encrypted JSON string. We parse/decrypt with decryptWithPassword(sessionPassword, ...).
  • Add/Edit data:
    • Items go into pendingCredentials / pendingNotes / pendingWallets.
    • The user sees these as “(Pending)” until they click “Save All.”
  • Save All:
    • Encrypt each pending item with encryptWithPassword() (AES-GCM) and send to the contract’s upsert methods with value = upsertCost.
    • After mining, we re-fetch and re-decrypt the data so the UI is up to date.
  • Delete items:
    • Calls deleteCredentials(ids), etc., then re-loads from chain to refresh the UI.

8. Idle Timeout & Session Reset

The DApp enforces a 2.5-minute idle timer:

  • If no user activity (click, scroll, keypress) occurs, handleIdleTimeout(true) fires.
  • We immediately hide the vault, clear sessionPassword and walletDerivedKey, and show an alert about the session reset.
  • The user must re-sign and re-enter the password to resume.
  • If the user manually changes accounts in the wallet, we call handleIdleTimeout(false) (no alert) but still reset and hide the vault.

9. Resetting the Password (Delete All Data)

There’s no built-in method to “change” your vault password. Instead, if you want a fresh password, you must:

  1. Delete all items (credentials, notes, wallets) from your vault or deploy a new vault.
  2. Next time you add data, you can set a brand-new password.

10. Summary Diagram (Textual)

The overall state flow in text form:

          ┌───────────┐
          │ Page Load │
          └─────┬─────┘
                │
                v
   ┌───────────────────────────┐
   │ Check Cached Web3Provider │
   └────────────┬──────────────┘
                │No
                v
       [Show Connect Button]
                │User clicks
                v
     ┌──────────────────────┐
     │ connectWallet()      │
     │ -> afterWalletConnect│
     └──────────┬───────────┘
                │Yes
                v
 ┌───────────────────────────────┐
 │ Wallet is connected -> Button │
 │   links to CronoScan          │
 └───────────────────────────────┘


afterWalletConnect():
 ┌────────────────────────────────────────────────────────┐
 │1) Switch to Cronos chain                               │
 │2) walletAddress = getAddress()                         │
 │3) Check vault: factory.ownerToVault(address)           │
 │4) If vault=0x000.. => show "Create Vault"              │
 │   else => userVault & load data => possibly show       │
 │   unlock modal (if data found)                         │
 └────────────────────────────────────────────────────────┘

Create Vault Flow:
 ┌────────────────────────────────────────────────────────┐
 │ createVault(value=creationCost) -> event => userVault  │
 │ user must sign + set password when they add data.      │
 └────────────────────────────────────────────────────────┘

Unlock Flow:
 ┌────────────────────────────────────────────────────────┐
 │ If vault has data => showUnlockModal => user pass =>   │
 │ deriveWalletKey => decrypt => show vault => idleTimer  │
 └────────────────────────────────────────────────────────┘

Saving / Editing / Deleting Data:
 ┌────────────────────────────────────────────────────────┐
 │1) read & decrypt existing data                         │
 │2) user modifies => pending arrays => "Save All"        │
 │3) upsert with upsertCost => re-read => re-decrypt      │
 │4) "Delete" calls delete => re-read => UI refresh       │
 └────────────────────────────────────────────────────────┘

Idle Timeout / Account Switch:
 ┌────────────────────────────────────────────────────────┐
 │ If user is idle => handleIdleTimeout(true) => reset    │
 │ session => hide vault => user must unlock again.       │
 │ If accountsChanged => handleIdleTimeout(false).        │
 └────────────────────────────────────────────────────────┘

Reset Password:
 ┌────────────────────────────────────────────────────────┐
 │ Must delete all data or create a new vault => fresh pw │
 └────────────────────────────────────────────────────────┘