@umbra-privacy/ceremony 0.1.2 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +196 -87
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -5,7 +5,7 @@ import { render } from "ink";
|
|
|
5
5
|
|
|
6
6
|
// src/components/App.tsx
|
|
7
7
|
import { useEffect as useEffect4, useState as useState4 } from "react";
|
|
8
|
-
import { Box as
|
|
8
|
+
import { Box as Box7, Text as Text7, useApp, useInput as useInput2 } from "ink";
|
|
9
9
|
|
|
10
10
|
// src/cleanup.ts
|
|
11
11
|
var pendingLeaveQueue = null;
|
|
@@ -33,7 +33,7 @@ import { createWriteStream } from "fs";
|
|
|
33
33
|
import { readFile, unlink } from "fs/promises";
|
|
34
34
|
import { pipeline } from "stream/promises";
|
|
35
35
|
import { Readable } from "stream";
|
|
36
|
-
var DEFAULT_API_URL = "
|
|
36
|
+
var DEFAULT_API_URL = "https://ceremony.api.umbraprivacy.com";
|
|
37
37
|
var BASE = (process.env["CEREMONY_API_URL"] ?? DEFAULT_API_URL).replace(/\/$/, "");
|
|
38
38
|
async function request(path, options = {}) {
|
|
39
39
|
const res = await fetch(`${BASE}${path}`, {
|
|
@@ -262,7 +262,7 @@ var STATUS_COLOR = {
|
|
|
262
262
|
function Header({ ceremony, subtitle }) {
|
|
263
263
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [
|
|
264
264
|
/* @__PURE__ */ jsxs(Box, { children: [
|
|
265
|
-
/* @__PURE__ */ jsx(Text, { bold: true, color: "cyan", children: "\u25C6
|
|
265
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color: "cyan", children: "\u25C6 Umbra Ceremony TUI" }),
|
|
266
266
|
ceremony && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
267
267
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " \xB7 " }),
|
|
268
268
|
/* @__PURE__ */ jsx(Text, { bold: true, children: ceremony.name }),
|
|
@@ -271,6 +271,9 @@ function Header({ ceremony, subtitle }) {
|
|
|
271
271
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "]" })
|
|
272
272
|
] })
|
|
273
273
|
] }),
|
|
274
|
+
/* @__PURE__ */ jsx(Text, { color: "cyan", children: "Phase 2 trusted-setup contribution \xB7 Groth16 / BN254" }),
|
|
275
|
+
/* @__PURE__ */ jsx(Text, { color: "gray", children: "You are adding fresh entropy to Umbra's circuit proving keys. The on-chain privacy of every deposit, claim and transfer holds as long as ONE contributor in this ceremony destroys their secret." }),
|
|
276
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "Press ? at any time for a full explanation of what is happening." }),
|
|
274
277
|
ceremony && /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
275
278
|
ceremony.total_tracks,
|
|
276
279
|
" circuit",
|
|
@@ -688,26 +691,56 @@ function Attestation({ contribution }) {
|
|
|
688
691
|
] });
|
|
689
692
|
}
|
|
690
693
|
|
|
691
|
-
// src/components/
|
|
694
|
+
// src/components/InfoModal.tsx
|
|
695
|
+
import { Box as Box6, Text as Text6 } from "ink";
|
|
692
696
|
import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
693
|
-
function
|
|
697
|
+
function InfoModal() {
|
|
698
|
+
return /* @__PURE__ */ jsx6(Box6, { flexDirection: "column", paddingX: 2, paddingY: 1, children: /* @__PURE__ */ jsxs6(
|
|
699
|
+
Box6,
|
|
700
|
+
{
|
|
701
|
+
flexDirection: "column",
|
|
702
|
+
borderStyle: "round",
|
|
703
|
+
borderColor: "cyan",
|
|
704
|
+
paddingX: 2,
|
|
705
|
+
paddingY: 1,
|
|
706
|
+
width: 84,
|
|
707
|
+
gap: 1,
|
|
708
|
+
children: [
|
|
709
|
+
/* @__PURE__ */ jsx6(Text6, { bold: true, color: "cyan", children: "Umbra Phase 2 Trusted-Setup Ceremony" }),
|
|
710
|
+
/* @__PURE__ */ jsx6(Text6, { children: "Umbra uses Groth16 zero-knowledge proofs to give Solana users on-chain privacy. Every circuit needs a one-time multi-party ceremony to generate its proving key safely \u2014 that is Phase 2. Each contributor adds their own secret entropy and destroys it afterward. The setup stays secure as long as AT LEAST ONE contributor erased theirs, which is why your single contribution genuinely matters." }),
|
|
711
|
+
/* @__PURE__ */ jsx6(Text6, { children: "What you will do: tap 20 keys to seed your entropy, download the latest challenge file, run snarkjs locally to combine your secret with the parameters, and upload the response. Your secret never leaves your machine. Erase it when you are done." }),
|
|
712
|
+
/* @__PURE__ */ jsx6(Text6, { dimColor: true, children: "Press B, Esc or ? to close" })
|
|
713
|
+
]
|
|
714
|
+
}
|
|
715
|
+
) });
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
// src/components/App.tsx
|
|
719
|
+
import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
720
|
+
var NAME_MAX_LEN = 100;
|
|
721
|
+
var NAME_VALID_RE = /^[\p{L}\p{N} _.\-]*$/u;
|
|
722
|
+
function App({ ceremonyId: initialCeremonyId, displayName: initialDisplayName }) {
|
|
694
723
|
const { exit } = useApp();
|
|
695
724
|
const [activeCeremonyId, setActiveCeremonyId] = useState4(initialCeremonyId);
|
|
725
|
+
const [displayName2, setDisplayName] = useState4(initialDisplayName ?? "anonymous");
|
|
726
|
+
const [nameSet, setNameSet] = useState4(initialDisplayName !== void 0);
|
|
696
727
|
const [screen, setScreen] = useState4(
|
|
697
|
-
initialCeremonyId ? { name: "loading" } : { name: "ceremony-picker", ceremonies: [], loading: true }
|
|
728
|
+
initialDisplayName === void 0 ? { name: "name-input", value: "" } : initialCeremonyId ? { name: "loading" } : { name: "ceremony-picker", ceremonies: [], loading: true }
|
|
698
729
|
);
|
|
699
730
|
const [ceremony, setCeremony] = useState4(null);
|
|
700
731
|
const [session, setSession] = useState4(null);
|
|
701
732
|
const [contributed, setContributed] = useState4({});
|
|
702
733
|
const [selectedIdx, setSelectedIdx] = useState4(0);
|
|
703
734
|
const [tab, setTab] = useState4(0);
|
|
735
|
+
const [showInfo, setShowInfo] = useState4(false);
|
|
704
736
|
useEffect4(() => {
|
|
737
|
+
if (!nameSet) return;
|
|
705
738
|
if (!initialCeremonyId) {
|
|
706
739
|
loadCeremonies();
|
|
707
740
|
} else {
|
|
708
741
|
boot(initialCeremonyId);
|
|
709
742
|
}
|
|
710
|
-
}, []);
|
|
743
|
+
}, [nameSet]);
|
|
711
744
|
async function loadCeremonies() {
|
|
712
745
|
try {
|
|
713
746
|
const { ceremonies } = await api.listCeremonies();
|
|
@@ -739,6 +772,7 @@ function App({ ceremonyId: initialCeremonyId, displayName: displayName2 = "anony
|
|
|
739
772
|
setScreen({ name: "error", message: "No tracks found in this ceremony.", recoverable: false });
|
|
740
773
|
return;
|
|
741
774
|
}
|
|
775
|
+
setSelectedIdx(0);
|
|
742
776
|
setScreen({ name: "tracks", tracks });
|
|
743
777
|
} catch (e) {
|
|
744
778
|
if (e.code === "INVALID_SESSION" || e.status === 401) {
|
|
@@ -751,6 +785,7 @@ function App({ ceremonyId: initialCeremonyId, displayName: displayName2 = "anony
|
|
|
751
785
|
setScreen({ name: "error", message: "No tracks found in this ceremony.", recoverable: false });
|
|
752
786
|
return;
|
|
753
787
|
}
|
|
788
|
+
setSelectedIdx(0);
|
|
754
789
|
setScreen({ name: "tracks", tracks });
|
|
755
790
|
} catch (e2) {
|
|
756
791
|
setScreen({ name: "error", message: e2.message ?? "Failed to load tracks.", recoverable: false });
|
|
@@ -760,6 +795,22 @@ function App({ ceremonyId: initialCeremonyId, displayName: displayName2 = "anony
|
|
|
760
795
|
setScreen({ name: "error", message: e.message ?? "Failed to load tracks.", recoverable: false });
|
|
761
796
|
}
|
|
762
797
|
}
|
|
798
|
+
function commitName(raw) {
|
|
799
|
+
const trimmed = raw.trim();
|
|
800
|
+
if (trimmed.length === 0) return;
|
|
801
|
+
setDisplayName(trimmed);
|
|
802
|
+
setNameSet(true);
|
|
803
|
+
setScreen(
|
|
804
|
+
initialCeremonyId ? { name: "loading" } : { name: "ceremony-picker", ceremonies: [], loading: true }
|
|
805
|
+
);
|
|
806
|
+
}
|
|
807
|
+
function randomAnonName() {
|
|
808
|
+
const hex = Array.from(
|
|
809
|
+
{ length: 6 },
|
|
810
|
+
() => Math.floor(Math.random() * 16).toString(16)
|
|
811
|
+
).join("");
|
|
812
|
+
return `anon-${hex}`;
|
|
813
|
+
}
|
|
763
814
|
async function joinTrack(track) {
|
|
764
815
|
if (!session) return;
|
|
765
816
|
setScreen({ name: "joining" });
|
|
@@ -795,6 +846,44 @@ function App({ ceremonyId: initialCeremonyId, displayName: displayName2 = "anony
|
|
|
795
846
|
}, [screen.name]);
|
|
796
847
|
useInput2((input, key) => {
|
|
797
848
|
const q = input.toLowerCase();
|
|
849
|
+
if (showInfo) {
|
|
850
|
+
if (key.escape || input === "?" || q === "b") {
|
|
851
|
+
setShowInfo(false);
|
|
852
|
+
return;
|
|
853
|
+
}
|
|
854
|
+
if (q === "q") {
|
|
855
|
+
exit();
|
|
856
|
+
return;
|
|
857
|
+
}
|
|
858
|
+
return;
|
|
859
|
+
}
|
|
860
|
+
if (input === "?" && screen.name !== "entropy") {
|
|
861
|
+
setShowInfo(true);
|
|
862
|
+
return;
|
|
863
|
+
}
|
|
864
|
+
if (screen.name === "name-input") {
|
|
865
|
+
if (key.escape) {
|
|
866
|
+
exit();
|
|
867
|
+
return;
|
|
868
|
+
}
|
|
869
|
+
if (key.tab) {
|
|
870
|
+
setScreen({ name: "name-input", value: randomAnonName() });
|
|
871
|
+
return;
|
|
872
|
+
}
|
|
873
|
+
if (key.return) {
|
|
874
|
+
commitName(screen.value);
|
|
875
|
+
return;
|
|
876
|
+
}
|
|
877
|
+
if (key.backspace || key.delete) {
|
|
878
|
+
setScreen({ name: "name-input", value: screen.value.slice(0, -1) });
|
|
879
|
+
return;
|
|
880
|
+
}
|
|
881
|
+
if (input && input.length === 1 && NAME_VALID_RE.test(input)) {
|
|
882
|
+
if (screen.value.length >= NAME_MAX_LEN) return;
|
|
883
|
+
setScreen({ name: "name-input", value: screen.value + input });
|
|
884
|
+
}
|
|
885
|
+
return;
|
|
886
|
+
}
|
|
798
887
|
if (q === "q" && screen.name !== "entropy") {
|
|
799
888
|
if (screen.name === "queue" && session) {
|
|
800
889
|
clearQueueCleanup();
|
|
@@ -866,32 +955,52 @@ function App({ ceremonyId: initialCeremonyId, displayName: displayName2 = "anony
|
|
|
866
955
|
goHome();
|
|
867
956
|
}
|
|
868
957
|
});
|
|
958
|
+
if (showInfo) {
|
|
959
|
+
return /* @__PURE__ */ jsx7(InfoModal, {});
|
|
960
|
+
}
|
|
961
|
+
if (screen.name === "name-input") {
|
|
962
|
+
const { value } = screen;
|
|
963
|
+
const canSubmit = value.trim().length > 0;
|
|
964
|
+
return /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
|
|
965
|
+
/* @__PURE__ */ jsx7(Header, { ceremony: null }),
|
|
966
|
+
/* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", marginTop: 1, gap: 1, children: [
|
|
967
|
+
/* @__PURE__ */ jsx7(Text7, { bold: true, children: "Who are you contributing as?" }),
|
|
968
|
+
/* @__PURE__ */ jsx7(Text7, { dimColor: true, children: "Your display name appears next to your contributions in the public transcript. Pick anything \u2014 your real name, a handle, or hit Tab for a random anonymous name." }),
|
|
969
|
+
/* @__PURE__ */ jsxs7(Box7, { children: [
|
|
970
|
+
/* @__PURE__ */ jsx7(Text7, { color: "cyan", children: " > " }),
|
|
971
|
+
/* @__PURE__ */ jsx7(Text7, { children: value }),
|
|
972
|
+
/* @__PURE__ */ jsx7(Text7, { color: "cyan", inverse: true, children: " " })
|
|
973
|
+
] }),
|
|
974
|
+
/* @__PURE__ */ jsx7(Text7, { dimColor: true, children: canSubmit ? "Enter to continue \xB7 Tab rerolls random name \xB7 \u232B backspace \xB7 Esc to quit" : "Type a name, or press Tab to suggest a random anonymous one \xB7 Esc to quit" })
|
|
975
|
+
] })
|
|
976
|
+
] });
|
|
977
|
+
}
|
|
869
978
|
if (screen.name === "ceremony-picker") {
|
|
870
979
|
const { ceremonies, loading } = screen;
|
|
871
|
-
return /* @__PURE__ */
|
|
872
|
-
/* @__PURE__ */
|
|
873
|
-
loading ? /* @__PURE__ */
|
|
874
|
-
/* @__PURE__ */
|
|
875
|
-
/* @__PURE__ */
|
|
876
|
-
/* @__PURE__ */
|
|
877
|
-
] }) : /* @__PURE__ */
|
|
878
|
-
/* @__PURE__ */
|
|
879
|
-
/* @__PURE__ */
|
|
980
|
+
return /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
|
|
981
|
+
/* @__PURE__ */ jsx7(Header, { ceremony: null }),
|
|
982
|
+
loading ? /* @__PURE__ */ jsx7(Text7, { dimColor: true, children: "Loading ceremonies..." }) : ceremonies.length === 0 ? /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", gap: 1, children: [
|
|
983
|
+
/* @__PURE__ */ jsx7(Text7, { color: "yellow", children: "No ceremonies found." }),
|
|
984
|
+
/* @__PURE__ */ jsx7(Text7, { dimColor: true, children: "The server may not have any active ceremonies yet." }),
|
|
985
|
+
/* @__PURE__ */ jsx7(Text7, { dimColor: true, children: "Q to quit" })
|
|
986
|
+
] }) : /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
|
|
987
|
+
/* @__PURE__ */ jsx7(Text7, { bold: true, children: "Select a ceremony:" }),
|
|
988
|
+
/* @__PURE__ */ jsx7(Text7, { dimColor: true, children: " " + "\u2500".repeat(60) }),
|
|
880
989
|
ceremonies.map((c, i) => {
|
|
881
990
|
const isSelected = i === selectedIdx;
|
|
882
991
|
const isOpen = c.status === "open";
|
|
883
992
|
const statusColor = c.status === "open" ? "green" : c.status === "completed" ? "cyan" : "yellow";
|
|
884
|
-
return /* @__PURE__ */
|
|
885
|
-
/* @__PURE__ */
|
|
993
|
+
return /* @__PURE__ */ jsxs7(Box7, { gap: 2, children: [
|
|
994
|
+
/* @__PURE__ */ jsxs7(Text7, { color: isSelected ? "cyan" : isOpen ? void 0 : "gray", children: [
|
|
886
995
|
isSelected ? "\u25B6 " : " ",
|
|
887
996
|
c.name.padEnd(30)
|
|
888
997
|
] }),
|
|
889
|
-
/* @__PURE__ */
|
|
998
|
+
/* @__PURE__ */ jsxs7(Text7, { color: statusColor, children: [
|
|
890
999
|
"[",
|
|
891
1000
|
c.status,
|
|
892
1001
|
"]"
|
|
893
1002
|
] }),
|
|
894
|
-
/* @__PURE__ */
|
|
1003
|
+
/* @__PURE__ */ jsxs7(Text7, { dimColor: true, children: [
|
|
895
1004
|
c.track_count,
|
|
896
1005
|
" track",
|
|
897
1006
|
c.track_count !== 1 ? "s" : "",
|
|
@@ -902,12 +1011,12 @@ function App({ ceremonyId: initialCeremonyId, displayName: displayName2 = "anony
|
|
|
902
1011
|
] })
|
|
903
1012
|
] }, c.id);
|
|
904
1013
|
}),
|
|
905
|
-
/* @__PURE__ */
|
|
1014
|
+
/* @__PURE__ */ jsx7(Text7, { dimColor: true, children: " " + "\u2500".repeat(60) }),
|
|
906
1015
|
(() => {
|
|
907
1016
|
const c = ceremonies[selectedIdx];
|
|
908
1017
|
if (!c) return null;
|
|
909
1018
|
if (c.status === "initialized") {
|
|
910
|
-
return /* @__PURE__ */
|
|
1019
|
+
return /* @__PURE__ */ jsxs7(Text7, { color: "yellow", children: [
|
|
911
1020
|
" Not open yet \u2014 admin: run initialize ",
|
|
912
1021
|
"<id>",
|
|
913
1022
|
" then open ",
|
|
@@ -916,115 +1025,115 @@ function App({ ceremonyId: initialCeremonyId, displayName: displayName2 = "anony
|
|
|
916
1025
|
] });
|
|
917
1026
|
}
|
|
918
1027
|
if (c.status === "finalizing") {
|
|
919
|
-
return /* @__PURE__ */
|
|
1028
|
+
return /* @__PURE__ */ jsx7(Text7, { color: "yellow", children: " Contribution phase is closed \u2014 ceremony is applying the final beacon." });
|
|
920
1029
|
}
|
|
921
1030
|
if (c.status === "completed") {
|
|
922
|
-
return /* @__PURE__ */
|
|
1031
|
+
return /* @__PURE__ */ jsx7(Text7, { color: "cyan", children: " Ceremony complete \u2014 verification keys are available." });
|
|
923
1032
|
}
|
|
924
|
-
return /* @__PURE__ */
|
|
1033
|
+
return /* @__PURE__ */ jsx7(Text7, { dimColor: true, children: "\u2191/\u2193 select \xB7 Enter join \xB7 Q quit" });
|
|
925
1034
|
})()
|
|
926
1035
|
] })
|
|
927
1036
|
] });
|
|
928
1037
|
}
|
|
929
1038
|
if (screen.name === "loading") {
|
|
930
|
-
return /* @__PURE__ */
|
|
931
|
-
/* @__PURE__ */
|
|
932
|
-
/* @__PURE__ */
|
|
1039
|
+
return /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
|
|
1040
|
+
/* @__PURE__ */ jsx7(Header, { ceremony }),
|
|
1041
|
+
/* @__PURE__ */ jsx7(Text7, { dimColor: true, children: "Loading tracks..." })
|
|
933
1042
|
] });
|
|
934
1043
|
}
|
|
935
1044
|
if (screen.name === "error") {
|
|
936
1045
|
const backHint = !initialCeremonyId ? "\u232B Backspace \u2014 back to ceremony list \xB7 Q to quit" : screen.recoverable ? "\u232B Backspace / B to go back \xB7 Q to quit" : "Q to quit";
|
|
937
|
-
return /* @__PURE__ */
|
|
938
|
-
/* @__PURE__ */
|
|
939
|
-
/* @__PURE__ */
|
|
1046
|
+
return /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
|
|
1047
|
+
/* @__PURE__ */ jsx7(Header, { ceremony }),
|
|
1048
|
+
/* @__PURE__ */ jsxs7(Text7, { color: "red", bold: true, children: [
|
|
940
1049
|
"\u2717 ",
|
|
941
1050
|
screen.message
|
|
942
1051
|
] }),
|
|
943
|
-
/* @__PURE__ */
|
|
1052
|
+
/* @__PURE__ */ jsx7(Text7, { dimColor: true, children: backHint })
|
|
944
1053
|
] });
|
|
945
1054
|
}
|
|
946
1055
|
if (screen.name === "tracks") {
|
|
947
1056
|
const { tracks } = screen;
|
|
948
1057
|
const openTracks = tracks.filter((t) => t.status === "open");
|
|
949
1058
|
const myContributions = Object.values(contributed).filter((c) => c.ceremonyId === activeCeremonyId);
|
|
950
|
-
const TabBar = () => /* @__PURE__ */
|
|
951
|
-
/* @__PURE__ */
|
|
952
|
-
/* @__PURE__ */
|
|
953
|
-
/* @__PURE__ */
|
|
954
|
-
/* @__PURE__ */
|
|
1059
|
+
const TabBar = () => /* @__PURE__ */ jsxs7(Box7, { gap: 1, marginBottom: 1, children: [
|
|
1060
|
+
/* @__PURE__ */ jsx7(Text7, { bold: tab === 0, color: tab === 0 ? "cyan" : void 0, dimColor: tab !== 0, children: tab === 0 ? "[ Dashboard ]" : " Dashboard " }),
|
|
1061
|
+
/* @__PURE__ */ jsx7(Text7, { dimColor: true, children: "|" }),
|
|
1062
|
+
/* @__PURE__ */ jsx7(Text7, { bold: tab === 1, color: tab === 1 ? "cyan" : void 0, dimColor: tab !== 1, children: tab === 1 ? `[ My Contributions (${myContributions.length}) ]` : ` My Contributions (${myContributions.length}) ` }),
|
|
1063
|
+
/* @__PURE__ */ jsx7(Text7, { dimColor: true, children: " Tab to switch" })
|
|
955
1064
|
] });
|
|
956
|
-
return /* @__PURE__ */
|
|
957
|
-
/* @__PURE__ */
|
|
958
|
-
/* @__PURE__ */
|
|
1065
|
+
return /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
|
|
1066
|
+
/* @__PURE__ */ jsx7(Header, { ceremony }),
|
|
1067
|
+
/* @__PURE__ */ jsx7(TabBar, {}),
|
|
959
1068
|
tab === 0 ? (
|
|
960
1069
|
// ── Dashboard tab ────────────────────────────────────────────────
|
|
961
|
-
/* @__PURE__ */
|
|
962
|
-
/* @__PURE__ */
|
|
1070
|
+
/* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
|
|
1071
|
+
/* @__PURE__ */ jsxs7(Text7, { dimColor: true, children: [
|
|
963
1072
|
" CIRCUIT".padEnd(30),
|
|
964
1073
|
"TOTAL".padEnd(10),
|
|
965
1074
|
"QUEUE".padEnd(8),
|
|
966
1075
|
"STATUS".padEnd(14),
|
|
967
1076
|
"MY CONTRIBUTIONS"
|
|
968
1077
|
] }),
|
|
969
|
-
/* @__PURE__ */
|
|
1078
|
+
/* @__PURE__ */ jsx7(Text7, { dimColor: true, children: " " + "\u2500".repeat(68) }),
|
|
970
1079
|
tracks.map((t, i) => {
|
|
971
1080
|
const isSelected = i === selectedIdx;
|
|
972
1081
|
const canContribute = t.status === "open";
|
|
973
1082
|
const nameClipped = t.circuit_name.length > 26 ? t.circuit_name.slice(0, 24) + ".." : t.circuit_name;
|
|
974
1083
|
const statusColor = t.status === "open" ? "green" : t.status === "finalized" ? "cyan" : "yellow";
|
|
975
1084
|
const myContrib = contributed[t.id];
|
|
976
|
-
return /* @__PURE__ */
|
|
977
|
-
/* @__PURE__ */
|
|
1085
|
+
return /* @__PURE__ */ jsxs7(Box7, { children: [
|
|
1086
|
+
/* @__PURE__ */ jsxs7(Text7, { color: isSelected ? "cyan" : canContribute ? void 0 : "gray", children: [
|
|
978
1087
|
isSelected ? "\u25B6 " : " ",
|
|
979
1088
|
nameClipped.padEnd(28),
|
|
980
1089
|
String(t.contribution_count).padEnd(10),
|
|
981
1090
|
String(t.queue_depth).padEnd(8)
|
|
982
1091
|
] }),
|
|
983
|
-
/* @__PURE__ */
|
|
984
|
-
myContrib ? isSelected ? /* @__PURE__ */
|
|
1092
|
+
/* @__PURE__ */ jsx7(Text7, { color: statusColor, children: t.status.padEnd(14) }),
|
|
1093
|
+
myContrib ? isSelected ? /* @__PURE__ */ jsxs7(Text7, { color: "green", children: [
|
|
985
1094
|
"\u2713 contributed (round #",
|
|
986
1095
|
myContrib.sequenceNumber,
|
|
987
1096
|
") \u2014 already done"
|
|
988
|
-
] }) : /* @__PURE__ */
|
|
1097
|
+
] }) : /* @__PURE__ */ jsxs7(Text7, { color: "green", children: [
|
|
989
1098
|
"\u2713 contributed (round #",
|
|
990
1099
|
myContrib.sequenceNumber,
|
|
991
1100
|
")"
|
|
992
|
-
] }) : canContribute ? isSelected ? /* @__PURE__ */
|
|
1101
|
+
] }) : canContribute ? isSelected ? /* @__PURE__ */ jsx7(Text7, { color: "yellow", children: "\u2190 Enter to contribute" }) : /* @__PURE__ */ jsx7(Text7, { dimColor: true, children: "not contributed" }) : /* @__PURE__ */ jsx7(Text7, { dimColor: true, children: "\u2014" })
|
|
993
1102
|
] }, t.id);
|
|
994
1103
|
}),
|
|
995
|
-
/* @__PURE__ */
|
|
996
|
-
openTracks.length === 0 ? /* @__PURE__ */
|
|
1104
|
+
/* @__PURE__ */ jsx7(Text7, { dimColor: true, children: " " + "\u2500".repeat(68) }),
|
|
1105
|
+
openTracks.length === 0 ? /* @__PURE__ */ jsx7(Text7, { color: "yellow", children: "No open tracks \u2014 ceremony may be finalizing or complete." }) : /* @__PURE__ */ jsxs7(Text7, { dimColor: true, children: [
|
|
997
1106
|
"\u2191/\u2193 select \xB7 Enter contribute \xB7 R refresh \xB7 Q quit",
|
|
998
1107
|
!initialCeremonyId ? " \xB7 \u232B back to ceremony list" : ""
|
|
999
1108
|
] })
|
|
1000
1109
|
] })
|
|
1001
1110
|
) : (
|
|
1002
1111
|
// ── My Contributions tab ─────────────────────────────────────────
|
|
1003
|
-
/* @__PURE__ */
|
|
1004
|
-
/* @__PURE__ */
|
|
1005
|
-
/* @__PURE__ */
|
|
1006
|
-
] }) : /* @__PURE__ */
|
|
1007
|
-
/* @__PURE__ */
|
|
1112
|
+
/* @__PURE__ */ jsx7(Box7, { flexDirection: "column", children: myContributions.length === 0 ? /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", gap: 1, children: [
|
|
1113
|
+
/* @__PURE__ */ jsx7(Text7, { dimColor: true, children: "No contributions yet." }),
|
|
1114
|
+
/* @__PURE__ */ jsx7(Text7, { dimColor: true, children: "Switch to Dashboard tab and press Enter on a circuit to contribute." })
|
|
1115
|
+
] }) : /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
|
|
1116
|
+
/* @__PURE__ */ jsxs7(Text7, { dimColor: true, children: [
|
|
1008
1117
|
" CIRCUIT".padEnd(28),
|
|
1009
1118
|
"ROUND".padEnd(8),
|
|
1010
1119
|
"HASH".padEnd(20),
|
|
1011
1120
|
"TIME"
|
|
1012
1121
|
] }),
|
|
1013
|
-
/* @__PURE__ */
|
|
1014
|
-
myContributions.map((c, i) => /* @__PURE__ */
|
|
1015
|
-
/* @__PURE__ */
|
|
1016
|
-
/* @__PURE__ */
|
|
1017
|
-
/* @__PURE__ */
|
|
1018
|
-
/* @__PURE__ */
|
|
1019
|
-
/* @__PURE__ */
|
|
1122
|
+
/* @__PURE__ */ jsx7(Text7, { dimColor: true, children: " " + "\u2500".repeat(68) }),
|
|
1123
|
+
myContributions.map((c, i) => /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
|
|
1124
|
+
/* @__PURE__ */ jsxs7(Box7, { children: [
|
|
1125
|
+
/* @__PURE__ */ jsx7(Text7, { color: "green", children: " \u2713 " }),
|
|
1126
|
+
/* @__PURE__ */ jsx7(Text7, { bold: true, children: c.circuitName.padEnd(24) }),
|
|
1127
|
+
/* @__PURE__ */ jsx7(Text7, { color: "yellow", children: "#" + c.sequenceNumber + " " }),
|
|
1128
|
+
/* @__PURE__ */ jsx7(Text7, { color: "cyan", children: c.contributionHash ? c.contributionHash.slice(0, 16) + "..." : "(pending)" })
|
|
1020
1129
|
] }),
|
|
1021
|
-
/* @__PURE__ */
|
|
1130
|
+
/* @__PURE__ */ jsxs7(Text7, { dimColor: true, children: [
|
|
1022
1131
|
" ",
|
|
1023
1132
|
c.verifiedAt ? new Date(c.verifiedAt).toLocaleString() : ""
|
|
1024
1133
|
] })
|
|
1025
1134
|
] }, i)),
|
|
1026
|
-
/* @__PURE__ */
|
|
1027
|
-
/* @__PURE__ */
|
|
1135
|
+
/* @__PURE__ */ jsx7(Text7, { dimColor: true, children: " " + "\u2500".repeat(68) }),
|
|
1136
|
+
/* @__PURE__ */ jsxs7(Text7, { dimColor: true, children: [
|
|
1028
1137
|
"Total: ",
|
|
1029
1138
|
myContributions.length,
|
|
1030
1139
|
" contribution",
|
|
@@ -1037,24 +1146,24 @@ function App({ ceremonyId: initialCeremonyId, displayName: displayName2 = "anony
|
|
|
1037
1146
|
] });
|
|
1038
1147
|
}
|
|
1039
1148
|
if (screen.name === "joining") {
|
|
1040
|
-
return /* @__PURE__ */
|
|
1041
|
-
/* @__PURE__ */
|
|
1042
|
-
/* @__PURE__ */
|
|
1149
|
+
return /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
|
|
1150
|
+
/* @__PURE__ */ jsx7(Header, { ceremony }),
|
|
1151
|
+
/* @__PURE__ */ jsx7(Text7, { dimColor: true, children: "Joining queue..." })
|
|
1043
1152
|
] });
|
|
1044
1153
|
}
|
|
1045
1154
|
if (screen.name === "queue") {
|
|
1046
1155
|
const { trackId, circuitName } = screen;
|
|
1047
1156
|
const priorContrib = contributed[trackId];
|
|
1048
|
-
return /* @__PURE__ */
|
|
1049
|
-
/* @__PURE__ */
|
|
1050
|
-
priorContrib && /* @__PURE__ */
|
|
1157
|
+
return /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
|
|
1158
|
+
/* @__PURE__ */ jsx7(Header, { ceremony, subtitle: `Circuit: ${circuitName}` }),
|
|
1159
|
+
priorContrib && /* @__PURE__ */ jsx7(Box7, { marginBottom: 1, paddingX: 1, children: /* @__PURE__ */ jsxs7(Text7, { color: "yellow", children: [
|
|
1051
1160
|
"\u26A0 You already contributed to this circuit (round #",
|
|
1052
1161
|
priorContrib.sequenceNumber,
|
|
1053
1162
|
").",
|
|
1054
1163
|
" ",
|
|
1055
1164
|
"Contributing again is allowed and adds more entropy."
|
|
1056
1165
|
] }) }),
|
|
1057
|
-
/* @__PURE__ */
|
|
1166
|
+
/* @__PURE__ */ jsx7(
|
|
1058
1167
|
QueueView,
|
|
1059
1168
|
{
|
|
1060
1169
|
ceremonyId: activeCeremonyId,
|
|
@@ -1064,14 +1173,14 @@ function App({ ceremonyId: initialCeremonyId, displayName: displayName2 = "anony
|
|
|
1064
1173
|
onError: (e) => setScreen({ name: "error", message: e.message, recoverable: true })
|
|
1065
1174
|
}
|
|
1066
1175
|
),
|
|
1067
|
-
/* @__PURE__ */
|
|
1176
|
+
/* @__PURE__ */ jsx7(Text7, { dimColor: true, children: "\u232B Backspace to go back \xB7 Q to quit" })
|
|
1068
1177
|
] });
|
|
1069
1178
|
}
|
|
1070
1179
|
if (screen.name === "entropy") {
|
|
1071
1180
|
const { trackId, circuitName, slotStatus } = screen;
|
|
1072
|
-
return /* @__PURE__ */
|
|
1073
|
-
/* @__PURE__ */
|
|
1074
|
-
/* @__PURE__ */
|
|
1181
|
+
return /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
|
|
1182
|
+
/* @__PURE__ */ jsx7(Header, { ceremony, subtitle: `Circuit: ${circuitName} \xB7 Your turn!` }),
|
|
1183
|
+
/* @__PURE__ */ jsx7(
|
|
1075
1184
|
EntropyCollector,
|
|
1076
1185
|
{
|
|
1077
1186
|
onComplete: (entropy) => setScreen({ name: "contribute", trackId, circuitName, slotStatus, entropy }),
|
|
@@ -1082,9 +1191,9 @@ function App({ ceremonyId: initialCeremonyId, displayName: displayName2 = "anony
|
|
|
1082
1191
|
}
|
|
1083
1192
|
if (screen.name === "contribute") {
|
|
1084
1193
|
const { trackId, circuitName, slotStatus, entropy } = screen;
|
|
1085
|
-
return /* @__PURE__ */
|
|
1086
|
-
/* @__PURE__ */
|
|
1087
|
-
/* @__PURE__ */
|
|
1194
|
+
return /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
|
|
1195
|
+
/* @__PURE__ */ jsx7(Header, { ceremony, subtitle: `Circuit: ${circuitName} \xB7 Contributing` }),
|
|
1196
|
+
/* @__PURE__ */ jsx7(
|
|
1088
1197
|
ContributeFlow,
|
|
1089
1198
|
{
|
|
1090
1199
|
ceremonyId: activeCeremonyId,
|
|
@@ -1113,19 +1222,19 @@ function App({ ceremonyId: initialCeremonyId, displayName: displayName2 = "anony
|
|
|
1113
1222
|
}
|
|
1114
1223
|
if (screen.name === "done") {
|
|
1115
1224
|
const { contribution } = screen;
|
|
1116
|
-
return /* @__PURE__ */
|
|
1117
|
-
/* @__PURE__ */
|
|
1118
|
-
/* @__PURE__ */
|
|
1119
|
-
/* @__PURE__ */
|
|
1225
|
+
return /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
|
|
1226
|
+
/* @__PURE__ */ jsx7(Header, { ceremony }),
|
|
1227
|
+
/* @__PURE__ */ jsx7(Attestation, { contribution }),
|
|
1228
|
+
/* @__PURE__ */ jsx7(Box7, { marginTop: 1, children: /* @__PURE__ */ jsx7(Text7, { dimColor: true, children: "\u232B Backspace / B = contribute to another circuit \xB7 Q to quit" }) })
|
|
1120
1229
|
] });
|
|
1121
1230
|
}
|
|
1122
1231
|
return null;
|
|
1123
1232
|
}
|
|
1124
1233
|
|
|
1125
1234
|
// src/index.tsx
|
|
1126
|
-
import { jsx as
|
|
1235
|
+
import { jsx as jsx8 } from "react/jsx-runtime";
|
|
1127
1236
|
var ceremonyId = process.env["CEREMONY_ID"] ?? "";
|
|
1128
|
-
var displayName = process.env["CONTRIBUTOR_NAME"]
|
|
1237
|
+
var displayName = process.env["CONTRIBUTOR_NAME"];
|
|
1129
1238
|
process.stdout.write("\x1B[?1049h\x1B[H");
|
|
1130
1239
|
function restoreScreen() {
|
|
1131
1240
|
process.stdout.write("\x1B[?1049l");
|
|
@@ -1148,7 +1257,7 @@ process.on("SIGTERM", () => {
|
|
|
1148
1257
|
});
|
|
1149
1258
|
});
|
|
1150
1259
|
var { waitUntilExit } = render(
|
|
1151
|
-
/* @__PURE__ */
|
|
1260
|
+
/* @__PURE__ */ jsx8(App, { ceremonyId, displayName }),
|
|
1152
1261
|
{ exitOnCtrlC: false }
|
|
1153
1262
|
);
|
|
1154
1263
|
await waitUntilExit();
|