Files
kane-diagnostics/hubzilla/addon/g1wallet/g1wallet_renderer.php
2026-06-08 03:33:03 -04:00

159 lines
7.0 KiB
PHP

<?php
/**
* g1wallet_renderer.php — All HTML rendering for g1wallet.
* Knows nothing about network calls or POST handling.
* Knows nothing about crypto — that lives entirely in g1wallet.js.
*/
// ----------------------------------------------------------------------------
// ACCESS WALL
// ----------------------------------------------------------------------------
function g1wallet_render_access_wall() {
return '
<div class="g1wallet-content">
<div class="alert alert-info" role="alert">
<strong>SASE verification required to access the Ğ1 Wallet.</strong>
This wallet is available to verified HOA participants only.
To participate, you must complete the SASE process.
Visit <a href="https://directory.diagnostics.kane-il.us/channel/theron">
directory.diagnostics.kane-il.us
</a> to begin.
</div>
</div>
';
}
// ----------------------------------------------------------------------------
// WALLET LANDING
// ----------------------------------------------------------------------------
function g1wallet_render_landing($access) {
// Wallet landing: shows unlock form or unlocked interface depending on JS session state.
// At skeleton stage, always shows the unlock form.
// Once g1wallet.js is wired, the JS will swap to the unlocked view on successful derivation.
$out = '<div class="g1wallet-content">';
$out .= '<div class="g1wallet-header mb-3">';
$out .= '<h2>Ğ1 Wallet</h2>';
$out .= '<p class="text-muted">Your self-sovereign Ğ1 identity. Keys are derived in your browser and never leave your device.</p>';
$out .= '</div>';
// Locked view — shown by default. JS hides this and shows unlocked-view on successful derivation.
$out .= '<div id="g1wallet-locked-view">';
$out .= g1wallet_render_unlock_form();
$out .= '</div>';
// Unlocked view — hidden by default. JS populates and shows this after derivation.
$out .= '<div id="g1wallet-unlocked-view" style="display:none;">';
$out .= g1wallet_render_unlocked_placeholder($access);
$out .= '</div>';
$out .= '</div>';
return $out;
}
// ----------------------------------------------------------------------------
// UNLOCK FORM
// ----------------------------------------------------------------------------
function g1wallet_render_unlock_form() {
// Renders the wallet unlock form.
// The form is handled entirely by g1wallet.js — it does NOT POST to the server.
// Pseudo and password never leave the browser.
$out = '<div class="g1wallet-unlock-form">';
$out .= '<h4>Unlock Your Wallet</h4>';
$out .= '<p class="text-muted small">Enter your Ğ1 credentials. These are used only in your browser to derive your keypair. They are never sent to the server.</p>';
$out .= '<div class="mb-3">';
$out .= '<label class="form-label" for="g1wallet-pseudo">Pseudo <span class="text-danger">*</span></label>';
$out .= '<input type="text" class="form-control" id="g1wallet-pseudo" name="g1wallet_pseudo"
autocomplete="username" autocorrect="off" autocapitalize="off" spellcheck="false"
placeholder="your Ğ1 pseudo">';
$out .= '<div class="form-text">Your Ğ1 pseudo — the same one you use in Cesium or Ğecko.</div>';
$out .= '</div>';
$out .= '<div class="mb-3">';
$out .= '<label class="form-label" for="g1wallet-password">Password <span class="text-danger">*</span></label>';
$out .= '<input type="password" class="form-control" id="g1wallet-password" name="g1wallet_password"
autocomplete="current-password"
placeholder="your Ğ1 password">';
$out .= '<div class="form-text">Your Ğ1 password. Never sent to the server.</div>';
$out .= '</div>';
$out .= '<div id="g1wallet-unlock-error" class="alert alert-danger" style="display:none;" role="alert"></div>';
$out .= '<div class="mt-3">';
$out .= '<button type="button" id="g1wallet-unlock-btn" class="btn btn-primary">Unlock Wallet</button>';
$out .= '<span id="g1wallet-unlock-spinner" class="ms-2 text-muted small" style="display:none;">Deriving keypair…</span>';
$out .= '</div>';
$out .= '<div class="mt-3">';
$out .= '<p class="text-muted small">';
$out .= 'Don\'t have a Ğ1 account? You can create one using ';
$out .= '<a href="https://cesium.app" target="_blank" rel="noopener">Cesium</a> or ';
$out .= '<a href="https://gecko.duniter.org" target="_blank" rel="noopener">Ğecko</a>.';
$out .= '</p>';
$out .= '</div>';
$out .= '</div>';
return $out;
}
// ----------------------------------------------------------------------------
// UNLOCKED INTERFACE (PLACEHOLDER)
// ----------------------------------------------------------------------------
function g1wallet_render_unlocked_placeholder($access) {
// Placeholder for the unlocked wallet interface.
// Populated by g1wallet.js once key derivation is implemented.
$pubkey_url = z_root() . '/g1wallet/pubkey';
$out = '<div class="g1wallet-unlocked">';
$out .= '<div class="alert alert-success d-flex justify-content-between align-items-center">';
$out .= '<span><strong>Wallet unlocked.</strong></span>';
$out .= '<button type="button" id="g1wallet-lock-btn" class="btn btn-sm btn-outline-secondary">Lock</button>';
$out .= '</div>';
$out .= '<div class="mb-3">';
$out .= '<h5 class="g1wallet-section-label">Public Key</h5>';
$out .= '<p id="g1wallet-pubkey-display" class="font-monospace text-muted small">—</p>';
$out .= '</div>';
$out .= '<div class="mb-3">';
$out .= '<h5 class="g1wallet-section-label">Ğ1 Balance</h5>';
$out .= '<p id="g1wallet-balance-display" class="text-muted fst-italic">Not yet loaded.</p>';
$out .= '<button type="button" id="g1wallet-refresh-balance-btn" class="btn btn-sm btn-outline-primary">Refresh Balance</button>';
$out .= '</div>';
// Hidden form to store pubkey in channel settings — posted once after first unlock.
// g1wallet.js posts to this via fetch() after derivation, not via form submit.
$out .= '<form id="g1wallet-pubkey-form" style="display:none;">';
$out .= g1wallet_csrf_token();
$out .= '<input type="hidden" id="g1wallet-pubkey-input" name="g1_pubkey" value="">';
$out .= '</form>';
if ($access === 'operator') {
$out .= '<div class="mt-3">';
$out .= '<p class="text-muted small">You are the operator. Your Ğ1 public key is stored in your channel settings, not in config.</p>';
$out .= '</div>';
}
$out .= '</div>';
return $out;
}
// ----------------------------------------------------------------------------
// ERROR
// ----------------------------------------------------------------------------
function g1wallet_render_error($message) {
// Shows a plain-language error. Never shows a blank page or stack trace.
return '<div class="g1wallet-content"><div class="alert alert-danger">'
. g1wallet_h($message)
. '</div></div>';
}