diff --git a/packages/core/src/molecule/predefined.ts b/packages/core/src/molecule/predefined.ts index 176da41c..fac9c97b 100644 --- a/packages/core/src/molecule/predefined.ts +++ b/packages/core/src/molecule/predefined.ts @@ -57,6 +57,13 @@ export const Bool: Codec = Codec.from({ export const BoolOpt = option(Bool); export const BoolVec = vector(Bool); +export const Byte: Codec = Codec.from({ + byteLength: 1, + encode: (value) => bytesFrom(value), + decode: (buffer) => hexFrom(buffer), +}); +export const ByteOpt = option(Byte); + export const Byte4: Codec = Codec.from({ byteLength: 4, encode: (value) => bytesFrom(value), diff --git a/packages/demo/src/app/connected/page.tsx b/packages/demo/src/app/connected/page.tsx index 772fef66..8351a669 100644 --- a/packages/demo/src/app/connected/page.tsx +++ b/packages/demo/src/app/connected/page.tsx @@ -51,6 +51,7 @@ const TABS: [ReactNode, string, keyof typeof icons, string][] = [ ["Hash", "/utils/Hash", "Barcode", "text-violet-500"], ["Mnemonic", "/utils/Mnemonic", "SquareAsterisk", "text-fuchsia-500"], ["Keystore", "/utils/Keystore", "Notebook", "text-rose-500"], + ["Molecule", "/utils/Molecule", "Hash", "text-emerald-500"], ]; /* eslint-enable react/jsx-key */ diff --git a/packages/demo/src/app/utils/(tools)/Molecule/DataInput.tsx b/packages/demo/src/app/utils/(tools)/Molecule/DataInput.tsx new file mode 100644 index 00000000..ee85f475 --- /dev/null +++ b/packages/demo/src/app/utils/(tools)/Molecule/DataInput.tsx @@ -0,0 +1,133 @@ +import React, { useEffect, useState } from "react"; +import { ccc } from "@ckb-ccc/connector-react"; +import JsonView from "@uiw/react-json-view"; +import { useApp } from "@/src/context"; +import { Button } from "@/src/components/Button"; +import { Textarea } from "@/src/components/Textarea"; +import { darkTheme } from "@uiw/react-json-view/dark"; +import { Dropdown } from "@/src/components/Dropdown"; +export type UnpackType = + | string + | number + | undefined + | { [property: string]: UnpackType } + | UnpackType[]; + +type Props = { + codec: ccc.mol.Codec | undefined; + mode: "decode" | "encode"; +}; + +const formatInput = (input: string): string => { + if (!input.startsWith("0x")) { + return `0x${input}`; + } + return input; +}; + +const isBlank = (data: UnpackType): boolean => { + if (!data) { + return true; + } + return false; +}; + +export const DataInput: React.FC = ({ codec, mode }) => { + const [inputData, setInputData] = useState(""); + const [decodeResult, setDecodeResult] = useState(undefined); + const [encodeResult, setEncodeResult] = useState( + undefined, + ); + const { createSender } = useApp(); + const { log, error } = createSender("Molecule"); + + const handleDecode = () => { + if (!codec) { + error("please select codec"); + return; + } + try { + const result = codec.decode(formatInput(inputData)); + log("Successfully decoded data"); + setDecodeResult(result); + } catch (e: unknown) { + setDecodeResult(undefined); + error((e as Error).message); + } + }; + + const handleEncode = () => { + if (!codec) { + error("please select codec"); + return; + } + try { + const inputObject = JSON.parse(inputData); + const result = codec.encode(inputObject); + log("Successfully encoded data"); + setEncodeResult(ccc.hexFrom(result)); + } catch (e: unknown) { + setEncodeResult(undefined); + error((e as Error).message); + } + }; + + // If mode changes, clear the input data + useEffect(() => { + setInputData(""); + setDecodeResult(undefined); + setEncodeResult(undefined); + }, [mode]); + + return ( +
+
+ +
+