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 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..0bd3d6a --- /dev/null +++ b/src/routes/jurors/+page.svelte @@ -0,0 +1,308 @@ + + + + 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)} +

+
+
+

+ Min. bond +

+

+ {formatSats(MIN_BOND)} +

+
+
+ + +
+ {#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. +
  • +
  • + 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 +

+ +
+ +
+ + + + + + +
+ {#if !isLoggedIn} +

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

+ {/if} + +

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

+
+
+
+