diff --git a/package.json b/package.json index eeb202d..ceed22f 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "@polkadot-api/ledger-signer": "^0.1.6", "@polkadot-api/metadata-builders": "^0.9.1", "@polkadot-api/observable-client": "^0.6.2", + "@polkadot-api/react-builder": "link:../polkadot-api/packages/react-builder", "@polkadot-api/substrate-bindings": "^0.9.3", "@polkadot-api/substrate-client": "^0.3.0", "@polkadot-api/utils": "^0.1.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 446d85d..1b68f4f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -34,6 +34,9 @@ importers: '@polkadot-api/observable-client': specifier: ^0.6.2 version: 0.6.2(patch_hash=ntppxp7tto3f2viektlrpekj7y)(@polkadot-api/substrate-client@0.3.0)(rxjs@7.8.1) + '@polkadot-api/react-builder': + specifier: link:../polkadot-api/packages/react-builder + version: link:../polkadot-api/packages/react-builder '@polkadot-api/substrate-bindings': specifier: ^0.9.3 version: 0.9.3 diff --git a/src/codec-components/BinaryViewCodec/CEnum.tsx b/src/codec-components/BinaryViewCodec/CEnum.tsx index d3fbefd..0d9c4fe 100644 --- a/src/codec-components/BinaryViewCodec/CEnum.tsx +++ b/src/codec-components/BinaryViewCodec/CEnum.tsx @@ -1,4 +1,4 @@ -import { EditEnum, NOTIN } from "@codec-components" +import { EditEnum, NOTIN } from "@polkadot-api/react-builder" import { u8 } from "@polkadot-api/substrate-bindings" import { useStateObservable } from "@react-rxjs/core" import { isActive$ } from "../common/paths.state" diff --git a/src/codec-components/BinaryViewCodec/CStruct.tsx b/src/codec-components/BinaryViewCodec/CStruct.tsx index d58361e..3c1f181 100644 --- a/src/codec-components/BinaryViewCodec/CStruct.tsx +++ b/src/codec-components/BinaryViewCodec/CStruct.tsx @@ -1,4 +1,4 @@ -import { EditStruct, NOTIN } from "@codec-components" +import { EditStruct, NOTIN } from "@polkadot-api/react-builder" import { useStateObservable } from "@react-rxjs/core" import React from "react" import { isActive$ } from "../common/paths.state" diff --git a/src/codec-components/BinaryViewCodec/ListComponents.tsx b/src/codec-components/BinaryViewCodec/ListComponents.tsx index ea3ff9a..8caa718 100644 --- a/src/codec-components/BinaryViewCodec/ListComponents.tsx +++ b/src/codec-components/BinaryViewCodec/ListComponents.tsx @@ -4,7 +4,7 @@ import { EditSequence, EditTuple, NOTIN, -} from "@codec-components" +} from "@polkadot-api/react-builder" import { compact } from "@polkadot-api/substrate-bindings" import { useStateObservable } from "@react-rxjs/core" import React, { ReactNode } from "react" diff --git a/src/codec-components/BinaryViewCodec/codec-components.tsx b/src/codec-components/BinaryViewCodec/codec-components.tsx index 04b79b6..c2c7578 100644 --- a/src/codec-components/BinaryViewCodec/codec-components.tsx +++ b/src/codec-components/BinaryViewCodec/codec-components.tsx @@ -11,7 +11,7 @@ import { EditStr, EditVoid, NOTIN, -} from "@codec-components" +} from "@polkadot-api/react-builder" import { u8 } from "@polkadot-api/substrate-bindings" import { toHex } from "@polkadot-api/utils" import { useStateObservable } from "@react-rxjs/core" diff --git a/src/codec-components/BinaryViewCodec/index.ts b/src/codec-components/BinaryViewCodec/index.ts index 94489ff..b6ca8f7 100644 --- a/src/codec-components/BinaryViewCodec/index.ts +++ b/src/codec-components/BinaryViewCodec/index.ts @@ -1,4 +1,4 @@ -import { getCodecComponent } from "@codec-components" +import { getCodecComponent } from "@polkadot-api/react-builder" import * as treeComponents from "./components" diff --git a/src/codec-components/EditCodec/CAccountId.tsx b/src/codec-components/EditCodec/CAccountId.tsx index ae5fbf3..a71880e 100644 --- a/src/codec-components/EditCodec/CAccountId.tsx +++ b/src/codec-components/EditCodec/CAccountId.tsx @@ -20,7 +20,7 @@ import { } from "@/extension-accounts.state" import { identity$, isVerified } from "@/identity.state" import { cn } from "@/utils/cn" -import { EditAccountId, NOTIN } from "@codec-components" +import { EditAccountId, NOTIN } from "@polkadot-api/react-builder" import { getSs58AddressInfo } from "@polkadot-api/substrate-bindings" import { toHex } from "@polkadot-api/utils" import { state, useStateObservable } from "@react-rxjs/core" diff --git a/src/codec-components/EditCodec/CBytes.tsx b/src/codec-components/EditCodec/CBytes.tsx index 72cab59..bb94e7d 100644 --- a/src/codec-components/EditCodec/CBytes.tsx +++ b/src/codec-components/EditCodec/CBytes.tsx @@ -1,4 +1,4 @@ -import { EditBytes } from "@codec-components" +import { EditBytes } from "@polkadot-api/react-builder" import { BinaryInput } from "@/components/BinaryInput" export const CBytes: EditBytes = ({ value, onValueChanged, len }) => ( diff --git a/src/codec-components/EditCodec/CEnum.tsx b/src/codec-components/EditCodec/CEnum.tsx index 95e3eac..44c4b80 100644 --- a/src/codec-components/EditCodec/CEnum.tsx +++ b/src/codec-components/EditCodec/CEnum.tsx @@ -1,6 +1,6 @@ import { SearchableSelect } from "@/components/Select" import { isEnumComplex, isEnumVoid } from "@/utils/shape" -import { EditEnum, NOTIN } from "@codec-components" +import { EditEnum, NOTIN } from "@polkadot-api/react-builder" import { Marker } from "../common/Markers" import { useSubtreeFocus } from "../common/SubtreeFocus" diff --git a/src/codec-components/EditCodec/CSequence.tsx b/src/codec-components/EditCodec/CSequence.tsx index 77ea525..047210b 100644 --- a/src/codec-components/EditCodec/CSequence.tsx +++ b/src/codec-components/EditCodec/CSequence.tsx @@ -1,4 +1,4 @@ -import { EditSequence, NOTIN } from "@codec-components" +import { EditSequence, NOTIN } from "@polkadot-api/react-builder" import { CirclePlus } from "lucide-react" import { twMerge as clsx } from "tailwind-merge" import { ListItem } from "../common/ListItem" diff --git a/src/codec-components/EditCodec/CStr.tsx b/src/codec-components/EditCodec/CStr.tsx index 68148d5..6f0f0ae 100644 --- a/src/codec-components/EditCodec/CStr.tsx +++ b/src/codec-components/EditCodec/CStr.tsx @@ -1,5 +1,5 @@ import { withDefault } from "@/utils/default" -import { EditStr } from "@codec-components" +import { EditStr } from "@polkadot-api/react-builder" // TODO export const CStr: EditStr = ({ value, onValueChanged }) => { diff --git a/src/codec-components/EditCodec/CStruct.tsx b/src/codec-components/EditCodec/CStruct.tsx index 0c91b74..2232f71 100644 --- a/src/codec-components/EditCodec/CStruct.tsx +++ b/src/codec-components/EditCodec/CStruct.tsx @@ -1,6 +1,6 @@ import { ExpandBtn } from "@/components/Expand" import { getFinalType } from "@/utils/shape" -import { EditStruct } from "@codec-components" +import { EditStruct } from "@polkadot-api/react-builder" import { useStateObservable } from "@react-rxjs/core" import React from "react" import { twMerge as clsx, twMerge } from "tailwind-merge" diff --git a/src/codec-components/EditCodec/CTuple.tsx b/src/codec-components/EditCodec/CTuple.tsx index 17a476a..b804bb4 100644 --- a/src/codec-components/EditCodec/CTuple.tsx +++ b/src/codec-components/EditCodec/CTuple.tsx @@ -1,5 +1,5 @@ import { useSubtreeFocus } from "../common/SubtreeFocus" -import { EditTuple } from "@codec-components" +import { EditTuple } from "@polkadot-api/react-builder" export const CTuple: EditTuple = ({ innerComponents, path }) => { const focus = useSubtreeFocus() diff --git a/src/codec-components/EditCodec/EditNumber.tsx b/src/codec-components/EditCodec/EditNumber.tsx index a1cb3f0..226b3be 100644 --- a/src/codec-components/EditCodec/EditNumber.tsx +++ b/src/codec-components/EditCodec/EditNumber.tsx @@ -6,7 +6,7 @@ import { EditNumber, EditNumberInterface, NOTIN, -} from "@codec-components" +} from "@polkadot-api/react-builder" import { TextInputField } from "./codec-components" import { useSynchronizeInput } from "@/components/useSynchroniseInput" diff --git a/src/codec-components/EditCodec/Tree/CEnum.tsx b/src/codec-components/EditCodec/Tree/CEnum.tsx index 9c40098..4bbf508 100644 --- a/src/codec-components/EditCodec/Tree/CEnum.tsx +++ b/src/codec-components/EditCodec/Tree/CEnum.tsx @@ -1,6 +1,6 @@ import { Enum } from "@/components/Icons" import { isComplex } from "@/utils/shape" -import { EditEnum, NOTIN } from "@codec-components" +import { EditEnum, NOTIN } from "@polkadot-api/react-builder" import { useContext, useLayoutEffect, useState } from "react" import { Portal } from "react-portal" import { scrollToMarker } from "../../common/scroll" diff --git a/src/codec-components/EditCodec/Tree/CStruct.tsx b/src/codec-components/EditCodec/Tree/CStruct.tsx index 6cb9d87..c867f10 100644 --- a/src/codec-components/EditCodec/Tree/CStruct.tsx +++ b/src/codec-components/EditCodec/Tree/CStruct.tsx @@ -1,6 +1,6 @@ import { lookupToType, TypeIcon, TypeIcons } from "@/components/Icons" import { isComplex } from "@/utils/shape" -import { EditStruct } from "@codec-components" +import { EditStruct } from "@polkadot-api/react-builder" import { useStateObservable } from "@react-rxjs/core" import { FC, PropsWithChildren, useState } from "react" import { twMerge } from "tailwind-merge" diff --git a/src/codec-components/EditCodec/Tree/ListComponents.tsx b/src/codec-components/EditCodec/Tree/ListComponents.tsx index 818f862..70beaa0 100644 --- a/src/codec-components/EditCodec/Tree/ListComponents.tsx +++ b/src/codec-components/EditCodec/Tree/ListComponents.tsx @@ -6,7 +6,7 @@ import { EditSequence, EditTuple, NOTIN, -} from "@codec-components" +} from "@polkadot-api/react-builder" import { useStateObservable } from "@react-rxjs/core" import { GripVertical, Trash2 } from "lucide-react" import React, { diff --git a/src/codec-components/EditCodec/Tree/codec-components.tsx b/src/codec-components/EditCodec/Tree/codec-components.tsx index eba1a04..399d493 100644 --- a/src/codec-components/EditCodec/Tree/codec-components.tsx +++ b/src/codec-components/EditCodec/Tree/codec-components.tsx @@ -13,7 +13,7 @@ import { EditStr, EditVoid, NOTIN, -} from "@codec-components" +} from "@polkadot-api/react-builder" import { HexString } from "@polkadot-api/substrate-bindings" import { useStateObservable } from "@react-rxjs/core" import { Circle } from "lucide-react" diff --git a/src/codec-components/EditCodec/Tree/index.ts b/src/codec-components/EditCodec/Tree/index.ts index cd6315a..cf6f199 100644 --- a/src/codec-components/EditCodec/Tree/index.ts +++ b/src/codec-components/EditCodec/Tree/index.ts @@ -1,4 +1,4 @@ -import { getCodecComponent } from "@codec-components" +import { getCodecComponent } from "@polkadot-api/react-builder" import * as treeComponents from "./components" diff --git a/src/codec-components/EditCodec/codec-components.tsx b/src/codec-components/EditCodec/codec-components.tsx index 5631cf2..d8901cf 100644 --- a/src/codec-components/EditCodec/codec-components.tsx +++ b/src/codec-components/EditCodec/codec-components.tsx @@ -8,7 +8,7 @@ import { EditResult, EditVoid, NOTIN, -} from "@codec-components" +} from "@polkadot-api/react-builder" import { FC, ReactNode, useState } from "react" import { twMerge } from "tailwind-merge" import { ListItem } from "../common/ListItem" diff --git a/src/codec-components/EditCodec/index.tsx b/src/codec-components/EditCodec/index.tsx index 33bd78e..367193a 100644 --- a/src/codec-components/EditCodec/index.tsx +++ b/src/codec-components/EditCodec/index.tsx @@ -1,4 +1,4 @@ -import { getCodecComponent } from "@codec-components" +import { getCodecComponent } from "@polkadot-api/react-builder" import * as editComponents from "./components" export const EditCodec = getCodecComponent(editComponents) diff --git a/src/codec-components/LookupTypeEdit/BinaryDisplay.tsx b/src/codec-components/LookupTypeEdit/BinaryDisplay.tsx index dc20874..655436c 100644 --- a/src/codec-components/LookupTypeEdit/BinaryDisplay.tsx +++ b/src/codec-components/LookupTypeEdit/BinaryDisplay.tsx @@ -2,7 +2,7 @@ import { BinaryViewCodec } from "@/codec-components/BinaryViewCodec" import { BinaryEditButton } from "@/components/BinaryEditButton" import { CopyText } from "@/components/Copy" import { ExpandBtn } from "@/components/Expand" -import { CodecComponentType, NOTIN } from "@codec-components" +import { CodecComponentType, NOTIN } from "@polkadot-api/react-builder" import { Binary, HexString } from "@polkadot-api/substrate-bindings" import { toHex } from "@polkadot-api/utils" import { ComponentProps, FC, useState } from "react" diff --git a/src/codec-components/LookupTypeEdit/LookupTypeEdit.tsx b/src/codec-components/LookupTypeEdit/LookupTypeEdit.tsx index 19c1325..0620354 100644 --- a/src/codec-components/LookupTypeEdit/LookupTypeEdit.tsx +++ b/src/codec-components/LookupTypeEdit/LookupTypeEdit.tsx @@ -1,6 +1,6 @@ import { runtimeCtx$ } from "@/chain.state" import { byteArraysAreEqual } from "@/utils/byteArray" -import { CodecComponentType, CodecComponentValue } from "@codec-components" +import { CodecComponentType, CodecComponentValue } from "@polkadot-api/react-builder" import { state, useStateObservable } from "@react-rxjs/core" import { Codec } from "polkadot-api" import { ComponentProps, FC, useEffect, useRef, useState } from "react" diff --git a/src/codec-components/ViewCodec/CAccountId.tsx b/src/codec-components/ViewCodec/CAccountId.tsx index 807bf84..1b3c8e7 100644 --- a/src/codec-components/ViewCodec/CAccountId.tsx +++ b/src/codec-components/ViewCodec/CAccountId.tsx @@ -1,5 +1,5 @@ import { AccountIdDisplay } from "@/components/AccountIdDisplay" -import { ViewAccountId } from "@codec-components" +import { ViewAccountId } from "@polkadot-api/react-builder" import { useReportBinary } from "./CopyBinary" export const CAccountId: ViewAccountId = ({ value, encodedValue }) => { diff --git a/src/codec-components/ViewCodec/CBytes.tsx b/src/codec-components/ViewCodec/CBytes.tsx index 7e20c09..7af3d6f 100644 --- a/src/codec-components/ViewCodec/CBytes.tsx +++ b/src/codec-components/ViewCodec/CBytes.tsx @@ -1,5 +1,5 @@ import { bytesToString } from "@/components/BinaryInput" -import { ViewBytes } from "@codec-components" +import { ViewBytes } from "@polkadot-api/react-builder" import { useReportBinary } from "./CopyBinary" export const CBytes: ViewBytes = ({ value, encodedValue }) => { diff --git a/src/codec-components/ViewCodec/CEnum.tsx b/src/codec-components/ViewCodec/CEnum.tsx index 33b27d4..3f91355 100644 --- a/src/codec-components/ViewCodec/CEnum.tsx +++ b/src/codec-components/ViewCodec/CEnum.tsx @@ -1,4 +1,4 @@ -import { ViewEnum } from "@codec-components" +import { ViewEnum } from "@polkadot-api/react-builder" import { useStateObservable } from "@react-rxjs/core" import { useContext, useState } from "react" import { Portal } from "react-portal" diff --git a/src/codec-components/ViewCodec/CStruct.tsx b/src/codec-components/ViewCodec/CStruct.tsx index d659fe6..0aeb80b 100644 --- a/src/codec-components/ViewCodec/CStruct.tsx +++ b/src/codec-components/ViewCodec/CStruct.tsx @@ -1,5 +1,5 @@ import { ExpandBtn } from "@/components/Expand" -import { ViewStruct } from "@codec-components" +import { ViewStruct } from "@polkadot-api/react-builder" import { Var } from "@polkadot-api/metadata-builders" import { useStateObservable } from "@react-rxjs/core" import React, { useContext, useState } from "react" diff --git a/src/codec-components/ViewCodec/ListComponents.tsx b/src/codec-components/ViewCodec/ListComponents.tsx index 1db360a..7dac510 100644 --- a/src/codec-components/ViewCodec/ListComponents.tsx +++ b/src/codec-components/ViewCodec/ListComponents.tsx @@ -1,4 +1,4 @@ -import { ViewArray, ViewSequence, ViewTuple } from "@codec-components" +import { ViewArray, ViewSequence, ViewTuple } from "@polkadot-api/react-builder" import { useStateObservable } from "@react-rxjs/core" import { FC, PropsWithChildren, ReactNode } from "react" import { ListItem } from "../common/ListItem" diff --git a/src/codec-components/ViewCodec/codec-components.tsx b/src/codec-components/ViewCodec/codec-components.tsx index 62b08cc..0f79aa9 100644 --- a/src/codec-components/ViewCodec/codec-components.tsx +++ b/src/codec-components/ViewCodec/codec-components.tsx @@ -7,7 +7,7 @@ import { ViewResult, ViewStr, ViewVoid, -} from "@codec-components" +} from "@polkadot-api/react-builder" export const CBool: ViewBool = ({ value }) => { return
{value ? "Yes" : "No"}
diff --git a/src/codec-components/ViewCodec/index.tsx b/src/codec-components/ViewCodec/index.tsx index 12b1e60..517347a 100644 --- a/src/codec-components/ViewCodec/index.tsx +++ b/src/codec-components/ViewCodec/index.tsx @@ -1,4 +1,4 @@ -import { getCodecComponent } from "@codec-components" +import { getCodecComponent } from "@polkadot-api/react-builder" import * as viewComponents from "./components" export const ViewCodec = getCodecComponent(viewComponents) diff --git a/src/components/BinaryEditButton.tsx b/src/components/BinaryEditButton.tsx index 37692ba..f68173b 100644 --- a/src/components/BinaryEditButton.tsx +++ b/src/components/BinaryEditButton.tsx @@ -4,7 +4,7 @@ import { } from "@/components/BinaryInput" import { Modal } from "@/components/Modal" import { useGenericSynchronizeInput } from "@/components/useSynchroniseInput" -import { NOTIN } from "@codec-components" +import { NOTIN } from "@polkadot-api/react-builder" import { Binary } from "@polkadot-api/substrate-bindings" import { Download, FileUp } from "lucide-react" import { ComponentProps, FC, useMemo, useState } from "react" diff --git a/src/components/BinaryInput.tsx b/src/components/BinaryInput.tsx index 54b44a6..f74395e 100644 --- a/src/components/BinaryInput.tsx +++ b/src/components/BinaryInput.tsx @@ -1,5 +1,5 @@ import { byteArraysAreEqual } from "@/utils/byteArray" -import { NOTIN } from "@codec-components" +import { NOTIN } from "@polkadot-api/react-builder" import { Binary } from "@polkadot-api/substrate-bindings" import { FileUp } from "lucide-react" import { FC, useState } from "react" diff --git a/src/components/useSynchroniseInput.ts b/src/components/useSynchroniseInput.ts index a802749..335d3d6 100644 --- a/src/components/useSynchroniseInput.ts +++ b/src/components/useSynchroniseInput.ts @@ -1,4 +1,4 @@ -import { NOTIN } from "@codec-components" +import { NOTIN } from "@polkadot-api/react-builder" import { useEffect, useLayoutEffect, useRef, useState } from "react" export const useGenericSynchronizeInput = ( diff --git a/src/lib/codecComponents/get-codec-component.tsx b/src/lib/codecComponents/get-codec-component.tsx deleted file mode 100644 index a348313..0000000 --- a/src/lib/codecComponents/get-codec-component.tsx +++ /dev/null @@ -1,965 +0,0 @@ -/* eslint-disable react-hooks/rules-of-hooks */ -import { - V15, - V14, - HexString, - Encoder, - Bytes, -} from "@polkadot-api/substrate-bindings" -import * as scale from "@polkadot-api/substrate-bindings" -import { - getDynamicBuilder, - getLookupFn, - LookupEntry, - MetadataLookup, - Var, -} from "@polkadot-api/metadata-builders" -import React, { FC, useRef } from "react" -import { fromHex, mapObject, mergeUint8 } from "@polkadot-api/utils" -import type { - EditAccountId, - EditBigNumber, - EditBool, - EditComponents, - EditEthAccount, - EditNumber, - EditStr, - ViewAccountId, - ViewBigNumber, - ViewBool, - ViewComponents, - ViewEthAccount, - ViewNumber, - ViewStr, -} from "./types" -import { NOTIN } from "./types" - -export type MetadataType = V14 | V15 - -export const enum CodecComponentType { - Initial, - Updated, -} - -export type CodecComponentUpdate = - | { empty: true } - | { empty: false; decoded: any; encoded?: Uint8Array } -export type CodecComponentValue = - | { type: CodecComponentType.Initial; value?: Uint8Array | HexString } - | { type: CodecComponentType.Updated; value: CodecComponentUpdate } - -export type LookupType = Var["type"] - -const detectNotin: (x: T) => boolean = (x) => { - if (x === NOTIN) return true - return x != null && typeof x === "object" - ? Object.values(x).some(detectNotin) - : false -} - -const withNotin: ( - encoder: Encoder, -) => (input: T) => Uint8Array | undefined = (encoder) => (input) => - detectNotin(input) ? undefined : encoder(input) - -const getInnerEnumCodec = ( - input: scale.Codec<{ type: string; value: any }>, - idx: number, - type: string, -) => { - return scale.createCodec( - (value: any) => input.enc({ type, value }).slice(1), - (value) => { - const val: Uint8Array = - value instanceof Uint8Array - ? value - : typeof value === "string" - ? fromHex(value) - : new Uint8Array(value) - return input.dec(mergeUint8(new Uint8Array([idx]), val)).value - }, - ) -} - -export function getViewCodecComponent( - baseComponents: ViewComponents, -): React.FC<{ - metadata: MetadataType - codecType: number - value: Uint8Array | HexString -}> { - const { - CVoid, - CAccountId, - CBigNumber, - CNumber, - CBool, - CStr, - CBytes, - CEthAccount, - CEnum, - CSequence, - CArray, - CTuple, - CStruct, - COption, - CResult, - } = baseComponents as ViewComponents - - const CodecComponent: React.FC<{ - path: string[] - dynCodecs: ReturnType["buildDefinition"] - entry: LookupEntry - parent?: { id: number; variantIdx: number; variantTag: string } - value: - | { - empty: true - } - | { empty: false; decoded: any; encoded?: Uint8Array } - }> = ({ entry, value, dynCodecs, parent, path }) => { - if (value.empty) return <> - - const codec = - "id" in entry - ? dynCodecs(entry.id) - : getInnerEnumCodec( - dynCodecs(parent!.id), - parent!.variantIdx, - parent!.variantTag, - ) - - const encodedValue = value.encoded || codec.enc(value.decoded) - const valueProps = { value: value.decoded, encodedValue: encodedValue } - - if (entry.type === "struct") { - const latestValue = value.decoded - return ( - ( - - ))} - /> - ) - } - - if (entry.type === "tuple") { - return ( - ( - - )), - }} - /> - ) - } - - if (entry.type === "enum") { - let innerEntry - if (!value.empty) { - innerEntry = entry.value[value.decoded.type as string] - if (innerEntry?.type === "lookupEntry") - innerEntry = innerEntry.value as any - if (!innerEntry) return null - } - return ( - ({ - tag, - idx, - })), - shape: entry, - inner: value.empty ? null : ( - - ), - }} - /> - ) - } - - if (entry.type === "result") { - return ( - - ), - }} - /> - ) - } - - if (entry.type === "option") { - return ( - - ) : ( - - ), - }} - /> - ) - } - - if (entry.type === "void") return - - if (entry.type === "array") { - if (entry.value.type === "primitive" && entry.value.value === "u8") { - return - } - - const latestValue = value.empty - ? Array(entry.len).fill(NOTIN) - : (value.decoded as Array) - return ( - ( - - )), - }} - /> - ) - } - - if (entry.type === "sequence") { - if (entry.value.type === "primitive" && entry.value.value === "u8") { - return - } - - const latestValue = value.empty ? [] : (value.decoded as Array) - return ( - ( - - )), - }} - /> - ) - } - - let type: any = undefined - let ResultComponent: - | ViewBigNumber - | ViewNumber - | ViewBool - | ViewStr - | ViewAccountId - | ViewEthAccount = null as any - - switch (entry.type) { - case "compact": { - ResultComponent = entry.isBig ? CBigNumber : CNumber - type = entry.size - break - } - case "primitive": { - if (entry.value === "str" || entry.value === "char") - ResultComponent = CStr - else if (entry.value === "bool") ResultComponent = CBool - else { - const nBits = Number(entry.value.slice(1)) - ResultComponent = nBits < 64 ? CNumber : CBigNumber - type = entry.value - } - break - } - case "bitSequence": { - return null - } - case "AccountId32": { - ResultComponent = CAccountId - break - } - case "AccountId20": { - ResultComponent = CEthAccount - break - } - } - - const Result = ResultComponent as FC - return - } - - const result: FC<{ - metadata: V14 | V15 - codecType: number - value: Uint8Array | HexString - }> = ({ metadata, codecType, value: propsValue }) => { - const lookupRef = useRef<{ - metadata: V14 | V15 - lookup: MetadataLookup - dynCodecs: ReturnType["buildDefinition"] - refresh: ( - codecType: number, - value: Uint8Array | HexString, - ) => { empty: true } | { empty: false; decoded: any; encoded: Uint8Array } - }>({ - metadata: null as any, - lookup: null as any, - dynCodecs: null as any, - refresh: () => ({ empty: true }), - }) - - if (lookupRef.current.metadata !== metadata) { - const lookup = getLookupFn(metadata) - lookupRef.current = { - metadata, - lookup, - dynCodecs: getDynamicBuilder(lookup).buildDefinition, - refresh: (codecType, val) => { - try { - const decoded = lookupRef.current.dynCodecs(codecType).dec(val) - return { - empty: false, - decoded, - encoded: typeof val === "string" ? fromHex(val) : val, - } - } catch (_error) { - console.error("invalid hex for the codec") - return { empty: true } - } - }, - } - } - - const value = lookupRef.current.refresh(codecType, propsValue) - - return ( - - ) - } - - return result as any -} - -export function getCodecComponent(baseComponent: ViewComponents): React.FC<{ - metadata: V14 | V15 - codecType: number - value: CodecComponentValue -}> -export function getCodecComponent(baseComponent: EditComponents): React.FC<{ - metadata: V14 | V15 - codecType: number - value: CodecComponentValue - onUpdate?: (newValue: CodecComponentUpdate) => void -}> -export function getCodecComponent( - _baseComponents: EditComponents | ViewComponents, -) { - const { - CVoid, - CAccountId, - CBigNumber, - CNumber, - CBool, - CStr, - CBytes, - CEthAccount, - CEnum, - CSequence, - CArray, - CTuple, - CStruct, - COption, - CResult, - } = _baseComponents as EditComponents - const CodecComponent: React.FC<{ - path: string[] - dynCodecs: ReturnType["buildDefinition"] - entry: LookupEntry - parent?: { id: number; variantIdx: number; variantTag: string } - value: - | { - empty: true - } - | { empty: false; decoded: any; encoded?: Uint8Array } - onChange: (value: any) => boolean - }> = ({ entry, value, dynCodecs, onChange, parent, path }) => { - const codec = - "id" in entry - ? dynCodecs(entry.id) - : getInnerEnumCodec( - dynCodecs(parent!.id), - parent!.variantIdx, - parent!.variantTag, - ) - - const createDecode = (decoder: scale.Decoder) => - scale.createDecoder((bytes) => { - try { - const result = decoder(bytes) - return bytes.length === (bytes as Uint8Array & { i: number }).i - ? result - : NOTIN - } catch { - return NOTIN - } - }) - const decode = createDecode(codec.dec) - - let valueProps: - | { type: "blank"; value: NOTIN; encodedValue: undefined } - | { type: "partial"; value: any; encodedValue: undefined } - | { type: "complete"; value: any; encodedValue: Uint8Array } = { - type: "blank" as const, - value: NOTIN, - encodedValue: undefined, - } - if (!value.empty) { - const encodedValue = value.encoded || withNotin(codec.enc)(value.decoded) - valueProps = encodedValue - ? { type: "complete", value: value.decoded, encodedValue } - : { type: "partial", value: value.decoded, encodedValue: undefined } - } - - if (entry.type === "struct") { - const latestValue = value.empty - ? mapObject(entry.value, () => NOTIN) - : value.decoded - return ( - ( - { - const value = { ...latestValue } - value[key] = x - return onChange(value) - }} - value={ - latestValue[key] === NOTIN - ? { empty: true } - : { - empty: false, - decoded: latestValue[key], - } - } - /> - ))} - /> - ) - } - - if (entry.type === "tuple") { - const latestValue = value.empty - ? entry.value.map(() => NOTIN) - : value.decoded - return ( - ( - { - const value = [...latestValue] - value[idx] = x - return onChange(value) - }} - value={ - value.empty - ? value - : value.decoded[idx] === NOTIN - ? { empty: true } - : { - empty: false, - decoded: value.decoded[idx], - } - } - /> - )), - }} - /> - ) - } - - if (entry.type === "enum") { - let innerEntry - if (!value.empty) { - innerEntry = entry.value[value.decoded.type as string] - if (innerEntry?.type === "lookupEntry") - innerEntry = innerEntry.value as any - if (!innerEntry) { - valueProps = { type: "blank", value: NOTIN, encodedValue: undefined } - value = { empty: true } - } - } - return ( - ({ - tag, - idx, - })), - shape: entry, - inner: value.empty ? null : ( - - onChange({ type: value.decoded.type, value: x }) - } - parent={{ - id: entry.id, - variantTag: value.decoded.type, - variantIdx: - entry.value[value.decoded.type as keyof typeof entry.value] - .idx, - }} - value={ - value.decoded.value === NOTIN - ? { empty: true } - : { - empty: false, - decoded: value.decoded.value, - encoded: - (valueProps as any).encodedValue && - (valueProps as any).encodedValue.slice(1), - } - } - /> - ), - }} - /> - ) - } - - if (entry.type === "result") { - return ( - - onChange({ success: value.decoded.success, value: x }) - } - dynCodecs={dynCodecs} - entry={entry.value[value.decoded.success ? "ok" : "ko"]} - value={ - value.decoded.value === NOTIN - ? { empty: true } - : { empty: false, decoded: value.decoded.value } - } - /> - ), - }} - /> - ) - } - - if (entry.type === "option") { - return ( - - ) : ( - - ), - }} - /> - ) - } - - if (entry.type === "void") return - - if (entry.type === "array") { - if (entry.value.type === "primitive" && entry.value.value === "u8") { - const decoder = Bytes(entry.len)[1] - return ( - - ) - } - - const latestValue = value.empty - ? Array(entry.len).fill(NOTIN) - : (value.decoded as Array) - return ( - ( - { - const value = [...latestValue] - value[idx] = x - return onChange(value) - }} - value={ - decoded === NOTIN - ? { empty: true } - : { empty: false, decoded } - } - /> - )), - }} - /> - ) - } - - if (entry.type === "sequence") { - if (entry.value.type === "primitive" && entry.value.value === "u8") { - const decoder = Bytes()[1] - return ( - - ) - } - - const latestValue = value.empty ? [] : (value.decoded as Array) - return ( - ( - { - const value = [...latestValue] - value[idx] = x - return onChange(value) - }} - value={ - decoded === NOTIN - ? { empty: true } - : { empty: false, decoded } - } - /> - )), - }} - /> - ) - } - - let type: any = undefined - let ResultComponent: - | EditBigNumber - | EditNumber - | EditBool - | EditStr - | EditAccountId - | EditEthAccount = null as any - - switch (entry.type) { - case "compact": { - ResultComponent = entry.isBig ? CBigNumber : CNumber - type = entry.size - break - } - case "primitive": { - if (entry.value === "str" || entry.value === "char") - ResultComponent = CStr - else if (entry.value === "bool") ResultComponent = CBool - else { - const nBits = Number(entry.value.slice(1)) - ResultComponent = nBits < 64 ? CNumber : CBigNumber - type = entry.value - } - break - } - case "bitSequence": { - return null - } - case "AccountId32": { - ResultComponent = CAccountId - break - } - case "AccountId20": { - ResultComponent = CEthAccount - break - } - } - - const Result = ResultComponent as FC - return ( - - ) - } - - const result: FC<{ - metadata: V14 | V15 - codecType: number - value: CodecComponentValue - onUpdate: (newValue: CodecComponentUpdate) => void - }> = ({ metadata, codecType, value: propsValue, onUpdate }) => { - const lookupRef = useRef<{ - metadata: V14 | V15 - lookup: MetadataLookup - dynCodecs: ReturnType["buildDefinition"] - refresh: ( - codecType: number, - value?: Uint8Array | HexString, - ) => - | { empty: true } - | { empty: false; decoded: any; encoded?: Uint8Array } - }>({ - metadata: null as any, - lookup: null as any, - dynCodecs: null as any, - refresh: () => ({ empty: true }), - }) - - if (lookupRef.current.metadata !== metadata) { - const lookup = getLookupFn(metadata) - lookupRef.current = { - metadata, - lookup, - dynCodecs: getDynamicBuilder(lookup).buildDefinition, - refresh: (codecType, val) => { - try { - return val - ? { - empty: false, - decoded: lookupRef.current.dynCodecs(codecType).dec(val), - encoded: typeof val === "string" ? fromHex(val) : val, - } - : { empty: true } - } catch (_error) { - console.error("invalid hex for the codec") - return { empty: true } - } - }, - } - } - - const value = - propsValue.type === CodecComponentType.Initial - ? lookupRef.current.refresh( - codecType, - propsValue.value as CodecComponentInitial, - ) - : propsValue.value - - return ( - { - if (x === NOTIN) { - onUpdate({ empty: true }) - return true - } - - let encoded = undefined - const hasNotin = detectNotin(x) - if (!hasNotin) { - try { - encoded = lookupRef.current.dynCodecs(codecType).enc(x) - } catch (_e) { - console.warn("Error encoding", x) - return false - } - } - onUpdate({ empty: false, decoded: x, encoded }) - return true - }} - {...{ - dynCodecs: lookupRef.current.dynCodecs, - entry: lookupRef.current.lookup(codecType), - value: value, - }} - /> - ) - } - - return result as any -} diff --git a/src/lib/codecComponents/index.ts b/src/lib/codecComponents/index.ts deleted file mode 100644 index fa9a7d1..0000000 --- a/src/lib/codecComponents/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from "./types" -export * from "./get-codec-component" diff --git a/src/lib/codecComponents/types/edit-component-types.ts b/src/lib/codecComponents/types/edit-component-types.ts deleted file mode 100644 index 4449abe..0000000 --- a/src/lib/codecComponents/types/edit-component-types.ts +++ /dev/null @@ -1,144 +0,0 @@ -import type { - ArrayVar, - EnumVar, - OptionVar, - ResultVar, - SequenceVar, - StructVar, - TupleVar, -} from "@polkadot-api/metadata-builders" -import type { - Binary, - HexString, - SS58String, -} from "@polkadot-api/substrate-bindings" -import type { ReactNode, FC } from "react" - -export const NOTIN = Symbol("Notin") -export type NOTIN = typeof NOTIN - -export type EditComplexCodecComponentProps = ( - | { type: "blank"; value: NOTIN; encodedValue: undefined } - | { type: "partial"; value: T; encodedValue: undefined } - | { type: "complete"; value: T; encodedValue: Uint8Array } -) & { - path: string[] - onValueChanged: (newValue: T | NOTIN) => boolean - decode: (value: Uint8Array | HexString) => T | NOTIN -} - -export type EditPrimitiveComponentProps = ( - | { type: "blank"; value: NOTIN; encodedValue: undefined } - | { type: "complete"; value: T; encodedValue: Uint8Array } -) & { - path: string[] - onValueChanged: (newValue: T | NOTIN) => boolean - decode: (value: Uint8Array | HexString) => T | NOTIN -} - -export type EditVoidInterface = {} -export type EditVoid = FC - -export type EditAccountIdInterface = EditPrimitiveComponentProps -export type EditAccountId = FC - -export type EditBigNumberInterface = EditPrimitiveComponentProps & { - numType: "u64" | "u128" | "u256" | "i64" | "i128" | "i256" -} -export type EditBigNumber = FC - -export type EditNumberInterface = EditPrimitiveComponentProps & { - numType: "u8" | "u16" | "u32" | "i8" | "i16" | "i32" -} -export type EditNumber = FC - -export type EditBoolInterface = EditPrimitiveComponentProps -export type EditBool = FC - -export type EditStrInterface = EditPrimitiveComponentProps -export type EditStr = FC - -export type EditBytesInterface = EditPrimitiveComponentProps & { - len?: number -} -export type EditBytes = FC - -export type EditEthAccountInterface = EditPrimitiveComponentProps -export type EditEthAccount = FC - -export type EditEnumInterface = EditComplexCodecComponentProps<{ - type: string - value: any -}> & { - tags: Array<{ idx: number; tag: string }> - inner: ReactNode - shape: EnumVar -} -export type EditEnum = FC - -export type EditSequenceInterface = EditComplexCodecComponentProps< - Array -> & { - innerComponents: Array - shape: SequenceVar -} -export type EditSequence = FC - -export type EditArrayInterface = EditComplexCodecComponentProps< - Array -> & { - innerComponents: Array - shape: ArrayVar -} -export type EditArray = FC - -export type EditTupleInterface = EditComplexCodecComponentProps< - Array -> & { - innerComponents: Array - shape: TupleVar -} -export type EditTuple = FC - -export type EditStructInterface = EditComplexCodecComponentProps< - Record -> & { - innerComponents: Record - shape: StructVar -} -export type EditStruct = FC - -export type EditOptionInterface = EditComplexCodecComponentProps< - T | undefined -> & { - inner: ReactNode - shape: OptionVar -} -export type EditOption = FC - -export type EditResultInterface = EditComplexCodecComponentProps<{ - success: boolean - value: any -}> & { - shape: ResultVar - inner: ReactNode -} -export type EditResult = FC - -export interface EditComponents { - CVoid: EditVoid - CAccountId: EditAccountId - CBigNumber: EditBigNumber - CNumber: EditNumber - CBool: EditBool - CStr: EditStr - CBytes: EditBytes - CEthAccount: EditEthAccount - CEnum: EditEnum - CSequence: EditSequence - CArray: EditArray - CTuple: EditTuple - CStruct: EditStruct - COption: EditOption - CResult: EditResult -} diff --git a/src/lib/codecComponents/types/index.ts b/src/lib/codecComponents/types/index.ts deleted file mode 100644 index e0e1c6d..0000000 --- a/src/lib/codecComponents/types/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from "./edit-component-types" -export * from "./view-component-types" diff --git a/src/lib/codecComponents/types/view-component-types.ts b/src/lib/codecComponents/types/view-component-types.ts deleted file mode 100644 index 545c243..0000000 --- a/src/lib/codecComponents/types/view-component-types.ts +++ /dev/null @@ -1,126 +0,0 @@ -import type { - ArrayVar, - EnumVar, - OptionVar, - ResultVar, - SequenceVar, - StructVar, - TupleVar, -} from "@polkadot-api/metadata-builders" -import type { - Binary, - HexString, - SS58String, -} from "@polkadot-api/substrate-bindings" -import type { ReactNode, FC } from "react" - -export type ViewCodecComponentProps = { - value: T - encodedValue: Uint8Array - path: string[] -} - -export type ViewPrimitiveComponentProps = ViewCodecComponentProps - -export type ViewVoidInterface = {} -export type ViewVoid = FC - -export type ViewAccountIdInterface = ViewPrimitiveComponentProps -export type ViewAccountId = FC - -export type ViewBigNumberInterface = ViewPrimitiveComponentProps & { - numType: "u64" | "u128" | "u256" | "i64" | "i128" | "i256" -} -export type ViewBigNumber = FC - -export type ViewNumberInterface = ViewPrimitiveComponentProps & { - numType: "u8" | "u16" | "u32" | "i8" | "i16" | "i32" -} -export type ViewNumber = FC - -export type ViewBoolInterface = ViewPrimitiveComponentProps -export type ViewBool = FC - -export type ViewStrInterface = ViewPrimitiveComponentProps -export type ViewStr = FC - -export type ViewBytesInterface = ViewPrimitiveComponentProps & { - len?: number -} -export type ViewBytes = FC - -export type ViewEthAccountInterface = ViewPrimitiveComponentProps -export type ViewEthAccount = FC - -export type ViewEnumInterface = ViewCodecComponentProps<{ - type: string - value: any -}> & { - tags: Array<{ idx: number; tag: string }> - inner: ReactNode - shape: EnumVar -} -export type ViewEnum = FC - -export type ViewSequenceInterface = ViewCodecComponentProps< - Array -> & { - innerComponents: Array - shape: SequenceVar -} -export type ViewSequence = FC - -export type ViewArrayInterface = ViewCodecComponentProps> & { - innerComponents: Array - shape: ArrayVar -} -export type ViewArray = FC - -export type ViewTupleInterface = ViewCodecComponentProps> & { - innerComponents: Array - shape: TupleVar -} -export type ViewTuple = FC - -export type ViewStructInterface = ViewCodecComponentProps< - Record -> & { - innerComponents: Record - shape: StructVar -} -export type ViewStruct = FC - -export type ViewOptionInterface = ViewCodecComponentProps< - T | undefined -> & { - inner: ReactNode - shape: OptionVar -} -export type ViewOption = FC - -export type ViewResultInterface = ViewCodecComponentProps<{ - success: boolean - value: any -}> & { - shape: ResultVar - inner: ReactNode -} -export type ViewResult = FC - -export interface ViewComponents { - CVoid: ViewVoid - CAccountId: ViewAccountId - CBigNumber: ViewBigNumber - CNumber: ViewNumber - CBool: ViewBool - CStr: ViewStr - CBytes: ViewBytes - CEthAccount: ViewEthAccount - CEnum: ViewEnum - CSequence: ViewSequence - CArray: ViewArray - CTuple: ViewTuple - CStruct: ViewStruct - COption: ViewOption - CResult: ViewResult -} diff --git a/src/pages/Constants.tsx b/src/pages/Constants.tsx index 7f0e5cb..54d981d 100644 --- a/src/pages/Constants.tsx +++ b/src/pages/Constants.tsx @@ -6,7 +6,7 @@ import { ExpandBtn } from "@/components/Expand" import { LoadingMetadata } from "@/components/Loading" import { Tooltip } from "@/components/Tooltip" import { withSubscribe } from "@/components/withSuspense" -import { CodecComponentType } from "@/lib/codecComponents" +import { CodecComponentType } from "@polkadot-api/react-builder" import { getTypeComplexity } from "@/utils/shape" import { state, useStateObservable } from "@react-rxjs/core" import { Dot } from "lucide-react" diff --git a/src/pages/Extrinsics/EditMode.tsx b/src/pages/Extrinsics/EditMode.tsx index b22117d..ff6616f 100644 --- a/src/pages/Extrinsics/EditMode.tsx +++ b/src/pages/Extrinsics/EditMode.tsx @@ -12,7 +12,7 @@ import { CodecComponentUpdate, CodecComponentValue, MetadataType, -} from "@codec-components" +} from "@polkadot-api/react-builder" import { useEffect, useRef, useState } from "react" export const EditMode: React.FC<{ diff --git a/src/pages/Extrinsics/Extrinsics.tsx b/src/pages/Extrinsics/Extrinsics.tsx index 9845c27..005bb7c 100644 --- a/src/pages/Extrinsics/Extrinsics.tsx +++ b/src/pages/Extrinsics/Extrinsics.tsx @@ -3,7 +3,7 @@ import { BinaryDisplay } from "@/codec-components/LookupTypeEdit" import { ButtonGroup } from "@/components/ButtonGroup" import { LoadingMetadata } from "@/components/Loading" import { withSubscribe } from "@/components/withSuspense" -import { CodecComponentType, CodecComponentValue } from "@codec-components" +import { CodecComponentType, CodecComponentValue } from "@polkadot-api/react-builder" import { Binary } from "@polkadot-api/substrate-bindings" import { state, useStateObservable } from "@react-rxjs/core" import { useState } from "react" diff --git a/src/pages/Storage/StorageDecode.tsx b/src/pages/Storage/StorageDecode.tsx index 4911f00..c6900e2 100644 --- a/src/pages/Storage/StorageDecode.tsx +++ b/src/pages/Storage/StorageDecode.tsx @@ -1,6 +1,6 @@ import { dynamicBuilder$ } from "@/chain.state" import { ActionButton } from "@/components/ActionButton" -import { NOTIN } from "@codec-components" +import { NOTIN } from "@polkadot-api/react-builder" import { state, useStateObservable } from "@react-rxjs/core" import { createSignal } from "@react-rxjs/utils" import { FC } from "react" diff --git a/src/pages/Storage/StorageQuery.tsx b/src/pages/Storage/StorageQuery.tsx index f4f1f63..ac5f570 100644 --- a/src/pages/Storage/StorageQuery.tsx +++ b/src/pages/Storage/StorageQuery.tsx @@ -8,7 +8,7 @@ import { CodecComponentType, CodecComponentValue, NOTIN, -} from "@codec-components" +} from "@polkadot-api/react-builder" import { state, useStateObservable, withDefault } from "@react-rxjs/core" import { createSignal } from "@react-rxjs/utils" import { Binary } from "polkadot-api" diff --git a/src/pages/Storage/StorageSubscriptions.tsx b/src/pages/Storage/StorageSubscriptions.tsx index e7e73a6..3def7c8 100644 --- a/src/pages/Storage/StorageSubscriptions.tsx +++ b/src/pages/Storage/StorageSubscriptions.tsx @@ -3,7 +3,7 @@ import { ViewCodec } from "@/codec-components/ViewCodec" import { CopyBinary } from "@/codec-components/ViewCodec/CopyBinary" import { ButtonGroup } from "@/components/ButtonGroup" import { JsonDisplay } from "@/components/JsonDisplay" -import { CodecComponentType, NOTIN } from "@codec-components" +import { CodecComponentType, NOTIN } from "@polkadot-api/react-builder" import { state, useStateObservable } from "@react-rxjs/core" import { PauseCircle, PlayCircle, Trash2 } from "lucide-react" import { FC, useMemo, useState } from "react" diff --git a/src/utils/default.tsx b/src/utils/default.tsx index 3cfcb2d..3728bb2 100644 --- a/src/utils/default.tsx +++ b/src/utils/default.tsx @@ -1,4 +1,4 @@ -import { NOTIN } from "@codec-components" +import { NOTIN } from "@polkadot-api/react-builder" export const withDefault: (value: T | NOTIN, fallback: T) => T = ( value, diff --git a/tsconfig.app.json b/tsconfig.app.json index c7118ba..0c927c8 100644 --- a/tsconfig.app.json +++ b/tsconfig.app.json @@ -22,8 +22,7 @@ "noFallthroughCasesInSwitch": true, "paths": { - "@/*": ["./src/*"], - "@codec-components": ["./src/lib/codecComponents"] + "@/*": ["./src/*"] } }, "include": ["src"] diff --git a/vite.config.ts b/vite.config.ts index 0d1ff40..edc93c5 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -7,7 +7,6 @@ export default defineConfig({ resolve: { alias: { "@": path.resolve(__dirname, "./src"), - "@codec-components": path.resolve(__dirname, "./src/lib/codecComponents"), }, }, plugins: [react()],