From 6a19597b59dd0d9cd3bfce350c839f7164206abf Mon Sep 17 00:00:00 2001 From: guildm4ster <289806744+guildm4ster@users.noreply.github.com> Date: Mon, 10 Aug 2026 17:58:19 +0300 Subject: [PATCH 1/4] chore: add docs/ to .gitignore --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 3b462cb..7aae3b9 100644 --- a/.gitignore +++ b/.gitignore @@ -21,3 +21,6 @@ Thumbs.db # Vite vite.config.js.timestamp-* vite.config.ts.timestamp-* + +# misc +docs \ No newline at end of file From ed34b1a8b4bfa6cd93b9c9dc09c2376407f4b4e1 Mon Sep 17 00:00:00 2001 From: guildm4ster <289806744+guildm4ster@users.noreply.github.com> Date: Mon, 10 Aug 2026 18:26:23 +0300 Subject: [PATCH 2/4] feat: add juror registry page --- src/lib/components/JurorCard.svelte | 124 ++++++++++++ src/lib/components/Navbar.svelte | 6 + src/lib/types/juror.ts | 21 ++ src/routes/jurors/+page.svelte | 294 ++++++++++++++++++++++++++++ 4 files changed, 445 insertions(+) create mode 100644 src/lib/components/JurorCard.svelte create mode 100644 src/lib/types/juror.ts create mode 100644 src/routes/jurors/+page.svelte diff --git a/src/lib/components/JurorCard.svelte b/src/lib/components/JurorCard.svelte new file mode 100644 index 0000000..aeee7b9 --- /dev/null +++ b/src/lib/components/JurorCard.svelte @@ -0,0 +1,124 @@ + + +
+ +
+
+ {#if juror.avatarUrl} + {juror.displayName} + {:else} + + {initial} + + {/if} +
+

+ {juror.displayName} +

+

+ {juror.nostrPubkey.slice(0, 8)}…{juror.nostrPubkey.slice(-4)} +

+
+
+ + {availabilityBadge[juror.availability].label} + +
+ + +
+ Bond + + {formatSats(juror.bondAmountSats)} + +
+ + + {#if juror.specialisations.length > 0} + + {/if} + + +
+ {#if juror.reputation.totalVotes === 0} + No votes yet + {:else} + + {juror.reputation.totalVotes} + {juror.reputation.totalVotes === 1 ? 'vote' : 'votes'} + + {#if majorityRate !== null} + + {majorityRate}% + majority + + {/if} + {#if juror.reputation.nonParticipation > 0} + + {juror.reputation.nonParticipation} + missed + + {/if} + {/if} +
+
diff --git a/src/lib/components/Navbar.svelte b/src/lib/components/Navbar.svelte index 8b94f0f..3847e34 100644 --- a/src/lib/components/Navbar.svelte +++ b/src/lib/components/Navbar.svelte @@ -39,6 +39,12 @@ > New bounty + + Jurors + diff --git a/src/lib/types/juror.ts b/src/lib/types/juror.ts new file mode 100644 index 0000000..3907223 --- /dev/null +++ b/src/lib/types/juror.ts @@ -0,0 +1,21 @@ +export type JurorAvailability = 'active' | 'inactive'; + +export interface JurorReputation { + totalVotes: number; + majorityVotes: number; + minorityVotes: number; + nonParticipation: number; +} + +export interface Juror { + /** Hex-encoded Nostr public key */ + nostrPubkey: string; + displayName: string; + avatarUrl?: string; + /** Satoshi amount locked in the bond vTXO (≥ MIN_JUROR_BOND = 100,000) */ + bondAmountSats: number; + /** Skill tags used for panel matching, e.g. ["rust", "bitcoin"] */ + specialisations: string[]; + availability: JurorAvailability; + reputation: JurorReputation; +} diff --git a/src/routes/jurors/+page.svelte b/src/routes/jurors/+page.svelte new file mode 100644 index 0000000..e63db01 --- /dev/null +++ b/src/routes/jurors/+page.svelte @@ -0,0 +1,294 @@ + + + + SatCode — Juror Registry + + +
+ +

Juror Registry

+

+ Staked jurors resolve disputes on subjective bounties. A randomly selected + panel reviews evidence and votes; the majority verdict releases the escrow. +

+ + +
+
+

+ Active jurors +

+

{activeJurors.length}

+
+
+

+ Total bonded +

+

+ {formatSats(totalBondedSats)} +

+
+
+

+ Avg. bond +

+

+ {formatSats(avgBondSats)} +

+
+
+ + +
+ {#each jurors as juror (juror.nostrPubkey)} + + {/each} +
+ + +
+

Become a Juror

+

+ Stake a bond of at least {formatSats(MIN_BOND)} to register as juror. You'll + earn sats on every dispute you help resolve. Voting without reasoning, or missing + a vote, may result in a partial bond slash. +

+ + +
+

How it works

+
    +
  • + Create an Ark vTXO of at least {formatSats(MIN_BOND)} locked to a juror + bond script. +
  • +
  • + Fill in the form below and submit your registration to Nostr + (kind:30060). +
  • +
  • You'll be eligible for random selection onto dispute panels.
  • +
  • Bonds must be refreshed every 30 days to maintain eligibility.
  • +
+
+ +
+ + + + + + +
+ Availability +
+ + +
+ + Set to inactive to temporarily pause panel selection without + deregistering. + +
+ +
+ {#if !isLoggedIn} +

+ You must be logged in with Nostr to register as a juror. +

+ {/if} + +

+ Publishing to Nostr isn't wired up yet. +

+
+
+
+
From 8926cd448b3c9e28f8263b96d2649f4b0642bf4d Mon Sep 17 00:00:00 2001 From: guildm4ster <289806744+guildm4ster@users.noreply.github.com> Date: Tue, 11 Aug 2026 15:57:07 +0300 Subject: [PATCH 3/4] UI: put juror form into Modal --- src/routes/jurors/+page.svelte | 108 +++++++++++++++++++-------------- 1 file changed, 61 insertions(+), 47 deletions(-) diff --git a/src/routes/jurors/+page.svelte b/src/routes/jurors/+page.svelte index e63db01..e964207 100644 --- a/src/routes/jurors/+page.svelte +++ b/src/routes/jurors/+page.svelte @@ -1,5 +1,6 @@ @@ -149,10 +148,10 @@

- Avg. bond + Min. bond

- {formatSats(avgBondSats)} + {formatSats(MIN_BOND)}

@@ -166,12 +165,16 @@
-

Become a Juror

-

- Stake a bond of at least {formatSats(MIN_BOND)} to register as juror. You'll - earn sats on every dispute you help resolve. Voting without reasoning, or missing - a vote, may result in a partial bond slash. -

+
+
+

Become a Juror

+

+ Stake a bond of at least {formatSats(MIN_BOND)} to register as juror. You'll + earn sats on every dispute you help resolve. Voting without reasoning, or + missing a vote, may result in a partial bond slash. +

+
+
  • - Fill in the form below and submit your registration to Nostr - (kind:30060). + Click Become a juror and submit your + registration to Nostr (kind:30060).
  • You'll be eligible for random selection onto dispute panels.
  • Bonds must be refreshed every 30 days to maintain eligibility.
  • + +
    + + + (showModal = false)} + labelId="juror-modal-title" +> +
    +
    +

    + Become a Juror +

    + +
    -
    + -
    - Availability -
    - - -
    - - Set to inactive to temporarily pause panel selection without - deregistering. - -
    -
    {#if !isLoggedIn}

    @@ -291,4 +305,4 @@

    - +
    From 2d0fda17c3a885b2e00a0f8c5d91c98edbef71cf Mon Sep 17 00:00:00 2001 From: guildm4ster <289806744+guildm4ster@users.noreply.github.com> Date: Tue, 11 Aug 2026 17:45:09 +0300 Subject: [PATCH 4/4] chore: format --- README.md | 2 +- src/routes/jurors/+page.svelte | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 23afb46..eeb7434 100644 --- a/README.md +++ b/README.md @@ -4,4 +4,4 @@ Bounties are organized in the open on Nostr, work is paid in Bitcoin - a permiss # License -This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or any later version. \ No newline at end of file +This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or any later version. diff --git a/src/routes/jurors/+page.svelte b/src/routes/jurors/+page.svelte index e964207..0bd3d6a 100644 --- a/src/routes/jurors/+page.svelte +++ b/src/routes/jurors/+page.svelte @@ -196,7 +196,7 @@