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

' . $name . '

'; $out .= '

Value Layer — Ğ1 balance and capacity signals.

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

'; $out .= 'The Value Layer and the Ğ1 Wallet are 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 .= '

'; $out .= cry01_render_balance_display(); $out .= cry01_render_lookup_form($association_slug, $lookup); $out .= cry01_render_signal_board($association_slug, $access); if ($access === 'participant') { $signal_url = z_root() . '/cry01/' . cry01_h($association_slug) . '/signal'; $out .= '
'; $out .= 'Register a Signal'; $out .= '
'; } if ($access === 'operator') { $manage_url = z_root() . '/cry01/' . cry01_h($association_slug) . '/manage'; $g1_url = z_root() . '/cry01/' . cry01_h($association_slug) . '/g1'; $out .= '
'; $out .= 'Manage'; $out .= 'Ğ1 Candidates'; $out .= '
'; } $out .= ''; return $out; } // ---------------------------------------------------------------------------- // BALANCE DISPLAY (operator/cached) // ---------------------------------------------------------------------------- function cry01_render_balance_display() { // Renders the Ğ1 balance from cache. The cached key belongs to whoever last refreshed. // Shows staleness if cache is old. $cache = cry01_read_cache(); $balance = $cache['balance'] ?? null; $pubkey = $cache['g1_pubkey'] ?? ''; $refreshed = $cache['refreshed_at'] ?? null; $out = '
'; $out .= '
Ğ1 Balance
'; if ($balance === null) { $out .= '

Balance not yet loaded. Unlock your Ğ1 wallet and use Manage to refresh.

'; } else { $out .= '

' . cry01_h($balance) . '

'; if ($pubkey) { $out .= '

' . cry01_h(substr($pubkey, 0, 16) . '...') . '

'; } if ($refreshed) { $stale = cry01_cache_is_stale() ? ' stale' : ''; $out .= '

Last refreshed: ' . cry01_h($refreshed) . $stale . '

'; } } $out .= '
'; return $out; } // ---------------------------------------------------------------------------- // PUBLIC BALANCE LOOKUP // ---------------------------------------------------------------------------- function cry01_render_lookup_form($association_slug, $lookup = []) { // Renders the public Ğ1 address lookup form. // Anyone can use this — no SASE, no wallet session, nothing stored. // Paste an address, see its current balance and account details, read // directly from this node's own Duniter mirror. $lookup_url = z_root() . '/cry01/' . cry01_h($association_slug) . '/lookup'; $error = $lookup['lookup_error'] ?? ''; $entered_address = $lookup['lookup_address'] ?? ''; $balance = $lookup['lookup_balance'] ?? null; $account_info = $lookup['lookup_account_info'] ?? null; $out = '
'; $out .= '
Ğ1 Address Lookup
'; $out .= '

Paste any Ğ1 wallet address to check its current balance and account details — read directly from this node\'s Duniter mirror. Nothing is stored.

'; $out .= '
'; $out .= cry01_csrf_token(); $out .= '
'; $out .= ''; $out .= ''; $out .= '
'; $out .= '
'; if ($error) { $out .= '
' . cry01_h($error) . '
'; } elseif ($balance !== null) { $out .= '
'; $out .= '' . cry01_h(substr($entered_address, 0, 16) . '...') . '
'; $out .= '' . cry01_h($balance) . ''; $out .= '
'; if ($account_info) { $out .= cry01_render_account_info_table($account_info); } } $out .= '
'; return $out; } function cry01_render_account_info_table($info) { // Renders the full decoded AccountInfo struct in plain language. // $info is the array returned by cry01_decode_account_info() / // cry01_get_account_info(): nonce, consumers, providers, sufficients, // free, reserved, frozen, flags — all base-10 decimal strings of raw // on-chain units (free/reserved/frozen/flags are in centimes; nonce/ // consumers/providers/sufficients are plain counts). // // 'free' is already shown separately as the headline balance — this // table covers the remaining fields. 'flags' is an internal bitfield // (account feature flags) and is not meaningful to a layperson; it is // omitted from display but available in $info for anyone who needs it. $reserved = cry01_format_g1_amount($info['reserved'] ?? '0'); $frozen = cry01_format_g1_amount($info['frozen'] ?? '0'); $nonce = $info['nonce'] ?? '0'; $out = '
'; $out .= ''; $out .= ''; $out .= ''; if ($info['reserved'] !== '0') { $out .= ''; } if ($info['frozen'] !== '0') { $out .= ''; } $out .= ''; $out .= '
Transactions sent' . cry01_h($nonce) . '
Reserved' . cry01_h($reserved) . '
Frozen' . cry01_h($frozen) . '
'; $out .= '
'; return $out; } // ---------------------------------------------------------------------------- // SIGNAL BOARD // ---------------------------------------------------------------------------- function cry01_render_signal_board($association_slug, $access) { // Renders the signal board. Visible to participants and operator only. if ($access === 'public') { return '
Signal board is visible to verified participants only.
'; } // TODO: load signals from orchestrator spool for this association. $out = '
'; $out .= '
Capacity Signals
'; $out .= '

No signals posted yet.

'; $out .= '
'; return $out; } // ---------------------------------------------------------------------------- // SIGNAL FORM // ---------------------------------------------------------------------------- function cry01_render_signal_form($association_slug, $access) { // Renders the capacity signal registration form. // The g1_pubkey field is populated by the g1wallet session event when available. $config = cry01_load_config(); $categories = $config['signal_categories'] ?? []; $form_url = z_root() . '/cry01/' . cry01_h($association_slug) . '/signal'; $out = '
'; $out .= '

Register a Capacity Signal

'; $out .= '

Describe what you are offering or seeking, denominated in Ğ1.

'; // Wallet session note — replaced by g1wallet integration once built. $out .= '
Your Ğ1 public key will be populated automatically once the Ğ1 Wallet addon is installed. Until then, enter it manually below.
'; $out .= '
'; $out .= cry01_csrf_token(); // g1_pubkey — will be read-only and auto-populated by g1wallet session once available. $out .= '
'; $out .= ''; $out .= ''; $out .= '
Your Ğ1 address. This is your payment address for this signal.
'; $out .= '
'; // Direction $out .= '
'; $out .= '
Direction *'; $out .= '
'; $out .= '
'; $out .= '
'; // Category if ($categories) { $out .= '
'; $out .= ''; $out .= '
'; } // Description $out .= '
'; $out .= ''; $out .= ''; $out .= '
'; // Denomination $out .= '
'; $out .= ''; $out .= ''; $out .= '
The amount in Ğ1 you consider fair exchange.
'; $out .= '
'; // Duration $out .= '
'; $out .= ''; $out .= ''; $out .= '
'; $out .= '
'; $out .= ''; $out .= '
'; $out .= '
'; $out .= '
'; return $out; } // ---------------------------------------------------------------------------- // Ğ1 CERTIFICATION CANDIDATE LIST // ---------------------------------------------------------------------------- function cry01_render_g1_candidates($association_slug) { // Renders the operator-only list of SASE participants with registered Ğ1 keys. // TODO: load candidate list from orchestrator spool. $out = '
'; $out .= '

Ğ1 Certification Candidates

'; $out .= '

SASE participants who have registered a Ğ1 public key and are eligible for web of trust certification.

'; $out .= '

No candidates registered yet.

'; $out .= '
'; return $out; } // ---------------------------------------------------------------------------- // MANAGE // ---------------------------------------------------------------------------- function cry01_render_manage($association_slug) { // Renders the operator manage page: cache refresh and config status. // The Ğ1 public key comes from the wallet session — not from config. $cache = cry01_read_cache(); $refreshed = $cache['refreshed_at'] ?? null; $config = cry01_load_config(); $has_rpc = !empty($config['g1_rpc_endpoint']); $manage_url = z_root() . '/cry01/' . cry01_h($association_slug) . '/manage'; $out = '
'; $out .= '

Value Layer — Manage

'; // Config status $out .= '
'; $out .= '
Configuration
'; $out .= '

' . ($has_rpc ? '✓' : '✗') . ' Duniter RPC endpoint: '; $out .= $has_rpc ? 'configured' : 'missing'; $out .= '

'; $out .= '

Your Ğ1 public key comes from your Ğ1 Wallet session — not from config. '; $out .= 'Unlock your wallet at Ğ1 Wallet, then return here to refresh.

'; $out .= '
'; // Cache status $out .= '
'; $out .= '
Balance Cache
'; if ($refreshed) { $cached_key = $cache['g1_pubkey'] ?? ''; $stale = cry01_cache_is_stale() ? ' (stale)' : ' (current)'; $out .= '

Last refreshed: ' . cry01_h($refreshed) . $stale . '

'; if ($cached_key) { $out .= '

Cached key: ' . cry01_h(substr($cached_key, 0, 16) . '...') . '

'; } } else { $out .= '

Cache has not been populated yet.

'; } $out .= '
'; // Refresh form — g1_pubkey comes from wallet session via hidden field. // g1wallet.js populates data-g1wallet-target="pubkey" fields on unlock. $out .= '
'; $out .= cry01_csrf_token(); $out .= ''; $out .= ''; $out .= ''; $out .= 'Requires active Ğ1 Wallet session.'; $out .= '
'; $out .= '
'; return $out; }