Skip to content

Commit

Permalink
feat: add DecodedCallData component
Browse files Browse the repository at this point in the history
  • Loading branch information
kratico committed Feb 29, 2024
1 parent 5a9085c commit c0cf45a
Show file tree
Hide file tree
Showing 5 changed files with 168 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ export const createBackgroundRpc = (
txCreator.destroy()
return tx
},
async getSignRequests([], { signRequests }) {
async getSignRequests(_, { signRequests }) {
return signRequests
},
async approveSignRequest([id], { signRequests }) {
Expand Down
24 changes: 12 additions & 12 deletions projects/wallet-template/src/containers/WalletPopup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,34 +33,34 @@ export const WalletPopup = () => {
<h1 className="text-3xl font-bold">Sign Request #{signRequestId}</h1>
<div className="my-4">
<div className="my-2">
<div className="text-sm font-semibold">Origin</div>
<div>{signRequest.url}</div>
<div className="text-xs font-semibold">Origin</div>
<div className="text-sm">{signRequest.url}</div>
</div>
<div className="my-2 overflow-hidden">
<div className="text-sm font-semibold">Chain Id</div>
<pre className="overflow-auto">{signRequest.chainId}</pre>
<div className="text-xs font-semibold">Chain Id</div>
<pre className="text-sm overflow-auto">{signRequest.chainId}</pre>
</div>
<div className="my-2">
<div className="text-sm font-semibold">From</div>
<pre>{signRequest.address}</pre>
<div className="text-xs font-semibold">From</div>
<pre className="text-sm">{signRequest.address}</pre>
</div>
<div className="my-2 overflow-hidden">
<div className="text-sm font-semibold">Call data</div>
<pre className="overflow-auto">{signRequest.callData}</pre>
<div className="text-xs font-semibold">Call data</div>
<pre className="text-sm overflow-auto">{signRequest.callData}</pre>
</div>
<div className="my-2">
<div className="text-sm font-semibold">Decoded Call data</div>
<div className="text-xs font-semibold">Decoded Call data</div>
<DecodedCallData
chainId={signRequest.chainId}
callData={signRequest.callData}
/>
</div>
<div className="my-2">
<div className="text-sm font-semibold">Signed extensions</div>
<div>coming soon...</div>
<div className="text-xs font-semibold">Signed extensions</div>
<div className="text-sm">coming soon...</div>
</div>
</div>
<div className="my-4 text-center">
<div className="flex justify-center space-x-4">
<button
onClick={() => rpc.client.approveSignRequest(signRequestId)}
className="py-1.5 px-8 mr-4 text-sm rounded border border-[#24cc85] text-[#24cc85] hover:text-white
Expand Down
Original file line number Diff line number Diff line change
@@ -1,26 +1,170 @@
import type {
ComplexDecoded,
Decoded,
PrimitiveDecoded,
} from "@polkadot-api/metadata-builders"
import { toHex } from "@polkadot-api/utils"
import { useDecodedCallData } from "../hooks"

type Props = {
chainId: string
callData: string
}

const jsonStringify = (value: any) =>
JSON.stringify(
value,
(_, value) => (typeof value === "bigint" ? value.toString() : value),
2,
)

type Props = {
chainId: string
callData: string
}
export const DecodedCallData = ({ chainId, callData }: Props) => {
const { decodedCallData } = useDecodedCallData(chainId, callData)
if (!decodedCallData) return <div>decoding...</div>
return (
<div>
<div className="text-sm">Pallet: {decodedCallData.pallet.value.name}</div>
<div className="text-sm">Call: {decodedCallData.call.value.name}</div>
<div className="text-sm">Args</div>
<pre>{jsonStringify(decodedCallData?.args.value)}</pre>
<div className="text-xs font-semibold">Pallet Call</div>
<div className="px-2">
{decodedCallData.pallet.value.name} {decodedCallData.call.value.name}
</div>
<div className="text-xs font-semibold">Args</div>
<DecodedValue value={decodedCallData.args.value} />
</div>
)
}

type DecodedValueProps = {
value: Decoded
}
const DecodedValue = ({ value }: DecodedValueProps) => (
<div className="px-2">
{isPrimitiveDecoded(value) ? (
<DecodedPrimitiveValue value={value} />
) : (
<DecodedComplexValue value={value} />
)}
</div>
)

type DecodedPrimitiveProps = {
value: PrimitiveDecoded
}
const DecodedPrimitiveValue = ({ value }: DecodedPrimitiveProps) => {
switch (value.codec) {
case "_void": {
return <div>void</div>
}
case "bool":
case "char":
case "str":
case "Bytes":
case "BytesArray": {
return <div>{value.value}</div>
}
case "AccountId": {
return <div>{value.value.address}</div>
}
case "bitSequence": {
// FIXME: improve bitsequence UI
// for example: n1,n2,...,n
return (
<div>
BitSequence: {toHex(value.value.bytes)}({value.value.bitsLen})
</div>
)
}
case "compactBn":
case "compactNumber":
case "i128":
case "i16":
case "i256":
case "i32":
case "i64":
case "i8":
case "u128":
case "u16":
case "u256":
case "u32":
case "u64":
case "u8":

default:

Check warning on line 90 in projects/wallet-template/src/containers/WalletPopup/components/DecodedCallData.tsx

View workflow job for this annotation

GitHub Actions / build (18.x)

Expected a 'break' statement before 'default'

Check warning on line 90 in projects/wallet-template/src/containers/WalletPopup/components/DecodedCallData.tsx

View workflow job for this annotation

GitHub Actions / build (20.x)

Expected a 'break' statement before 'default'

Check warning on line 90 in projects/wallet-template/src/containers/WalletPopup/components/DecodedCallData.tsx

View workflow job for this annotation

GitHub Actions / connect-flaky-tests

Expected a 'break' statement before 'default'

Check warning on line 90 in projects/wallet-template/src/containers/WalletPopup/components/DecodedCallData.tsx

View workflow job for this annotation

GitHub Actions / playwright-test-extension

Expected a 'break' statement before 'default'

Check warning on line 90 in projects/wallet-template/src/containers/WalletPopup/components/DecodedCallData.tsx

View workflow job for this annotation

GitHub Actions / playwright-test-examples

Expected a 'break' statement before 'default'

Check warning on line 90 in projects/wallet-template/src/containers/WalletPopup/components/DecodedCallData.tsx

View workflow job for this annotation

GitHub Actions / playwright-test-wallet-template

Expected a 'break' statement before 'default'

Check warning on line 90 in projects/wallet-template/src/containers/WalletPopup/components/DecodedCallData.tsx

View workflow job for this annotation

GitHub Actions / zombienet-tests

Expected a 'break' statement before 'default'
return <div>{value.value.toString()}</div>
}
}

type DecodedComplexProps = {
value: ComplexDecoded
}
const DecodedComplexValue = ({ value }: DecodedComplexProps) => {
switch (value.codec) {
case "Tuple":
case "Sequence":
case "Array": {
return value.value.map((value) => <DecodedValue value={value} />)
}
case "Enum": {
return (
<>
<div className="text-xs">{value.value.type}</div>
<DecodedValue value={value.value.value} />
</>
)
}
case "Option": {
// FIXME: What Option variant is value (Some or None)?
return value.value.codec === "_void" ? (
<div>None</div>
) : (
<DecodedValue value={value.value} />
)
}
case "Result": {
// FIXME: What Result variant is value (Ok or Error)?
return (
<>
<div className="text-xs">Ok</div>
<DecodedValue value={value.value.ok} />
<div className="text-xs">Error</div>
<DecodedValue value={value.value.ko} />
</>
)
}
case "Struct": {
return Object.entries(value.value).map(([key, value]) => (
<div>
<div className="text-xs">{key}</div>
<DecodedValue value={value} />
</div>
))
}
default:
return <pre className="text-xs">{jsonStringify(value)}</pre>
}
}

const PRIMITIVE_CODECS: PrimitiveDecoded["codec"][] = [
"bool",
"char",
"str",
"u8",
"u16",
"u32",
"u64",
"u128",
"u256",
"i8",
"i16",
"i32",
"i64",
"i128",
"i256",
"bitSequence",
"_void",
"compactNumber",
"compactBn",
"Bytes",
"BytesArray",
"AccountId",
]
const isPrimitiveDecoded = (value: Decoded): value is PrimitiveDecoded =>
PRIMITIVE_CODECS.includes(value.codec as PrimitiveDecoded["codec"])
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export const useDecodedCallData = (chainId: string, callData: string) => {
if (!isMounted()) return
setDecodedCallData(builder.callDecoder(callData))
})
}, [chainId, callData])
}, [chainId, callData, isMounted])

return { decodedCallData }
}
2 changes: 1 addition & 1 deletion projects/wallet-template/src/hooks/useActiveChains.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ const createChainDetailObservable = (chain: PageChain) =>
share(),
)
const bestBlockHeight$ = followAndBestBlocksWithRetry$.pipe(
map(([_, bestBlocks]) => bestBlocks[0]?.header.number),
map(([_, bestBlocks]) => bestBlocks[0]?.number),
filter(Boolean),
startWith(undefined),
)
Expand Down

0 comments on commit c0cf45a

Please sign in to comment.