ghost-extension-wallet/src/containers/WalletPopup/pages/SignRequest.tsx
Uncle Fatso cad8fa9f8d
explicit error handling during sign request
Signed-off-by: Uncle Fatso <uncle.fatso@ghostchain.io>
2025-11-29 13:11:08 +03:00

138 lines
5.7 KiB
TypeScript

import { useState } from "react"
import { useParams } from "react-router-dom"
import useSWR from "swr"
import { rpc } from "../api"
import { UserSignedExtensions as UserSignedExtensionsTy } from "@/types/UserSignedExtension"
import { wellKnownChainIdByGenesisHash } from "@/constants"
import { Layout } from "@/components/Layout"
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { ScrollArea } from "@/components/ui/scroll-area"
import { Textarea } from "@/components/ui/textarea"
import {
DecodedCallData,
UserSignedExtensionInputs,
UserSignedExtensions,
} from "../components"
export const SignRequest = () => {
const { signRequestId } = useParams<{ signRequestId: string }>()
const [userSignedExtensions, setUserSignedExtensions] = useState<Partial<UserSignedExtensionsTy>>({})
const {
data: signRequests,
error,
isLoading,
} = useSWR(signRequestId ? ["getSignRequest"] : null, () =>
rpc.client.getSignRequests(),
)
if (!signRequestId) {
window.close()
return null
}
if (isLoading) {
return (
<Layout>
<h1 className="text-3xl font-bold mb-6 px-6">Loading Sign Request #{signRequestId}</h1>
</Layout>
)
}
const request = signRequests?.[signRequestId]
if (error || !request) {
return (
<Layout>
<h1>Could not parse the sign request #{signRequestId}</h1>
<br />
Error: {error?.message}
</Layout>
)
}
return (
<Layout>
<h1 className="text-3xl font-bold mb-6 px-6">Sign Request #{signRequestId}</h1>
<ScrollArea className="px-6 mb-4 grow sm:px-8">
<section>
<div className="my-4">
<div className="my-2">
<div className="text-xs font-semibold mb-2 mt-4">Origin</div>
<Input
readOnly
aria-label="Request Origin"
type="text"
className="pr-10"
placeholder={request.url}
/>
</div>
<div className="my-2 overflow-hidden">
<div className="text-xs font-semibold mb-2 mt-4">Chain</div>
<Input
readOnly
aria-label="Request Origin"
type="text"
className="pr-10"
placeholder={wellKnownChainIdByGenesisHash[request.chainId]}
/>
</div>
<div className="my-2">
<div className="text-xs font-semibold mb-2 mt-4">From Address</div>
<Input
readOnly
aria-label="From Address"
type="text"
className="pr-10"
placeholder={request.address}
/>
</div>
<div className="my-2 overflow-hidden">
<div className="text-xs font-semibold mb-2 mt-4">Call data</div>
<Textarea
readOnly
aria-label="Call data"
rows={6}
className="text-sm text-justify resize-none"
placeholder={request.callData}
/>
</div>
<div className="my-2">
<div className="text-xs font-semibold mb-2 mt-4">Decoded Call data</div>
<DecodedCallData chainId={request.chainId} callData={request.callData} />
</div>
<div className="my-2">
{request.userSignedExtensions.type === "names" ? (
<UserSignedExtensionInputs
userSignedExtensionNames={request.userSignedExtensions.names}
onChange={setUserSignedExtensions}
/>
) : (
<UserSignedExtensions
userSignedExtensions={request.userSignedExtensions.values}
/>
)}
</div>
</div>
<div className="w-full flex gap-4 justify-center space-x-4 pt-6">
<Button
variant="secondary"
size="full"
className="h-12"
onClick={() => rpc.client.approveSignRequest(signRequestId, userSignedExtensions)}
>
Approve
</Button>
<Button
variant="secondary"
size="full"
className="h-12"
onClick={() => rpc.client.cancelSignRequest(signRequestId)}
>
Cancel
</Button>
</div>
</section>
</ScrollArea>
</Layout>
)
}