diff --git a/modules/rwallet/components/folk-wallet-viewer.ts b/modules/rwallet/components/folk-wallet-viewer.ts
index 2a32e90..2bafe8c 100644
--- a/modules/rwallet/components/folk-wallet-viewer.ts
+++ b/modules/rwallet/components/folk-wallet-viewer.ts
@@ -101,6 +101,7 @@ class FolkWalletViewer extends HTMLElement {
// Linked wallets state
private isAuthenticated = false;
private passKeyEOA = "";
+ private userDID = "";
private linkedWallets: LinkedWallet[] = [];
private showProviderPicker = false;
private discoveredProviders: DiscoveredProvider[] = [];
@@ -193,6 +194,7 @@ class FolkWalletViewer extends HTMLElement {
this.isAuthenticated = true;
this.topTab = "my-wallets";
this.passKeyEOA = parsed.claims?.eid?.walletAddress || "";
+ this.userDID = parsed.claims?.did || "";
this.loadLinkedWallets().then(() => this.loadMyWalletBalances());
this.loadCRDTBalances();
}
@@ -1235,6 +1237,24 @@ class FolkWalletViewer extends HTMLElement {
font-size: 13px; color: var(--rs-text-primary);
}
+ /* ── EncryptID identity card ── */
+ .encryptid-card { border-color: rgba(168,85,247,0.25); }
+ .encryptid-wallets { display: flex; flex-direction: column; gap: 12px; }
+ .encryptid-wallet-section {
+ padding: 10px 12px; border-radius: 8px;
+ background: var(--rs-bg-hover); border: 1px solid var(--rs-border-subtle);
+ }
+ .encryptid-wallet-label {
+ display: flex; align-items: center; gap: 6px;
+ font-size: 12px; font-weight: 600; text-transform: uppercase;
+ letter-spacing: 0.5px; color: var(--rs-text-secondary); margin-bottom: 8px;
+ }
+ .wallet-type-dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; }
+ .wallet-type-addr {
+ font-family: monospace; font-weight: 400; font-size: 11px;
+ color: var(--rs-text-muted); margin-left: auto; text-transform: none; letter-spacing: 0;
+ }
+
/* ── Aggregate stats ── */
.aggregate-stats {
display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
@@ -1421,20 +1441,15 @@ class FolkWalletViewer extends HTMLElement {
let html = '
';
- // EncryptID wallet card
- if (this.passKeyEOA) {
- html += this.renderWalletCard(this.passKeyEOA, "EncryptID", "encryptid", true);
- }
+ // EncryptID identity card — always shown for authenticated users
+ // Every EncryptID identity has both a CRDT wallet (DID) and an EVM wallet (passkey-derived)
+ html += this.renderEncryptIdCard();
- // Linked wallet cards
+ // Linked wallet cards (external wallets)
for (const w of this.linkedWallets) {
html += this.renderWalletCard(w.address, w.providerName || w.type.toUpperCase(), w.type, false, w.id);
}
- if (!this.passKeyEOA && this.linkedWallets.length === 0) {
- html += '
No wallets linked yet. Link a browser wallet to get started.
';
- }
-
html += '
';
// Aggregate total
@@ -1450,7 +1465,104 @@ class FolkWalletViewer extends HTMLElement {
return html;
}
- private renderWalletCard(address: string, label: string, badgeClass: string, isEncryptId: boolean, walletId?: string): string {
+ private renderEncryptIdCard(): string {
+ // ── CRDT Wallet (DID) ──
+ const didShort = this.userDID
+ ? `${this.userDID.slice(0, 16)}...${this.userDID.slice(-6)}`
+ : "loading...";
+
+ let crdtRows = "";
+ if (this.crdtLoading) {
+ crdtRows = ` Loading...
`;
+ } else if (this.crdtBalances.length > 0) {
+ crdtRows = this.crdtBalances.map(t => {
+ const formatted = (t.balance / Math.pow(10, t.decimals)).toFixed(2);
+ return `
+ ${t.icon || '\u{1FA99}'}
+ ${this.esc(t.symbol)}
+ ${this.esc(t.name)}
+ ${formatted}
+
`;
+ }).join("");
+ } else {
+ crdtRows = `No CRDT token balances
`;
+ }
+
+ // ── EVM Wallet (passkey-derived) ──
+ const chainBalances = this.passKeyEOA
+ ? (this.myWalletBalances.get(this.passKeyEOA.toLowerCase()) || [])
+ : [];
+
+ const allBals: Array = [];
+ for (const ch of chainBalances) {
+ for (const b of ch.balances) {
+ allBals.push({ ...b, chainId: ch.chainId, chainName: ch.chainName });
+ }
+ }
+
+ const sorted = allBals
+ .filter(b => parseFloat(b.fiatBalance || "0") > 0.01 || BigInt(b.balance || "0") > 0n)
+ .sort((a, b) => parseFloat(b.fiatBalance || "0") - parseFloat(a.fiatBalance || "0"));
+
+ const totalUSD = sorted.reduce((sum, b) => sum + parseFloat(b.fiatBalance || "0"), 0);
+
+ let evmBalanceRows = "";
+ if (sorted.length > 0) {
+ evmBalanceRows = sorted.slice(0, 10).map(b => {
+ const color = CHAIN_COLORS[b.chainId] || "#888";
+ return `
+ ${this.esc(b.chainName)} |
+ ${this.esc(b.token?.symbol || "ETH")} |
+ ${this.formatBalance(b.balance, b.token?.decimals || 18)} |
+ ${this.formatUSD(b.fiatBalance)} |
+
`;
+ }).join("");
+ if (sorted.length > 10) {
+ evmBalanceRows += `| + ${sorted.length - 10} more tokens |
`;
+ }
+ }
+
+ return `
+
+
+
+
+
+
+
+
+ CRDT Wallet
+ ${this.esc(didShort)}
+
+ ${crdtRows}
+
+
+
+
+
+
+ EVM Wallet
+ ${this.passKeyEOA ? this.shortenAddress(this.passKeyEOA) : "not derived"}
+
+ ${evmBalanceRows ? `
+
+
+ | Chain | Token | Balance | USD |
+
+ ${evmBalanceRows}
+
` : `
No on-chain balances found
`}
+
+
+
`;
+ }
+
+ private renderWalletCard(address: string, label: string, badgeClass: string, _isEncryptId: boolean, walletId?: string): string {
const chainBalances = this.myWalletBalances.get(address.toLowerCase()) || [];
// Flatten all balances for this wallet
@@ -1483,24 +1595,6 @@ class FolkWalletViewer extends HTMLElement {
}
}
- // CRDT tokens for EncryptID wallet
- let crdtSection = "";
- if (isEncryptId && this.crdtBalances.length > 0) {
- const crdtRows = this.crdtBalances.map(t => {
- const formatted = (t.balance / Math.pow(10, t.decimals)).toFixed(2);
- return `
- ${t.icon || '\u{1FA99}'}
- ${this.esc(t.symbol)}
- ${formatted}
-
`;
- }).join("");
- crdtSection = `
-
-
Local Tokens (CRDT)
- ${crdtRows}
-
`;
- }
-
return `
`;
}
diff --git a/modules/rwallet/mod.ts b/modules/rwallet/mod.ts
index 6cf9633..16405ea 100644
--- a/modules/rwallet/mod.ts
+++ b/modules/rwallet/mod.ts
@@ -840,7 +840,7 @@ function renderWallet(spaceSlug: string, initialView?: string) {
modules: getModuleInfoList(),
theme: "dark",
body: ``,
- scripts: ``,
+ scripts: ``,
styles: ``,
});
}