Skip to content

Commit b958bb9

Browse files
committed
feat: [wip] add encode addhoc logics
1 parent f5fe7f4 commit b958bb9

3 files changed

Lines changed: 166 additions & 85 deletions

File tree

Lines changed: 112 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,75 +1,132 @@
1-
import { CardWithTextTitle } from "@/components/Card";
2-
import { useState } from "react";
1+
import { CardWithTabsTitle } from "@/components/Card";
2+
import { EditableJSON } from "@/components/JWPVisualizer";
3+
import { useEffect, useState } from "react";
34

4-
type PayloadItem = {
5-
claim: string;
6-
decoded: string;
7-
raw: string;
8-
disclosed: boolean;
5+
type Payload = {
6+
claims: string[];
7+
decodedString: string;
8+
disclosed: boolean[];
99
};
1010

1111
type PayloadInputProps = {
12-
payload: PayloadItem[];
13-
onChange?: (payload: PayloadItem[]) => void;
12+
payload: Payload;
13+
onChange?: (payload: Payload) => void;
1414
};
1515

1616
export const PayloadInput: React.FC<PayloadInputProps> = ({
1717
payload,
1818
onChange,
1919
}) => {
20-
const [tableData, setTableData] = useState<PayloadItem[]>(payload);
20+
const [activeTabKey, setActiveTabKey] = useState<"json" | "table">("json");
2121

22-
const handleDecodedChange = (index: number, newDecoded: string) => {
23-
setTableData((prev) =>
24-
prev.map((item, i) =>
25-
i === index ? { ...item, decoded: newDecoded } : item,
26-
),
27-
);
28-
onChange?.(tableData);
22+
const [decodedString, setDecodedString] = useState<string>(
23+
payload.decodedString,
24+
);
25+
26+
const [disclosed, setDisclosed] = useState<boolean[]>(payload.disclosed);
27+
28+
const handleJsonChange = (newJsonString: string) => {
29+
setDecodedString(newJsonString);
30+
31+
try {
32+
JSON.parse(newJsonString);
33+
34+
onChange?.({
35+
claims: payload.claims,
36+
decodedString: newJsonString,
37+
disclosed,
38+
});
39+
} catch (error) {
40+
console.warn("JSON Parse Error", error);
41+
}
2942
};
3043

3144
const handleDisclosedChange = (index: number, newVal: boolean) => {
32-
setTableData((prev) =>
33-
prev.map((item, i) =>
34-
i === index ? { ...item, disclosed: newVal } : item,
35-
),
36-
);
45+
const newDisclosed = [...disclosed];
46+
newDisclosed[index] = newVal;
47+
setDisclosed(newDisclosed);
48+
49+
onChange?.({
50+
claims: payload.claims,
51+
decodedString,
52+
disclosed: newDisclosed,
53+
});
54+
};
55+
56+
const getTableData = () => {
57+
try {
58+
const parsedDecoded = JSON.parse(decodedString);
59+
if (Array.isArray(parsedDecoded)) {
60+
return payload.claims.map((claim, index) => ({
61+
claim,
62+
decodedValue:
63+
parsedDecoded[index] !== undefined
64+
? typeof parsedDecoded[index] === "object"
65+
? JSON.stringify(parsedDecoded[index])
66+
: String(parsedDecoded[index])
67+
: "",
68+
disclosed: disclosed[index] || false,
69+
}));
70+
}
71+
} catch (error) {
72+
console.warn("Table Data Generation Error:", error);
73+
}
74+
// Fallback if JSON parsing fails or not an array
75+
return payload.claims.map((claim, index) => ({
76+
claim,
77+
decodedValue: "",
78+
disclosed: disclosed[index] || false,
79+
}));
3780
};
3881

82+
// Synchronization process when payload changes
83+
useEffect(() => {
84+
setDecodedString(payload.decodedString);
85+
setDisclosed([...payload.disclosed]);
86+
}, [payload.decodedString, payload.disclosed]);
87+
3988
return (
40-
<CardWithTextTitle title="PAYLOAD (Check to disclose)">
41-
<table className="min-w-full border-collapse border text-xs">
42-
<thead className="bg-gray-50">
43-
<tr>
44-
<th className="border px-2 py-1 text-left">Claim</th>
45-
<th className="border px-2 py-1 text-left">Decoded</th>
46-
<th className="border px-2 py-1 text-center" />
47-
</tr>
48-
</thead>
49-
<tbody>
50-
{tableData.map((item, index) => (
51-
<tr key={index} className={!item.disclosed ? "bg-gray-300" : ""}>
52-
<td className="border px-2 py-1">{item.claim}</td>
53-
<td className="border px-2 py-1">
54-
<input
55-
className="w-full rounded border px-2 py-1"
56-
value={item.decoded}
57-
onChange={(e) => handleDecodedChange(index, e.target.value)}
58-
/>
59-
</td>
60-
<td className="border px-1 text-center">
61-
<input
62-
type="checkbox"
63-
checked={item.disclosed}
64-
onChange={(e) =>
65-
handleDisclosedChange(index, e.target.checked)
66-
}
67-
/>
68-
</td>
89+
<CardWithTabsTitle
90+
activeTabKey={activeTabKey}
91+
tabTitles={{ json: "JSON", table: "TABLE (Check to disclose)" }}
92+
onTabClick={(item) => setActiveTabKey(item as "json" | "table")}
93+
>
94+
{activeTabKey === "json" ? (
95+
<div className="p-4">
96+
<EditableJSON jsonData={decodedString} onChange={handleJsonChange} />
97+
</div>
98+
) : (
99+
<table className="min-w-full border-collapse border text-xs">
100+
<thead className="bg-gray-50">
101+
<tr>
102+
<th className="border px-2 py-1 text-left">Claim</th>
103+
<th className="border px-2 py-1 text-left">Decoded Value</th>
104+
<th className="border px-2 py-1 text-center" />
69105
</tr>
70-
))}
71-
</tbody>
72-
</table>
73-
</CardWithTextTitle>
106+
</thead>
107+
<tbody>
108+
{getTableData().map((item, index) => (
109+
<tr key={index} className={!item.disclosed ? "bg-gray-100" : ""}>
110+
<td className="border px-2 py-1">{item.claim}</td>
111+
<td className="border px-2 py-1">
112+
<div className="w-full overflow-x-auto px-2 py-1 font-mono">
113+
{item.decodedValue}
114+
</div>
115+
</td>
116+
<td className="border px-1 text-center">
117+
<input
118+
type="checkbox"
119+
checked={item.disclosed}
120+
onChange={(e) =>
121+
handleDisclosedChange(index, e.target.checked)
122+
}
123+
/>
124+
</td>
125+
</tr>
126+
))}
127+
</tbody>
128+
</table>
129+
)}
130+
</CardWithTabsTitle>
74131
);
75132
};

src/features/JWPEncoder/components/Input/index.tsx

Lines changed: 52 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -7,54 +7,78 @@ import { HeaderInput } from "./HeaderInput";
77
import { PayloadInput } from "./PayloadInput";
88
import { PrivKeyInput } from "./PrivKeyInput";
99

10+
// FIXME: There is an isssue with header processing.
11+
1012
export const EncoderInput = () => {
1113
const { isValidJWK } = useVerifyResult();
1214
const { jwk, setIssuedFormJWP, setPresentedFormJWP } = useDebuggerStore();
1315
const { getIssuedFormattedData, getPresentedFormattedData } =
1416
useValidateResult();
15-
const {
16-
initPresentationHeader,
17-
initIssuerHeader,
18-
initPayloads,
19-
// biome-ignore lint/correctness/useExhaustiveDependencies: <explanation>
20-
} = useMemo(() => {
17+
18+
const initialData = useMemo(() => {
2119
const {
2220
presentationHeader: initPresentationHeader,
2321
payloads: presentationPayload,
2422
issuerHeader: initIssuerHeader,
2523
} = getPresentedFormattedData();
2624
const { payloads: initPayloads } = getIssuedFormattedData();
27-
const payloadWithDisclosed = initPayloads.map((item, index) => {
28-
const disclosed = presentationPayload[index].decoded !== "";
29-
return {
30-
...item,
31-
disclosed,
32-
};
25+
26+
const claims = initPayloads.map((item) => item.claim);
27+
const decoded = initPayloads.map((item) => {
28+
const value = item.decoded;
29+
if (value.startsWith('"') && value.endsWith('"')) {
30+
return value.slice(1, -1);
31+
}
32+
return value;
3333
});
34+
const disclosed = presentationPayload.map((item) => item.decoded !== "");
35+
36+
console.log(JSON.stringify(decoded, null, 2));
3437
return {
3538
initPresentationHeader,
3639
initIssuerHeader,
37-
initPayloads: payloadWithDisclosed,
40+
payloadData: {
41+
claims,
42+
decodedString: JSON.stringify(decoded, null, 2),
43+
disclosed,
44+
},
3845
};
39-
}, []);
40-
const [issuerHeader, setIssuerHeader] = useState(initIssuerHeader);
46+
}, [getPresentedFormattedData, getIssuedFormattedData]);
47+
48+
const [issuerHeader, setIssuerHeader] = useState(
49+
initialData.initIssuerHeader,
50+
);
4151
const [presentationHeader, setPresentationHeader] = useState(
42-
initPresentationHeader,
52+
initialData.initPresentationHeader,
4353
);
44-
const [payloads, setPayloads] = useState(initPayloads);
54+
const [payloads, setPayloads] = useState(initialData.payloadData);
4555

4656
useMemo(() => {
47-
const disclosedClaims = payloads.filter((item) => item.disclosed);
48-
console.log("何変わった");
49-
const result = generateIssuedAndPresentedJWP(
50-
payloads,
51-
presentationHeader,
52-
disclosedClaims.map((item) => item.claim),
53-
jwk,
54-
);
55-
setIssuedFormJWP(result.issued);
56-
setPresentedFormJWP(result.presented);
57-
return result;
57+
try {
58+
const decodedValues = JSON.parse(payloads.decodedString);
59+
const formattedPayloads = payloads.claims.map((claim, index) => ({
60+
claim,
61+
decoded:
62+
decodedValues[index] !== undefined
63+
? typeof decodedValues[index] === "object"
64+
? JSON.stringify(decodedValues[index])
65+
: String(decodedValues[index])
66+
: "",
67+
}));
68+
const undisclosedClaims = payloads.claims.filter(
69+
(_, index) => !payloads.disclosed[index],
70+
);
71+
const result = generateIssuedAndPresentedJWP(
72+
formattedPayloads,
73+
presentationHeader,
74+
undisclosedClaims,
75+
jwk,
76+
);
77+
setIssuedFormJWP(result.issued);
78+
setPresentedFormJWP(result.presented);
79+
} catch (error) {
80+
console.error("JWP Generation Error:", error);
81+
}
5882
}, [
5983
payloads,
6084
presentationHeader,

src/libs/generate/generateJWP.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import {
99
export const generateIssuedAndPresentedJWP = (
1010
payload: Array<{ claim: string; decoded: string }>,
1111
presentationProtectedHeaderString: string,
12-
disclosedClaims: string[],
12+
undisclosedClaims: string[],
1313
jwkString: string,
1414
) => {
1515
const jwk = new Jwk(jwkString);
@@ -37,7 +37,7 @@ export const generateIssuedAndPresentedJWP = (
3737
const presentedJwp = new PresentedJwp(
3838
publicJwk,
3939
jwp,
40-
disclosedClaims,
40+
undisclosedClaims,
4141
aud,
4242
nonce,
4343
);

0 commit comments

Comments
 (0)