fix(rcart): recognize existing session without wallet + show username

checkExistingSession() required a derived wallet address to set
authenticated=true, causing a re-login prompt even with a valid session.
Now authenticates on valid session and derives wallet lazily at payment
generation time. Also extracts claims.username for display instead of
showing raw did:key identifiers.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Jeff Emmett 2026-03-11 21:25:26 -07:00
parent a2d01ed3ad
commit 44dff1991f
1 changed files with 53 additions and 13 deletions

View File

@ -16,6 +16,7 @@ class FolkPaymentRequest extends HTMLElement {
private authenticated = false;
private walletAddress = '';
private did = '';
private username = '';
private authError = '';
private authenticating = false;
@ -80,14 +81,18 @@ class FolkPaymentRequest extends HTMLElement {
const hasSession = sm.isValid() || !!rstackSession;
if (!hasSession) return;
// Get DID from either source
this.did = sm.getDID() || rstackSession?.claims?.did || rstackSession?.claims?.sub || '';
// Get wallet address from session claims
// Get identity from either source
const smState = sm.getSession();
this.did = sm.getDID() || rstackSession?.claims?.did || rstackSession?.claims?.sub || '';
this.username = smState?.claims?.username || rstackSession?.claims?.username || '';
// Valid session = authenticated, regardless of wallet derivation
this.authenticated = true;
// Try to get wallet address from session claims
this.walletAddress = smState?.claims?.eid?.walletAddress || rstackSession?.claims?.eid?.walletAddress || '';
// If session exists but no wallet address, try deriving from key manager
// If no wallet in claims, try deriving from key manager
if (!this.walletAddress) {
try {
const { getKeyManager } = await import('../../../src/encryptid/key-derivation');
@ -99,10 +104,7 @@ class FolkPaymentRequest extends HTMLElement {
} catch { /* key manager not ready */ }
}
if (this.walletAddress) {
this.authenticated = true;
this.render();
}
this.render();
} catch { /* session module not available */ }
}
@ -167,12 +169,37 @@ class FolkPaymentRequest extends HTMLElement {
// ── Generate payment request ──
private async generatePayment() {
if (!this.walletAddress || !this.description) return;
if (!this.description) return;
if (!this.amountEditable && !this.amount) return;
this.generating = true;
this.authError = '';
this.render();
// Derive wallet on-demand if not yet available
if (!this.walletAddress) {
try {
const { getKeyManager } = await import('../../../src/encryptid/key-derivation');
const km = getKeyManager();
if (!km.isInitialized()) {
// Trigger passkey to initialize key manager
const identity = document.querySelector('rstack-identity') as any;
if (identity?.deriveKeys) await identity.deriveKeys();
}
if (km.isInitialized()) {
const keys = await km.getKeys();
if (keys.eoaAddress) this.walletAddress = keys.eoaAddress;
}
} catch { /* derivation failed */ }
if (!this.walletAddress) {
this.authError = 'Could not derive wallet address. Please try signing in again.';
this.generating = false;
this.render();
return;
}
}
try {
const { getSessionManager } = await import('../../../src/encryptid/session');
const { getSession: getRstackSession } = await import('../../../shared/components/rstack-identity');
@ -283,13 +310,24 @@ class FolkPaymentRequest extends HTMLElement {
</div>`;
}
private get displayName(): string {
return this.username || (this.did.length > 24 ? this.did.slice(0, 16) + '...' + this.did.slice(-6) : this.did);
}
private renderForm(): string {
return `
<div class="wallet-badge">
const walletBadge = this.walletAddress
? `<div class="wallet-badge">
<span class="wallet-label">Receiving wallet</span>
<span class="wallet-addr">${this.walletAddress.slice(0, 6)}...${this.walletAddress.slice(-4)}</span>
<span class="wallet-full" title="${this.walletAddress}">${this.walletAddress}</span>
</div>
</div>`
: `<div class="wallet-badge wallet-badge--warn">
<span class="wallet-label">Signed in as</span>
<span class="wallet-addr">${this.esc(this.displayName)}</span>
<span class="wallet-hint">Wallet address not yet derived it will be created when you generate a payment.</span>
</div>`;
return `
${walletBadge}
<div class="form">
<div class="field">
@ -539,6 +577,8 @@ class FolkPaymentRequest extends HTMLElement {
.wallet-label { color: var(--rs-text-secondary); font-size: 0.75rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; }
.wallet-addr { color: var(--rs-text-primary); font-family: monospace; font-size: 0.9375rem; font-weight: 600; }
.wallet-full { display: none; }
.wallet-badge--warn { flex-direction: column; align-items: flex-start; }
.wallet-hint { color: var(--rs-text-muted); font-size: 0.75rem; }
.form { display: flex; flex-direction: column; gap: 1rem; }
.field { display: flex; flex-direction: column; gap: 0.375rem; }