'; } // ----------------------------------------------------------------------------- // WALLET LANDING // ----------------------------------------------------------------------------- function g1wallet_render_landing($access) { // Wallet landing: shows unlock form or unlocked interface depending on JS session state. // JS swaps to the unlocked view on successful derivation. $out = '
'; $out .= '
'; $out .= '

Ğ1 Wallet

'; $out .= '

Your self-sovereign Ğ1 identity. Keys are derived in your browser and never leave your device.

'; $out .= '
'; // Optional participation notice. $out .= '

'; $out .= 'The Ğ1 Wallet is optional. '; $out .= 'Ğ1 is a libre currency independent of fiat, used for valuing and bartering surplus capacity among private individuals. '; $out .= 'The Civic Infrastructure implements it for participants who choose to engage in that economy. '; $out .= 'It is not required for participation in the diagnostic record system. '; $out .= 'Future addons such as Barter will require an active wallet — this page is where you manage it.'; $out .= '

'; // Locked view — shown by default. JS hides this and shows unlocked-view on successful derivation. $out .= '
'; $out .= g1wallet_render_unlock_form(); $out .= '
'; // Unlocked view — hidden by default. JS populates and shows this after derivation. $out .= ''; $out .= '
'; 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. // The mnemonic never leaves the browser. // // Derivation (Duniter v2 / Substrate / Ğecko standard): // 12-word BIP39 mnemonic // → mnemonicToEntropy() → 16 bytes of raw entropy // → use entropy directly as 32-byte Ed25519 seed (zero-padded right) // → derive Ed25519 keypair (SubtleCrypto, non-extractable private key) // → SS58-encode public key with Ğ1 network prefix → g1... address $out = '
'; $out .= '

Unlock Your Wallet

'; $out .= '

Enter your 12-word Ğ1 mnemonic phrase. It is used only in your browser to derive your keypair. It is never sent to the server.

'; $out .= '
'; $out .= ''; $out .= ''; $out .= '
Your 12-word Ğ1 mnemonic — the recovery phrase generated when your Ğ1 account was created. Words are separated by single spaces, lowercase, English wordlist.
'; $out .= '
'; $out .= ''; $out .= '
'; $out .= ''; $out .= ''; $out .= '
'; $out .= '
'; return $out; } // ----------------------------------------------------------------------------- // UNLOCKED INTERFACE // ----------------------------------------------------------------------------- function g1wallet_render_unlocked_placeholder($access) { // Unlocked wallet interface. // Populated by g1wallet.js after key derivation. $out = '
'; $out .= '
'; $out .= 'Wallet unlocked.'; $out .= ''; $out .= '
'; $out .= '
'; $out .= ''; $out .= '

'; $out .= '
'; $out .= '
'; $out .= ''; $out .= '

Not yet loaded.

'; $out .= ''; $out .= '
'; // 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 .= ''; if ($access === 'operator') { $out .= '
'; $out .= '

You are the operator. Your Ğ1 public key is stored in your channel settings, not in config.

'; $out .= '
'; } $out .= '
'; return $out; } // ----------------------------------------------------------------------------- // ERROR // ----------------------------------------------------------------------------- function g1wallet_render_error($message) { // Shows a plain-language error. Never shows a blank page or stack trace. return '
' . g1wallet_h($message) . '
'; }