@umbra-privacy/ceremony 0.2.3 → 0.2.5
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 +137 -75
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -90,26 +90,20 @@ var api = {
|
|
|
90
90
|
},
|
|
91
91
|
// Slot polling
|
|
92
92
|
myTurn(ceremonyId2, trackId, token) {
|
|
93
|
-
return request(
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
);
|
|
93
|
+
return request(`/api/ceremonies/${ceremonyId2}/tracks/${trackId}/my-turn`, {
|
|
94
|
+
headers: bearer(token)
|
|
95
|
+
});
|
|
97
96
|
},
|
|
98
97
|
// Contribution
|
|
99
98
|
signalUploaded(ceremonyId2, trackId, contributionId, token) {
|
|
100
|
-
return request(
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
body: JSON.stringify({ contribution_id: contributionId })
|
|
106
|
-
}
|
|
107
|
-
);
|
|
99
|
+
return request(`/api/ceremonies/${ceremonyId2}/tracks/${trackId}/signal-uploaded`, {
|
|
100
|
+
method: "POST",
|
|
101
|
+
headers: bearer(token),
|
|
102
|
+
body: JSON.stringify({ contribution_id: contributionId })
|
|
103
|
+
});
|
|
108
104
|
},
|
|
109
105
|
getReceipt(ceremonyId2, contributionId) {
|
|
110
|
-
return request(
|
|
111
|
-
`/api/ceremonies/${ceremonyId2}/contributions/${contributionId}/receipt`
|
|
112
|
-
);
|
|
106
|
+
return request(`/api/ceremonies/${ceremonyId2}/contributions/${contributionId}/receipt`);
|
|
113
107
|
},
|
|
114
108
|
// Admin — signed-request flow. Caller supplies the 64-byte Solana keypair
|
|
115
109
|
// bytes (32 secret + 32 public). The helper fetches a one-time challenge,
|
|
@@ -252,6 +246,38 @@ async function recordContribution(trackId, contribution) {
|
|
|
252
246
|
|
|
253
247
|
// src/components/Header.tsx
|
|
254
248
|
import { Box, Text } from "ink";
|
|
249
|
+
|
|
250
|
+
// src/labels.ts
|
|
251
|
+
function ceremonyStatusLabel(status) {
|
|
252
|
+
switch (status) {
|
|
253
|
+
case "open":
|
|
254
|
+
return "open";
|
|
255
|
+
case "initialized":
|
|
256
|
+
return "not yet open";
|
|
257
|
+
case "finalizing":
|
|
258
|
+
return "closing";
|
|
259
|
+
case "completed":
|
|
260
|
+
return "complete";
|
|
261
|
+
default:
|
|
262
|
+
return status;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
function trackStatusLabel(status) {
|
|
266
|
+
switch (status) {
|
|
267
|
+
case "open":
|
|
268
|
+
return "open";
|
|
269
|
+
case "initializing":
|
|
270
|
+
return "preparing";
|
|
271
|
+
case "awaiting_beacon":
|
|
272
|
+
return "awaiting beacon";
|
|
273
|
+
case "finalized":
|
|
274
|
+
return "complete";
|
|
275
|
+
default:
|
|
276
|
+
return status;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// src/components/Header.tsx
|
|
255
281
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
256
282
|
var STATUS_COLOR = {
|
|
257
283
|
open: "green",
|
|
@@ -264,10 +290,10 @@ function Header({ ceremony, subtitle }) {
|
|
|
264
290
|
/* @__PURE__ */ jsxs(Box, { children: [
|
|
265
291
|
/* @__PURE__ */ jsx(Text, { bold: true, color: "cyan", children: "\u25C6 Umbra Ceremony TUI" }),
|
|
266
292
|
ceremony && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
267
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "
|
|
293
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " \xB7 " }),
|
|
268
294
|
/* @__PURE__ */ jsx(Text, { bold: true, children: ceremony.name }),
|
|
269
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "
|
|
270
|
-
/* @__PURE__ */ jsx(Text, { color: STATUS_COLOR[ceremony.status] ?? "white", children: ceremony.status }),
|
|
295
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " [" }),
|
|
296
|
+
/* @__PURE__ */ jsx(Text, { color: STATUS_COLOR[ceremony.status] ?? "white", children: ceremonyStatusLabel(ceremony.status) }),
|
|
271
297
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "]" })
|
|
272
298
|
] })
|
|
273
299
|
] }),
|
|
@@ -342,7 +368,10 @@ function QueueView({ ceremonyId: ceremonyId2, trackId, token, onReady, onError }
|
|
|
342
368
|
] });
|
|
343
369
|
}
|
|
344
370
|
const waitMins = Math.ceil((status.estimated_wait_secs ?? 0) / 60);
|
|
345
|
-
const expiresAt = status.slot_expires_at ? new Date(status.slot_expires_at).toLocaleTimeString([], {
|
|
371
|
+
const expiresAt = status.slot_expires_at ? new Date(status.slot_expires_at).toLocaleTimeString([], {
|
|
372
|
+
hour: "2-digit",
|
|
373
|
+
minute: "2-digit"
|
|
374
|
+
}) : null;
|
|
346
375
|
const fastPoll = status.queue_position <= 2;
|
|
347
376
|
return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", gap: 1, children: [
|
|
348
377
|
/* @__PURE__ */ jsxs2(Box2, { gap: 2, children: [
|
|
@@ -372,11 +401,7 @@ function QueueView({ ceremonyId: ceremonyId2, trackId, token, onReady, onError }
|
|
|
372
401
|
] }) }) : status.queue_position > 1 ? (
|
|
373
402
|
// Slot is idle but people are ahead — they joined and left without releasing.
|
|
374
403
|
// timeout_watchdog will clear each stale slot after contribution_timeout_secs.
|
|
375
|
-
/* @__PURE__ */
|
|
376
|
-
"Slot is idle \u2014 waiting for positions ahead to respond or time out",
|
|
377
|
-
" ",
|
|
378
|
-
"(up to ~5 min each)"
|
|
379
|
-
] })
|
|
404
|
+
/* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Slot is idle \u2014 waiting for positions ahead to respond or time out (up to ~5 min each)" })
|
|
380
405
|
) : (
|
|
381
406
|
// Position 1, slot idle — advance_queue should fire shortly.
|
|
382
407
|
/* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Slot is idle \u2014 your turn is being prepared..." })
|
|
@@ -460,7 +485,7 @@ function EntropyCollector({ onComplete, onError }) {
|
|
|
460
485
|
/* @__PURE__ */ jsx3(Text3, { bold: true, children: "Type anything to generate entropy:" }),
|
|
461
486
|
/* @__PURE__ */ jsx3(Text3, { dimColor: true, children: "Keystroke timing (nanosecond intervals) is the randomness source." }),
|
|
462
487
|
/* @__PURE__ */ jsxs3(Box3, { marginTop: 1, children: [
|
|
463
|
-
/* @__PURE__ */ jsx3(Text3, { dimColor: true, children: "
|
|
488
|
+
/* @__PURE__ */ jsx3(Text3, { dimColor: true, children: " > " }),
|
|
464
489
|
/* @__PURE__ */ jsx3(Text3, { color: "green", children: stars }),
|
|
465
490
|
/* @__PURE__ */ jsx3(Text3, { color: "yellow", children: "\u2588" })
|
|
466
491
|
] }),
|
|
@@ -475,7 +500,7 @@ function EntropyCollector({ onComplete, onError }) {
|
|
|
475
500
|
/* @__PURE__ */ jsxs3(Text3, { dimColor: true, children: [
|
|
476
501
|
"/",
|
|
477
502
|
TARGET,
|
|
478
|
-
" keystrokes
|
|
503
|
+
" keystrokes (",
|
|
479
504
|
pct,
|
|
480
505
|
"%)"
|
|
481
506
|
] })
|
|
@@ -572,9 +597,11 @@ function ContributeFlow(props) {
|
|
|
572
597
|
await api.signalUploaded(ceremonyId2, trackId, slotStatus.contribution_id, token);
|
|
573
598
|
if (cancelled) return;
|
|
574
599
|
setStep({ name: "verifying", attempt: 1 });
|
|
600
|
+
const TOTAL_POLLS = 80;
|
|
601
|
+
const FAST_POLLS = 20;
|
|
575
602
|
let receipt = null;
|
|
576
603
|
let lastErr = null;
|
|
577
|
-
for (let i = 0; i <
|
|
604
|
+
for (let i = 0; i < TOTAL_POLLS; i++) {
|
|
578
605
|
if (cancelled) return;
|
|
579
606
|
setStep({ name: "verifying", attempt: i + 1 });
|
|
580
607
|
try {
|
|
@@ -583,7 +610,8 @@ function ContributeFlow(props) {
|
|
|
583
610
|
break;
|
|
584
611
|
} catch (err) {
|
|
585
612
|
lastErr = err instanceof Error ? err : new Error(String(err));
|
|
586
|
-
|
|
613
|
+
const delay = i < FAST_POLLS ? 3e3 : 1e4;
|
|
614
|
+
await new Promise((r) => setTimeout(r, delay));
|
|
587
615
|
}
|
|
588
616
|
}
|
|
589
617
|
if (cancelled) return;
|
|
@@ -618,7 +646,8 @@ function ContributeFlow(props) {
|
|
|
618
646
|
const filled = Math.round(pct / 5);
|
|
619
647
|
const bar = "\u2588".repeat(filled) + "\u2591".repeat(20 - filled);
|
|
620
648
|
detail = /* @__PURE__ */ jsxs4(Text4, { dimColor: true, children: [
|
|
621
|
-
"
|
|
649
|
+
" ",
|
|
650
|
+
"[",
|
|
622
651
|
bar,
|
|
623
652
|
"] ",
|
|
624
653
|
pct,
|
|
@@ -626,10 +655,15 @@ function ContributeFlow(props) {
|
|
|
626
655
|
] });
|
|
627
656
|
}
|
|
628
657
|
if (isActive && step.name === "verifying") {
|
|
658
|
+
const elapsed = step.attempt <= 20 ? step.attempt * 3 : 20 * 3 + (step.attempt - 20) * 10;
|
|
659
|
+
const mins = Math.floor(elapsed / 60);
|
|
660
|
+
const secs = elapsed % 60;
|
|
661
|
+
const time = mins > 0 ? `${mins}m ${secs.toString().padStart(2, "0")}s` : `${secs}s`;
|
|
629
662
|
detail = /* @__PURE__ */ jsxs4(Text4, { dimColor: true, children: [
|
|
630
|
-
"
|
|
631
|
-
|
|
632
|
-
|
|
663
|
+
" ",
|
|
664
|
+
"worker verifying \u2014 large circuits can take a few minutes (",
|
|
665
|
+
time,
|
|
666
|
+
" elapsed)"
|
|
633
667
|
] });
|
|
634
668
|
}
|
|
635
669
|
return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", children: [
|
|
@@ -662,25 +696,25 @@ function Attestation({ contribution }) {
|
|
|
662
696
|
const hashShort = contribution.contributionHash ? `${contribution.contributionHash.slice(0, 16)}...${contribution.contributionHash.slice(-8)}` : "(pending verification)";
|
|
663
697
|
const verifiedAt = contribution.verifiedAt ? new Date(contribution.verifiedAt).toLocaleString() : null;
|
|
664
698
|
return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", gap: 1, children: [
|
|
665
|
-
/* @__PURE__ */ jsx5(Text5, { bold: true, color: "green", children: "\u2713
|
|
699
|
+
/* @__PURE__ */ jsx5(Text5, { bold: true, color: "green", children: "\u2713 Contribution verified!" }),
|
|
666
700
|
/* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", gap: 0, children: [
|
|
667
701
|
/* @__PURE__ */ jsxs5(Box5, { gap: 2, children: [
|
|
668
702
|
/* @__PURE__ */ jsx5(Text5, { dimColor: true, children: "Circuit" }),
|
|
669
703
|
/* @__PURE__ */ jsx5(Text5, { bold: true, children: contribution.circuitName })
|
|
670
704
|
] }),
|
|
671
705
|
/* @__PURE__ */ jsxs5(Box5, { gap: 2, children: [
|
|
672
|
-
/* @__PURE__ */ jsx5(Text5, { dimColor: true, children: "Round
|
|
706
|
+
/* @__PURE__ */ jsx5(Text5, { dimColor: true, children: "Round " }),
|
|
673
707
|
/* @__PURE__ */ jsxs5(Text5, { bold: true, children: [
|
|
674
708
|
"#",
|
|
675
709
|
contribution.sequenceNumber
|
|
676
710
|
] })
|
|
677
711
|
] }),
|
|
678
712
|
/* @__PURE__ */ jsxs5(Box5, { gap: 2, children: [
|
|
679
|
-
/* @__PURE__ */ jsx5(Text5, { dimColor: true, children: "Hash
|
|
713
|
+
/* @__PURE__ */ jsx5(Text5, { dimColor: true, children: "Hash " }),
|
|
680
714
|
/* @__PURE__ */ jsx5(Text5, { color: "cyan", children: hashShort })
|
|
681
715
|
] }),
|
|
682
716
|
verifiedAt && /* @__PURE__ */ jsxs5(Box5, { gap: 2, children: [
|
|
683
|
-
/* @__PURE__ */ jsx5(Text5, { dimColor: true, children: "Time
|
|
717
|
+
/* @__PURE__ */ jsx5(Text5, { dimColor: true, children: "Time " }),
|
|
684
718
|
/* @__PURE__ */ jsx5(Text5, { dimColor: true, children: verifiedAt })
|
|
685
719
|
] })
|
|
686
720
|
] }),
|
|
@@ -747,7 +781,11 @@ function App({ ceremonyId: initialCeremonyId, displayName: initialDisplayName })
|
|
|
747
781
|
setScreen({ name: "ceremony-picker", ceremonies, loading: false });
|
|
748
782
|
setSelectedIdx(0);
|
|
749
783
|
} catch (e) {
|
|
750
|
-
setScreen({
|
|
784
|
+
setScreen({
|
|
785
|
+
name: "error",
|
|
786
|
+
message: e.message ?? "Failed to load ceremonies.",
|
|
787
|
+
recoverable: false
|
|
788
|
+
});
|
|
751
789
|
}
|
|
752
790
|
}
|
|
753
791
|
async function boot(cId) {
|
|
@@ -769,7 +807,11 @@ function App({ ceremonyId: initialCeremonyId, displayName: initialDisplayName })
|
|
|
769
807
|
try {
|
|
770
808
|
const { tracks } = await api.listTracks(cId, s.session_token);
|
|
771
809
|
if (tracks.length === 0) {
|
|
772
|
-
setScreen({
|
|
810
|
+
setScreen({
|
|
811
|
+
name: "error",
|
|
812
|
+
message: "No tracks found in this ceremony.",
|
|
813
|
+
recoverable: false
|
|
814
|
+
});
|
|
773
815
|
return;
|
|
774
816
|
}
|
|
775
817
|
setSelectedIdx(0);
|
|
@@ -782,17 +824,29 @@ function App({ ceremonyId: initialCeremonyId, displayName: initialDisplayName })
|
|
|
782
824
|
setSession(fresh);
|
|
783
825
|
const { tracks } = await api.listTracks(cId, fresh.session_token);
|
|
784
826
|
if (tracks.length === 0) {
|
|
785
|
-
setScreen({
|
|
827
|
+
setScreen({
|
|
828
|
+
name: "error",
|
|
829
|
+
message: "No tracks found in this ceremony.",
|
|
830
|
+
recoverable: false
|
|
831
|
+
});
|
|
786
832
|
return;
|
|
787
833
|
}
|
|
788
834
|
setSelectedIdx(0);
|
|
789
835
|
setScreen({ name: "tracks", tracks });
|
|
790
836
|
} catch (e2) {
|
|
791
|
-
setScreen({
|
|
837
|
+
setScreen({
|
|
838
|
+
name: "error",
|
|
839
|
+
message: e2.message ?? "Failed to load tracks.",
|
|
840
|
+
recoverable: false
|
|
841
|
+
});
|
|
792
842
|
}
|
|
793
843
|
return;
|
|
794
844
|
}
|
|
795
|
-
setScreen({
|
|
845
|
+
setScreen({
|
|
846
|
+
name: "error",
|
|
847
|
+
message: e.message ?? "Failed to load tracks.",
|
|
848
|
+
recoverable: false
|
|
849
|
+
});
|
|
796
850
|
}
|
|
797
851
|
}
|
|
798
852
|
function commitName(raw) {
|
|
@@ -805,10 +859,9 @@ function App({ ceremonyId: initialCeremonyId, displayName: initialDisplayName })
|
|
|
805
859
|
);
|
|
806
860
|
}
|
|
807
861
|
function randomAnonName() {
|
|
808
|
-
const hex = Array.from(
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
).join("");
|
|
862
|
+
const hex = Array.from({ length: 6 }, () => Math.floor(Math.random() * 16).toString(16)).join(
|
|
863
|
+
""
|
|
864
|
+
);
|
|
812
865
|
return `anon-${hex}`;
|
|
813
866
|
}
|
|
814
867
|
async function joinTrack(track) {
|
|
@@ -818,7 +871,11 @@ function App({ ceremonyId: initialCeremonyId, displayName: initialDisplayName })
|
|
|
818
871
|
await api.joinQueue(activeCeremonyId, track.id, session.session_token);
|
|
819
872
|
} catch (e) {
|
|
820
873
|
if (e.code !== "ALREADY_IN_QUEUE") {
|
|
821
|
-
setScreen({
|
|
874
|
+
setScreen({
|
|
875
|
+
name: "error",
|
|
876
|
+
message: e.message ?? "Failed to join queue.",
|
|
877
|
+
recoverable: true
|
|
878
|
+
});
|
|
822
879
|
return;
|
|
823
880
|
}
|
|
824
881
|
}
|
|
@@ -990,6 +1047,7 @@ function App({ ceremonyId: initialCeremonyId, displayName: initialDisplayName })
|
|
|
990
1047
|
const isSelected = i === selectedIdx;
|
|
991
1048
|
const isOpen = c.status === "open";
|
|
992
1049
|
const statusColor = c.status === "open" ? "green" : c.status === "completed" ? "cyan" : "yellow";
|
|
1050
|
+
const statusLabel = ceremonyStatusLabel(c.status);
|
|
993
1051
|
return /* @__PURE__ */ jsxs7(Box7, { gap: 2, children: [
|
|
994
1052
|
/* @__PURE__ */ jsxs7(Text7, { color: isSelected ? "cyan" : isOpen ? void 0 : "gray", children: [
|
|
995
1053
|
isSelected ? "\u25B6 " : " ",
|
|
@@ -997,7 +1055,7 @@ function App({ ceremonyId: initialCeremonyId, displayName: initialDisplayName })
|
|
|
997
1055
|
] }),
|
|
998
1056
|
/* @__PURE__ */ jsxs7(Text7, { color: statusColor, children: [
|
|
999
1057
|
"[",
|
|
1000
|
-
|
|
1058
|
+
statusLabel,
|
|
1001
1059
|
"]"
|
|
1002
1060
|
] }),
|
|
1003
1061
|
/* @__PURE__ */ jsxs7(Text7, { dimColor: true, children: [
|
|
@@ -1017,20 +1075,23 @@ function App({ ceremonyId: initialCeremonyId, displayName: initialDisplayName })
|
|
|
1017
1075
|
if (!c) return null;
|
|
1018
1076
|
if (c.status === "initialized") {
|
|
1019
1077
|
return /* @__PURE__ */ jsxs7(Text7, { color: "yellow", children: [
|
|
1020
|
-
"
|
|
1021
|
-
"
|
|
1022
|
-
" then open ",
|
|
1023
|
-
"<id>",
|
|
1024
|
-
" to start contributions."
|
|
1078
|
+
" ",
|
|
1079
|
+
"This ceremony is not yet open for contributions. The Umbra team is still preparing the circuits \u2014 please check back shortly."
|
|
1025
1080
|
] });
|
|
1026
1081
|
}
|
|
1027
1082
|
if (c.status === "finalizing") {
|
|
1028
|
-
return /* @__PURE__ */
|
|
1083
|
+
return /* @__PURE__ */ jsxs7(Text7, { color: "yellow", children: [
|
|
1084
|
+
" ",
|
|
1085
|
+
"Contributions are closed. The ceremony is computing the final verification key \u2014 no further contributions can be added."
|
|
1086
|
+
] });
|
|
1029
1087
|
}
|
|
1030
1088
|
if (c.status === "completed") {
|
|
1031
|
-
return /* @__PURE__ */
|
|
1089
|
+
return /* @__PURE__ */ jsxs7(Text7, { color: "cyan", children: [
|
|
1090
|
+
" ",
|
|
1091
|
+
"Ceremony complete. The verification keys are finalised \u2014 thank you to everyone who contributed."
|
|
1092
|
+
] });
|
|
1032
1093
|
}
|
|
1033
|
-
return /* @__PURE__ */ jsx7(Text7, { dimColor: true, children: "\u2191/\u2193 select
|
|
1094
|
+
return /* @__PURE__ */ jsx7(Text7, { dimColor: true, children: "\u2191/\u2193 select \xB7 Enter join \xB7 Q quit" });
|
|
1034
1095
|
})()
|
|
1035
1096
|
] })
|
|
1036
1097
|
] });
|
|
@@ -1046,7 +1107,7 @@ function App({ ceremonyId: initialCeremonyId, displayName: initialDisplayName })
|
|
|
1046
1107
|
return /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
|
|
1047
1108
|
/* @__PURE__ */ jsx7(Header, { ceremony }),
|
|
1048
1109
|
/* @__PURE__ */ jsxs7(Text7, { color: "red", bold: true, children: [
|
|
1049
|
-
"\u2717
|
|
1110
|
+
"\u2717 ",
|
|
1050
1111
|
screen.message
|
|
1051
1112
|
] }),
|
|
1052
1113
|
/* @__PURE__ */ jsx7(Text7, { dimColor: true, children: backHint })
|
|
@@ -1055,12 +1116,14 @@ function App({ ceremonyId: initialCeremonyId, displayName: initialDisplayName })
|
|
|
1055
1116
|
if (screen.name === "tracks") {
|
|
1056
1117
|
const { tracks } = screen;
|
|
1057
1118
|
const openTracks = tracks.filter((t) => t.status === "open");
|
|
1058
|
-
const myContributions = Object.values(contributed).filter(
|
|
1119
|
+
const myContributions = Object.values(contributed).filter(
|
|
1120
|
+
(c) => c.ceremonyId === activeCeremonyId
|
|
1121
|
+
);
|
|
1059
1122
|
const TabBar = () => /* @__PURE__ */ jsxs7(Box7, { gap: 1, marginBottom: 1, children: [
|
|
1060
1123
|
/* @__PURE__ */ jsx7(Text7, { bold: tab === 0, color: tab === 0 ? "cyan" : void 0, dimColor: tab !== 0, children: tab === 0 ? "[ Dashboard ]" : " Dashboard " }),
|
|
1061
1124
|
/* @__PURE__ */ jsx7(Text7, { dimColor: true, children: "|" }),
|
|
1062
1125
|
/* @__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: "
|
|
1126
|
+
/* @__PURE__ */ jsx7(Text7, { dimColor: true, children: " Tab to switch" })
|
|
1064
1127
|
] });
|
|
1065
1128
|
return /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
|
|
1066
1129
|
/* @__PURE__ */ jsx7(Header, { ceremony }),
|
|
@@ -1072,10 +1135,10 @@ function App({ ceremonyId: initialCeremonyId, displayName: initialDisplayName })
|
|
|
1072
1135
|
" CIRCUIT".padEnd(30),
|
|
1073
1136
|
"TOTAL".padEnd(10),
|
|
1074
1137
|
"QUEUE".padEnd(8),
|
|
1075
|
-
"STATUS".padEnd(
|
|
1138
|
+
"STATUS".padEnd(16),
|
|
1076
1139
|
"MY CONTRIBUTIONS"
|
|
1077
1140
|
] }),
|
|
1078
|
-
/* @__PURE__ */ jsx7(Text7, { dimColor: true, children: " " + "\u2500".repeat(
|
|
1141
|
+
/* @__PURE__ */ jsx7(Text7, { dimColor: true, children: " " + "\u2500".repeat(70) }),
|
|
1079
1142
|
tracks.map((t, i) => {
|
|
1080
1143
|
const isSelected = i === selectedIdx;
|
|
1081
1144
|
const canContribute = t.status === "open";
|
|
@@ -1089,21 +1152,21 @@ function App({ ceremonyId: initialCeremonyId, displayName: initialDisplayName })
|
|
|
1089
1152
|
String(t.contribution_count).padEnd(10),
|
|
1090
1153
|
String(t.queue_depth).padEnd(8)
|
|
1091
1154
|
] }),
|
|
1092
|
-
/* @__PURE__ */ jsx7(Text7, { color: statusColor, children: t.status.padEnd(
|
|
1155
|
+
/* @__PURE__ */ jsx7(Text7, { color: statusColor, children: trackStatusLabel(t.status).padEnd(16) }),
|
|
1093
1156
|
myContrib ? isSelected ? /* @__PURE__ */ jsxs7(Text7, { color: "green", children: [
|
|
1094
1157
|
"\u2713 contributed (round #",
|
|
1095
1158
|
myContrib.sequenceNumber,
|
|
1096
|
-
")
|
|
1159
|
+
") \u2014 already done"
|
|
1097
1160
|
] }) : /* @__PURE__ */ jsxs7(Text7, { color: "green", children: [
|
|
1098
|
-
"\u2713 contributed
|
|
1161
|
+
"\u2713 contributed (round #",
|
|
1099
1162
|
myContrib.sequenceNumber,
|
|
1100
1163
|
")"
|
|
1101
1164
|
] }) : 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" })
|
|
1102
1165
|
] }, t.id);
|
|
1103
1166
|
}),
|
|
1104
|
-
/* @__PURE__ */ jsx7(Text7, { dimColor: true, children: " " + "\u2500".repeat(
|
|
1105
|
-
openTracks.length === 0 ? /* @__PURE__ */ jsx7(Text7, { color: "yellow", children: "No open
|
|
1106
|
-
"\u2191/\u2193 select
|
|
1167
|
+
/* @__PURE__ */ jsx7(Text7, { dimColor: true, children: " " + "\u2500".repeat(70) }),
|
|
1168
|
+
openTracks.length === 0 ? /* @__PURE__ */ jsx7(Text7, { color: "yellow", children: "No circuits are open for contributions right now \u2014 the ceremony may be closing or already complete." }) : /* @__PURE__ */ jsxs7(Text7, { dimColor: true, children: [
|
|
1169
|
+
"\u2191/\u2193 select \xB7 Enter contribute \xB7 R refresh \xB7 Q quit",
|
|
1107
1170
|
!initialCeremonyId ? " \xB7 \u232B back to ceremony list" : ""
|
|
1108
1171
|
] })
|
|
1109
1172
|
] })
|
|
@@ -1122,7 +1185,7 @@ function App({ ceremonyId: initialCeremonyId, displayName: initialDisplayName })
|
|
|
1122
1185
|
/* @__PURE__ */ jsx7(Text7, { dimColor: true, children: " " + "\u2500".repeat(68) }),
|
|
1123
1186
|
myContributions.map((c, i) => /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
|
|
1124
1187
|
/* @__PURE__ */ jsxs7(Box7, { children: [
|
|
1125
|
-
/* @__PURE__ */ jsx7(Text7, { color: "green", children: "
|
|
1188
|
+
/* @__PURE__ */ jsx7(Text7, { color: "green", children: " \u2713 " }),
|
|
1126
1189
|
/* @__PURE__ */ jsx7(Text7, { bold: true, children: c.circuitName.padEnd(24) }),
|
|
1127
1190
|
/* @__PURE__ */ jsx7(Text7, { color: "yellow", children: "#" + c.sequenceNumber + " " }),
|
|
1128
1191
|
/* @__PURE__ */ jsx7(Text7, { color: "cyan", children: c.contributionHash ? c.contributionHash.slice(0, 16) + "..." : "(pending)" })
|
|
@@ -1139,7 +1202,7 @@ function App({ ceremonyId: initialCeremonyId, displayName: initialDisplayName })
|
|
|
1139
1202
|
" contribution",
|
|
1140
1203
|
myContributions.length !== 1 ? "s" : "",
|
|
1141
1204
|
" \xB7 ",
|
|
1142
|
-
"Tab to switch
|
|
1205
|
+
"Tab to switch \xB7 Q to quit"
|
|
1143
1206
|
] })
|
|
1144
1207
|
] }) })
|
|
1145
1208
|
)
|
|
@@ -1157,7 +1220,7 @@ function App({ ceremonyId: initialCeremonyId, displayName: initialDisplayName })
|
|
|
1157
1220
|
return /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
|
|
1158
1221
|
/* @__PURE__ */ jsx7(Header, { ceremony, subtitle: `Circuit: ${circuitName}` }),
|
|
1159
1222
|
priorContrib && /* @__PURE__ */ jsx7(Box7, { marginBottom: 1, paddingX: 1, children: /* @__PURE__ */ jsxs7(Text7, { color: "yellow", children: [
|
|
1160
|
-
"\u26A0
|
|
1223
|
+
"\u26A0 You already contributed to this circuit (round #",
|
|
1161
1224
|
priorContrib.sequenceNumber,
|
|
1162
1225
|
").",
|
|
1163
1226
|
" ",
|
|
@@ -1173,7 +1236,7 @@ function App({ ceremonyId: initialCeremonyId, displayName: initialDisplayName })
|
|
|
1173
1236
|
onError: (e) => setScreen({ name: "error", message: e.message, recoverable: true })
|
|
1174
1237
|
}
|
|
1175
1238
|
),
|
|
1176
|
-
/* @__PURE__ */ jsx7(Text7, { dimColor: true, children: "\u232B Backspace to go back
|
|
1239
|
+
/* @__PURE__ */ jsx7(Text7, { dimColor: true, children: "\u232B Backspace to go back \xB7 Q to quit" })
|
|
1177
1240
|
] });
|
|
1178
1241
|
}
|
|
1179
1242
|
if (screen.name === "entropy") {
|
|
@@ -1225,7 +1288,7 @@ function App({ ceremonyId: initialCeremonyId, displayName: initialDisplayName })
|
|
|
1225
1288
|
return /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
|
|
1226
1289
|
/* @__PURE__ */ jsx7(Header, { ceremony }),
|
|
1227
1290
|
/* @__PURE__ */ jsx7(Attestation, { contribution }),
|
|
1228
|
-
/* @__PURE__ */ jsx7(Box7, { marginTop: 1, children: /* @__PURE__ */ jsx7(Text7, { dimColor: true, children: "\u232B Backspace / B = contribute to another circuit
|
|
1291
|
+
/* @__PURE__ */ jsx7(Box7, { marginTop: 1, children: /* @__PURE__ */ jsx7(Text7, { dimColor: true, children: "\u232B Backspace / B = contribute to another circuit \xB7 Q to quit" }) })
|
|
1229
1292
|
] });
|
|
1230
1293
|
}
|
|
1231
1294
|
return null;
|
|
@@ -1256,10 +1319,9 @@ process.on("SIGTERM", () => {
|
|
|
1256
1319
|
process.exit(0);
|
|
1257
1320
|
});
|
|
1258
1321
|
});
|
|
1259
|
-
var { waitUntilExit } = render(
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
);
|
|
1322
|
+
var { waitUntilExit } = render(/* @__PURE__ */ jsx8(App, { ceremonyId, displayName }), {
|
|
1323
|
+
exitOnCtrlC: false
|
|
1324
|
+
});
|
|
1263
1325
|
await waitUntilExit();
|
|
1264
1326
|
restoreScreen();
|
|
1265
1327
|
process.exit(0);
|