Skip to content

Commit 8294234

Browse files
committed
fix(evaluations): add documentation
1 parent 0dce78b commit 8294234

6 files changed

Lines changed: 105 additions & 13 deletions

File tree

.github/copilot-instructions.md

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,6 @@
22

33
> **Note:** These guidelines primarily apply to the `gas-benchmarks/` package but can serve as general standards for TypeScript code across the repository.
44
5-
## Benchmarks definitions
6-
7-
- **Shield**: Converting public assets into private ones by depositing them into a privacy pool or protocol. (e.g. shield, bridge, encrypt, etc)
8-
- **Unshield**: Converting private assets back into public ones by withdrawing them from a privacy pool or protocol. (e.g. unshield, bridge, decrypt, etc)
9-
- **Transfer**: Moving private assets from one address to another within the privacy pool or protocol. (e.g. transfer, send, etc)
10-
115
## 1. Clean and Concise Code
126

137
- Write clean, short code with minimal boilerplate
@@ -18,6 +12,7 @@
1812
- Validated by `src/__tests__/constants.test.ts`
1913
- Minimize inline comments - code should be self-explanatory
2014
- No `console.log` (prohibited by ESLint)
15+
- Give space around operators for readability, but avoid unnecessary blank lines
2116

2217
## 2. Use examples and references in comments
2318

@@ -43,13 +38,32 @@
4338

4439
## 6. Testing Requirements
4540

46-
- **ALWAYS** run `pnpm run test` and `pnpm run benchmark` after changes
4741
- Do NOT complete work without running these verification steps
4842
- Fix all test failures and benchmark errors before finalizing
4943

44+
# Specific Guidelines for the gas-benchmarks directory
45+
46+
## Rules
47+
48+
- Follow the general guidelines above, with a focus on clarity and maintainability in benchmark code
49+
- **ALWAYS** run `pnpm run test` and `pnpm run benchmark` after changes in the gas-benchmarks directory
50+
51+
## Benchmarks definitions
52+
53+
- **Shield**: Converting public assets into private ones by depositing them into a privacy pool or protocol. (e.g. shield, bridge, encrypt, etc)
54+
- **Unshield**: Converting private assets back into public ones by withdrawing them from a privacy pool or protocol. (e.g. unshield, bridge, decrypt, etc)
55+
- **Transfer**: Moving private assets from one address to another within the privacy pool or protocol. (e.g. transfer, send, etc)
56+
5057
## Examples
5158

5259
- Protocol patterns: `src/railgun/index.ts`, `src/tornado-cash/index.ts`, `src/privacy-pools/index.ts`
5360
- Protocol specific constants to interact with: `src/railgun/constants.ts`, `src/tornado-cash/constants.ts`, `src/privacy-pools/constants.ts`
5461
- Functional programming: `src/utils/utils.ts`, `src/utils/rpc.ts`, `src/index.ts`
5562
- Type organization: `src/utils/types.ts`, `src/__tests__/types.ts`
63+
64+
# Specific Guidelines for the project-evaluations directory
65+
66+
## Rules
67+
68+
- Follow the general guidelines above, with a focus on clarity and maintainability in evaluation code
69+
- **ALWAYS** run `pnpm run build` after changes in the project-evaluations directory unless these are changes only to project-evaluations/data/evaluations.json

project-evaluations/src/components/AddModal.tsx

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ interface AddModalProps {
1111
export default function AddModal({ onClose }: AddModalProps) {
1212
const [title, setTitle] = useState("");
1313
const [description, setDescription] = useState("");
14+
const [documentation, setDocumentation] = useState("");
1415
const [selectedCategories, setSelectedCategories] = useState<Category[]>([]);
1516

1617
const { addEvaluation } = useEvaluationsData();
@@ -24,12 +25,17 @@ export default function AddModal({ onClose }: AddModalProps) {
2425
alert("Please enter a title.");
2526
return;
2627
}
28+
2729
if (selectedCategories.length === 0) {
2830
alert("Please select at least one category.");
2931
return;
3032
}
33+
3134
const trimmedDescription = description.trim();
32-
addEvaluation(trimmedTitle, trimmedDescription, selectedCategories);
35+
const trimmedDocumentation = documentation.trim();
36+
37+
addEvaluation(trimmedTitle, trimmedDescription, trimmedDocumentation, selectedCategories);
38+
3339
onClose();
3440
};
3541

@@ -67,6 +73,18 @@ export default function AddModal({ onClose }: AddModalProps) {
6773
className={`${fieldClass} resize-none`}
6874
/>
6975
</div>
76+
<div>
77+
<label className="block text-xs text-gray-400 mb-1">Documentation</label>
78+
<textarea
79+
rows={2}
80+
placeholder="Documentation URL or link"
81+
value={documentation}
82+
onChange={(e) => {
83+
setDocumentation(e.target.value);
84+
}}
85+
className={`${fieldClass} resize-none`}
86+
/>
87+
</div>
7088
<div>
7189
<label className="block text-xs text-gray-400 mb-2">Categories</label>
7290
<div className="space-y-2 bg-gray-800 border border-gray-700 rounded p-3">

project-evaluations/src/components/ProtocolDetail.tsx

Lines changed: 57 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,10 @@ export default function ProtocolDetail({
1919
setSelectedId,
2020
}: ProtocolDetailProps) {
2121
const [editingField, setEditingField] = useState<string | null>(null);
22-
const [editValues, setEditValues] = useState<{ title: string; description: string }>({
22+
const [editValues, setEditValues] = useState<{ title: string; description: string; documentation: string }>({
2323
title: "",
2424
description: "",
25+
documentation: "",
2526
});
2627

2728
const evaluation = evaluations.find((entry) => entry.id === selectedId) ?? null;
@@ -34,11 +35,13 @@ export default function ProtocolDetail({
3435
);
3536
}
3637

37-
const startEdit = (field: "title" | "description"): void => {
38+
const startEdit = (field: "title" | "description" | "documentation"): void => {
3839
if (field === "title") {
3940
setEditValues((prev) => ({ ...prev, title: evaluation.title }));
40-
} else {
41+
} else if (field === "description") {
4142
setEditValues((prev) => ({ ...prev, description: evaluation.description }));
43+
} else {
44+
setEditValues((prev) => ({ ...prev, documentation: evaluation.documentation }));
4245
}
4346
setEditingField(field);
4447
};
@@ -50,6 +53,7 @@ export default function ProtocolDetail({
5053
if (entry.id !== selectedId) return entry;
5154
if (editingField === "title") return { ...entry, title: editValues.title };
5255
if (editingField === "description") return { ...entry, description: editValues.description };
56+
if (editingField === "documentation") return { ...entry, documentation: editValues.documentation };
5357
return entry;
5458
}),
5559
);
@@ -185,6 +189,56 @@ export default function ProtocolDetail({
185189
)}
186190
</div>
187191

192+
<div
193+
className="group cursor-pointer mt-3"
194+
onDoubleClick={() => {
195+
startEdit("documentation");
196+
}}
197+
onKeyDown={(e) => {
198+
if (e.key === "Enter") startEdit("documentation");
199+
}}
200+
role="button"
201+
tabIndex={0}
202+
>
203+
{editingField === "documentation" ? (
204+
<div className="flex gap-2">
205+
<textarea
206+
value={editValues.documentation}
207+
onChange={(e) => {
208+
setEditValues({ ...editValues, documentation: e.target.value });
209+
}}
210+
onKeyDown={(e) => {
211+
if (e.key === "Escape") cancelEdit();
212+
}}
213+
autoFocus
214+
className="text-sm text-gray-300 bg-gray-800 border border-indigo-500 rounded px-2 py-1 flex-1 resize-none"
215+
rows={2}
216+
/>
217+
<div className="flex flex-col gap-2">
218+
<button
219+
onClick={saveEdit}
220+
className="text-xs px-2 py-1 bg-indigo-600 text-white rounded hover:bg-indigo-700 whitespace-nowrap"
221+
>
222+
Save
223+
</button>
224+
<button
225+
onClick={cancelEdit}
226+
className="text-xs px-2 py-1 bg-gray-700 text-gray-300 rounded hover:bg-gray-600 whitespace-nowrap"
227+
>
228+
Cancel
229+
</button>
230+
</div>
231+
</div>
232+
) : (
233+
<div>
234+
<label className="block text-xs text-gray-500 mb-1">Documentation</label>
235+
<p className="text-sm text-gray-400 group-hover:text-gray-300 transition-colors">
236+
{evaluation.documentation || "Double-click to add documentation"}
237+
</p>
238+
</div>
239+
)}
240+
</div>
241+
188242
<ProtocolCategories
189243
categories={evaluation.categories}
190244
onUpdate={(categories) => {

project-evaluations/src/data/evaluations.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,27 +4,31 @@
44
"id": "railgun",
55
"title": "RAILGUN",
66
"description": "A privacy system for Ethereum using zk-SNARKs to shield ERC-20 tokens and ETH inside a smart contract, enabling private transfers and shielded DeFi interactions.",
7+
"documentation": "https://docs.railgun.com/",
78
"categories": ["Shielded pool"],
89
"properties": []
910
},
1011
{
1112
"id": "tornado-cash",
1213
"title": "Tornado Cash",
1314
"description": "A non-custodial, Ethereum-based mixer that uses zk-SNARKs to break the on-chain link between deposit and withdrawal addresses for fixed-denomination ETH and ERC-20 deposits.",
15+
"documentation": "https://docs.railgun.com/",
1416
"categories": ["Mixer"],
1517
"properties": []
1618
},
1719
{
1820
"id": "privacy-pools",
1921
"title": "Privacy Pools",
2022
"description": "A privacy protocol that extends Tornado Cash with association set providers (ASPs), allowing users to prove membership in compliant subsets without revealing their identity.",
23+
"documentation": "https://docs.railgun.com/",
2124
"categories": ["Shielded pool"],
2225
"properties": []
2326
},
2427
{
2528
"id": "intmax",
2629
"title": "Intmax",
2730
"description": "A stateless zkRollup optimised for private payments, pushing most data off-chain so that on-chain costs are minimal while preserving user-side privacy through client-side proving.",
31+
"documentation": "https://docs.railgun.com/",
2832
"categories": ["Shielded pool", "L2"],
2933
"properties": []
3034
}

project-evaluations/src/data/utils.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ export const useEvaluationsData = (
1414
setEvaluations: Dispatch<SetStateAction<Evaluation[]>>;
1515
selectedId: string | null;
1616
setSelectedId: Dispatch<SetStateAction<string | null>>;
17-
addEvaluation: (title: string, description: string, categories: Category[]) => void;
17+
addEvaluation: (title: string, description: string, documentation: string, categories: Category[]) => void;
1818
} => {
1919
const fallbackData = structuredClone(defaultData as EvaluationsData);
2020

@@ -37,14 +37,15 @@ export const useEvaluationsData = (
3737
.catch(() => undefined);
3838
}, [url]);
3939

40-
const addEvaluation = (title: string, description: string, categories: Category[]): void => {
40+
const addEvaluation = (title: string, description: string, documentation: string, categories: Category[]): void => {
4141
const newEvaluation: Evaluation = {
4242
id: title
4343
.toLowerCase()
4444
.replace(/[^a-z0-9]+/g, "-")
4545
.replace(/(^-|-$)/g, ""),
4646
title,
4747
description,
48+
documentation,
4849
categories,
4950
properties: [],
5051
};

project-evaluations/src/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ export interface Evaluation {
2828
id: string;
2929
title: string;
3030
description: string;
31+
documentation: string;
3132
categories: Category[];
3233
properties: Property[];
3334
}

0 commit comments

Comments
 (0)