Skip to content

Commit 0b1f6bd

Browse files
wemeetagainclaude
andcommitted
feat: support base64 input for deserialization
Add base64 as a deserialize input format alongside hex. The input panel now shows hex/base64 tabs in deserialize mode. The worker decodes base64 via atob before deserializing. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent d9de906 commit 0b1f6bd

3 files changed

Lines changed: 24 additions & 12 deletions

File tree

src/hooks/use-ssz.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,11 @@ export function useSsz(
3535
}
3636

3737
// Skip if debounced input doesn't match the current mode (stale data from mode switch)
38-
if (mode === "deserialize" && !debouncedInput.trim().startsWith("0x")) {
38+
const trimmed = debouncedInput.trim();
39+
if (mode === "deserialize" && inputFormat === "hex" && !trimmed.startsWith("0x")) {
3940
return;
4041
}
41-
if (mode === "serialize" && inputFormat !== "hex" && debouncedInput.trim().startsWith("0x")) {
42+
if (mode === "serialize" && inputFormat !== "hex" && trimmed.startsWith("0x")) {
4243
return;
4344
}
4445

@@ -59,7 +60,7 @@ export function useSsz(
5960
});
6061
}
6162
} else {
62-
const {deserialized} = await worker.deserialize(typeName, forkName, debouncedInput);
63+
const {deserialized} = await worker.deserialize(typeName, forkName, debouncedInput, inputFormat);
6364
if (!cancelled) {
6465
setResult({
6566
serialized: null,

src/lib/formats.ts

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,16 @@
11
import {type Type, fromHexString, toHexString} from "@chainsafe/ssz";
22
import {dumpYaml, parseYaml} from "./yaml";
33

4+
function fromBase64(b64: string): Uint8Array {
5+
const binstr = atob(b64);
6+
return Uint8Array.from(binstr, (ch) => ch.charCodeAt(0));
7+
}
8+
9+
function toBase64(data: Uint8Array): string {
10+
const binstr = Array.from(data, (ch) => String.fromCharCode(ch)).join("");
11+
return btoa(binstr);
12+
}
13+
414
// --- Input formats (for parsing user input into SSZ values) ---
515

616
type InputFormat = {
@@ -25,11 +35,6 @@ export const inputFormats: Record<string, InputFormat> = {
2535

2636
// --- Output formats (for displaying results) ---
2737

28-
function toBase64(data: Uint8Array): string {
29-
const binstr = Array.from(data, (ch) => String.fromCharCode(ch)).join("");
30-
return btoa(binstr);
31-
}
32-
3338
type SerializeOutputFormat = {
3439
dump: (value: Uint8Array) => string;
3540
};
@@ -53,6 +58,6 @@ export const deserializeOutputFormats: Record<string, DeserializeOutputFormat> =
5358
};
5459

5560
export const serializeInputFormatNames = ["yaml", "json", "hex"] as const;
56-
export const deserializeInputFormatNames = ["hex"] as const;
61+
export const deserializeInputFormatNames = ["hex", "base64"] as const;
5762
export const serializeOutputFormatNames = ["hex", "base64"] as const;
5863
export const deserializeOutputFormatNames = ["yaml", "json"] as const;

src/workers/ssz-worker.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,16 @@ const worker = {
3434
return Comlink.transfer({serialized, hashTreeRoot}, [serialized.buffer, hashTreeRoot.buffer]);
3535
},
3636

37-
async deserialize(typeName: string, forkName: string, hexData: string) {
37+
async deserialize(typeName: string, forkName: string, data: string, inputFormat: string) {
3838
const {fromHexString, forks} = await libs;
3939
const type = getType(forks, typeName, forkName);
40-
const bytes = fromHexString(hexData);
40+
let bytes: Uint8Array;
41+
if (inputFormat === "base64") {
42+
const binstr = atob(data);
43+
bytes = Uint8Array.from(binstr, (ch) => ch.charCodeAt(0));
44+
} else {
45+
bytes = fromHexString(data);
46+
}
4147
const deserialized = type.deserialize(bytes);
4248
return {deserialized};
4349
},
@@ -52,7 +58,7 @@ const worker = {
5258

5359
export type SszWorkerApi = {
5460
serialize(typeName: string, forkName: string, input: string, inputFormat: string): Promise<{serialized: Uint8Array; hashTreeRoot: Uint8Array}>;
55-
deserialize(typeName: string, forkName: string, hexData: string): Promise<{deserialized: unknown}>;
61+
deserialize(typeName: string, forkName: string, data: string, inputFormat: string): Promise<{deserialized: unknown}>;
5662
defaultValue(typeName: string, forkName: string): Promise<{value: unknown}>;
5763
};
5864

0 commit comments

Comments
 (0)