Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
7c13200
Support Vk saving in soroban format. Add enconding helpers in bridge.js
Fantoni0 Jan 21, 2026
3a4d26f
Add prover to index.html and update UI
Fantoni0 Jan 21, 2026
1f54c52
Add new field for ASP membership settings
Fantoni0 Jan 21, 2026
321fbbc
Deposit working
Fantoni0 Jan 21, 2026
c5f44a3
Withdraw and transact working
Fantoni0 Jan 22, 2026
10db074
Remove debug logs
Fantoni0 Jan 22, 2026
9344faa
Fix jest tests
Fantoni0 Jan 22, 2026
2a30489
Cleanup
Fantoni0 Jan 23, 2026
ffc05d0
Merge remote-tracking branch 'origin/main' into fetaure/wire-ui
Fantoni0 Jan 23, 2026
3826d8e
Format issues
Fantoni0 Jan 23, 2026
a1743a8
Refactor ui.js
Fantoni0 Jan 23, 2026
4bc0f62
Add basic registration/address book support
Fantoni0 Jan 23, 2026
413ca1d
Small UI fixes (#77)
NiDimi Jan 23, 2026
1d6939d
Added missing file
Fantoni0 Jan 25, 2026
11ab8e3
Proof failing
Fantoni0 Jan 25, 2026
939eef8
Proof working
Fantoni0 Jan 26, 2026
a6df9d3
Merge remote-tracking branch 'origin/fetaure/wire-ui' into fetaure/tr…
Fantoni0 Jan 26, 2026
f01aa5b
Merge and remove debug logs
Fantoni0 Jan 26, 2026
da1e38a
Admin panel changes
Fantoni0 Jan 26, 2026
50b6393
Working transfer
Fantoni0 Jan 27, 2026
aff77bf
Upload notes from files
Fantoni0 Jan 27, 2026
bf1af7c
Demo working pre-transact
Fantoni0 Jan 27, 2026
3884260
Minor issues with notes
Fantoni0 Jan 27, 2026
4ca10e6
Cleanup
Fantoni0 Jan 27, 2026
1c2a384
Fix search buttons
Fantoni0 Jan 28, 2026
9e7901b
Cargo fmt
Fantoni0 Jan 28, 2026
25beff5
feat: add insert_at() to MerkleTree
dkgoutham Jan 30, 2026
53748fb
feat: use insert_at in pool-store.js and asp-membership-store.js
dkgoutham Jan 30, 2026
953b31d
feat: add serialize() and deserialize() to MerkleTree
dkgoutham Jan 31, 2026
3ff4e30
chore: add snapshot DB store and bridge wrappers
dkgoutham Jan 31, 2026
20130b6
feat: persist and restore tree from IndexedDB in asp-membership-store…
dkgoutham Jan 31, 2026
9ffad03
chore: Remove redundant rebuildTree() after sync
dkgoutham Jan 31, 2026
6ee6947
feat: add build_from_leaves() batch constructor
dkgoutham Jan 31, 2026
7e0164c
chore: add buildMerkleTreeFromLeaves wrapper in bridge.js
dkgoutham Jan 31, 2026
2a27738
chore: use batch build in rebuild/init in pool-store and asp-membersh…
dkgoutham Jan 31, 2026
682a39b
chore: replace 1024-insert loop with single insert_at
dkgoutham Jan 31, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
118 changes: 101 additions & 17 deletions app/admin.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,27 +21,97 @@

<body class="bg-dark-950 text-dark-50 font-sans min-h-screen antialiased">
<div class="max-w-6xl mx-auto px-4 sm:px-6 lg:px-8 py-6 sm:py-8 flex flex-col gap-6 min-h-screen">
<header class="flex flex-col lg:flex-row lg:items-center justify-between gap-4 p-4 sm:p-6 bg-dark-900/80 backdrop-blur-sm border border-dark-800 rounded-xl" role="banner">
<div class="space-y-2">
<div class="flex items-center gap-2 text-xs uppercase tracking-[0.35em] text-brand-400">
<span class="w-6 h-px bg-brand-500"></span>
ASP Admin
</div>
<h1 class="text-xl sm:text-2xl font-semibold">Membership and Non-Membership Control</h1>
<p class="text-sm text-dark-400 max-w-2xl">
Generate compliant leaves, inspect contract roots, and insert new leaves
for the ASP membership and non-membership sets.
</p>
<header class="flex flex-col sm:flex-row items-center justify-between gap-4 p-4 bg-dark-900/80 backdrop-blur-sm border border-dark-800 rounded-xl overflow-visible relative z-50" role="banner">
<div class="flex items-center gap-3">
<div class="w-10 h-10 flex items-center justify-center bg-gradient-to-br from-brand-500 to-brand-600 rounded-lg shadow-lg shadow-brand-500/25" aria-hidden="true">
<svg class="w-6 h-6 text-dark-950" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<circle cx="12" cy="12" r="10"/>
<path d="M12 6v12M8 10l4-4 4 4"/>
<circle cx="12" cy="15" r="2" fill="currentColor"/>
</svg>
</div>
<div>
<h1 class="text-lg sm:text-xl font-semibold">
PoolStellar <span class="text-dark-400 font-normal">ASP Admin</span>
</h1>
<p class="text-xs text-dark-500">Manage membership and non-membership trees</p>
</div>
</div>
<div class="flex flex-wrap items-center gap-3">
<div class="px-3 py-1.5 bg-dark-800 border border-dark-700 rounded-full text-xs text-dark-300" id="networkChip">Network: --</div>
<div class="px-3 py-1.5 bg-dark-800 border border-dark-700 rounded-full text-xs text-dark-300" id="walletChip">Wallet: Disconnected</div>
<button class="px-4 py-2 bg-brand-500 text-dark-950 rounded-lg text-sm font-semibold shadow-lg shadow-brand-500/20 hover:bg-brand-400 transition" id="connectBtn" type="button">
Connect Freighter
</button>
<div class="flex items-center gap-3 overflow-visible">
<div class="flex items-center gap-2 px-3 py-1.5 bg-dark-800 border border-dark-700 rounded-full text-sm text-dark-300">
<span class="w-2 h-2 bg-emerald-500 rounded-full animate-pulse-dot shadow-sm shadow-emerald-500" aria-hidden="true"></span>
<span id="networkChip">Network</span>
</div>
<div class="relative overflow-visible" id="wallet-container">
<button
type="button"
id="connectBtn"
class="flex items-center gap-2 px-4 py-2 bg-dark-800 hover:bg-dark-700 border border-dark-700 hover:border-brand-500 rounded-lg text-sm font-medium transition-all duration-200 focus:outline-none focus:ring-2 focus:ring-brand-500 focus:ring-offset-2 focus:ring-offset-dark-950"
aria-label="Connect wallet"
>
<svg class="w-5 h-5" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" aria-hidden="true">
<rect x="2" y="6" width="20" height="14" rx="2"/>
<path d="M22 10h-4a2 2 0 0 0 0 4h4"/>
<circle cx="18" cy="12" r="1" fill="currentColor"/>
<path d="M6 6V4a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v2"/>
</svg>
<span id="walletChip">Connect Freighter</span>
</button>
</div>
</div>
</header>

<!-- Derive Keys Section -->
<section class="bg-dark-900/80 backdrop-blur-sm border border-dark-800 rounded-xl p-4 sm:p-6" aria-labelledby="derive-heading">
<div class="flex flex-col lg:flex-row lg:items-center justify-between gap-4">
<div class="space-y-1">
<h2 id="derive-heading" class="text-sm uppercase tracking-[0.25em] text-brand-400">Key Derivation</h2>
<p class="text-xs text-dark-400">
Sign a message to derive your ZK keys. These keys will be used to auto-fill the membership and non-membership forms.
<span class="text-brand-500">Keys persist when you switch accounts</span>, so you can derive for one user then sign with admin.
</p>
</div>
<div class="flex items-center gap-3">
<div class="text-right">
<p class="text-xs text-dark-500">Derived from account:</p>
<p id="derivedFromAccount" class="text-xs font-mono text-dark-300">--</p>
</div>
<button
type="button"
id="deriveKeysBtn"
class="flex items-center gap-2 px-4 py-2 bg-brand-500 text-dark-950 rounded-lg text-sm font-semibold shadow-lg shadow-brand-500/20 hover:bg-brand-400 transition disabled:opacity-50 disabled:cursor-not-allowed"
>
<svg class="w-4 h-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M21 2l-2 2m-7.61 7.61a5.5 5.5 0 1 1-7.778 7.778 5.5 5.5 0 0 1 7.777-7.777zm0 0L15.5 7.5m0 0l3 3L22 7l-3-3m-3.5 3.5L19 4"/>
</svg>
<span id="deriveKeysBtnText">Derive Keys</span>
</button>
</div>
</div>

<!-- Derived Keys Display -->
<div id="derivedKeysDisplay" class="hidden mt-4 grid grid-cols-1 lg:grid-cols-2 gap-4">
<div class="p-3 bg-dark-800 border border-dark-700 rounded-lg">
<div class="flex items-center justify-between mb-2">
<span class="text-[10px] uppercase tracking-wide text-dark-400">Private Key (Spending)</span>
<button type="button" class="copy-btn p-1 text-dark-500 hover:text-brand-500 transition-colors" data-target="derivedPrivateKey" title="Copy">
<svg class="w-3.5 h-3.5" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="8" y="8" width="12" height="12" rx="2"/><path d="M16 8V6a2 2 0 0 0-2-2H6a2 2 0 0 0-2 2v8a2 2 0 0 0 2 2h2"/></svg>
</button>
</div>
<div class="font-mono text-xs text-dark-200 break-all" id="derivedPrivateKey">--</div>
</div>
<div class="p-3 bg-dark-800 border border-dark-700 rounded-lg">
<div class="flex items-center justify-between mb-2">
<span class="text-[10px] uppercase tracking-wide text-dark-400">Public Key (ZK)</span>
<button type="button" class="copy-btn p-1 text-dark-500 hover:text-brand-500 transition-colors" data-target="derivedPublicKey" title="Copy">
<svg class="w-3.5 h-3.5" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="8" y="8" width="12" height="12" rx="2"/><path d="M16 8V6a2 2 0 0 0-2-2H6a2 2 0 0 0-2 2v8a2 2 0 0 0 2 2h2"/></svg>
</button>
</div>
<div class="font-mono text-xs text-brand-400 break-all" id="derivedPublicKey">--</div>
</div>
</div>
</section>

<main id="main-content" class="grid grid-cols-1 xl:grid-cols-3 gap-4 sm:gap-6">
<section class="bg-dark-900/80 backdrop-blur-sm border border-dark-800 rounded-xl p-4 sm:p-6 space-y-4" aria-labelledby="state-heading">
<div class="flex items-center justify-between gap-2">
Expand Down Expand Up @@ -163,6 +233,20 @@ <h2 id="activity-heading" class="text-sm uppercase tracking-[0.25em] text-brand-
</main>
</div>

<!-- Toast Container -->
<div id="toast-container" class="fixed bottom-4 right-4 flex flex-col gap-2 z-50" role="region" aria-label="Notifications" aria-live="polite"></div>

<!-- Toast Template -->
<template id="tpl-toast">
<div class="toast flex items-center gap-3 px-4 py-3 bg-dark-800 border rounded-lg shadow-xl max-w-sm animate-slide-in" role="alert">
<svg class="toast-icon w-5 h-5 flex-shrink-0" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"></svg>
<p class="toast-message flex-1 text-sm"></p>
<button type="button" class="toast-close p-1 text-dark-400 hover:text-dark-200 transition-colors" aria-label="Dismiss">
<svg class="w-4 h-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
</button>
</div>
</template>

<script type="module" src="js/admin.js"></script>
</body>
</html>
11 changes: 11 additions & 0 deletions app/crates/prover/src/crypto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,17 @@ pub(crate) fn poseidon2_compression(left: Scalar, right: Scalar) -> Scalar {
perm[0].add(input[0])
}

/// Poseidon2 hash with 2 inputs as compression mode

#[wasm_bindgen]
pub fn poseidon2_compression_wasm(input0: &[u8], input1: &[u8]) -> Result<Vec<u8>, JsValue> {
let a = bytes_to_scalar(input0)?;
let b = bytes_to_scalar(input1)?;

let result = poseidon2_compression(a, b);
Ok(scalar_to_bytes(&result))
}

/// Poseidon2 hash with 2 inputs and domain separation
///
/// Matches the Circom Poseidon2(2) template
Expand Down
17 changes: 13 additions & 4 deletions app/crates/prover/src/encryption.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,18 +139,27 @@ pub fn derive_note_private_key(signature: &[u8]) -> Result<Vec<u8>, JsValue> {
/// even when amount and recipient are the same.
///
/// # Returns
/// 32 bytes: Random BN254 scalar (little-endian)
/// 32 bytes: Random BN254 scalar (little-endian), reduced to field modulus
///
/// # Note
/// Unlike the private keys above, blinding factors are NOT derived
/// deterministically. They are random per-note and must be stored for later
/// use.
#[wasm_bindgen]
pub fn generate_random_blinding() -> Result<Vec<u8>, JsValue> {
let mut blinding = [0u8; 32];
getrandom::getrandom(&mut blinding)
let mut random_bytes = [0u8; 32];
getrandom::getrandom(&mut random_bytes)
.map_err(|e| JsValue::from_str(&format!("Random generation failed: {}", e)))?;
Ok(blinding.to_vec())

// Reduce to BN254 field
let scalar = Fr::from_le_bytes_mod_order(&random_bytes);

// Serialize back to little-endian bytes
let mut result = Vec::with_capacity(32);
scalar
.serialize_compressed(&mut result)
.map_err(|e| JsValue::from_str(&format!("Serialization failed: {}", e)))?;
Ok(result)
}

/// Encrypt note data using X25519-XSalsa20-Poly1305 (NaCl crypto_box).
Expand Down
Loading
Loading