mirror of
https://github.com/luxfhe/example-smart-wallet.git
synced 2026-10-30 18:13:16 +00:00
173 lines
6.0 KiB
TypeScript
173 lines
6.0 KiB
TypeScript
"use client";
|
|
|
|
import { InputBase } from "../scaffold-eth";
|
|
import { PermitTypeIcon, PermitTypeText } from "./PermitTypeComponents";
|
|
import { PermitV2 } from "~~/permits/permitV2";
|
|
import truncateAddress from "~~/utils/truncate-address";
|
|
import { usePermitSatisfiesRequirements } from "~~/services/store/permitModalStore";
|
|
import { formattedTimestamp, getTimestamp, timeUntilTimestamp } from "./utils";
|
|
|
|
export type ValidityState = "error" | "warning" | "success";
|
|
export const ValidityIndicator: React.FC<{
|
|
validity: ValidityState;
|
|
validLabel?: string;
|
|
warningLabel?: string;
|
|
invalidLabel?: string;
|
|
}> = ({ validity, validLabel, warningLabel, invalidLabel }) => {
|
|
return (
|
|
<div className="flex flex-row gap-2 items-center justify-center text-sm">
|
|
<div
|
|
className={`w-3 h-3 rounded-full ${
|
|
validity === "success"
|
|
? "bg-bg-surface-success"
|
|
: validity === "warning"
|
|
? "bg-bg-surface-warning"
|
|
: "bg-bg-surface-error"
|
|
}`}
|
|
/>
|
|
{validity === "success" && validLabel}
|
|
{validity === "warning" && warningLabel}
|
|
{validity === "error" && invalidLabel}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export const PermitTypeDisplayRow: React.FC<{ permit: PermitV2 }> = ({ permit }) => {
|
|
return (
|
|
<div className="flex flex-row items-center justify-between gap-4">
|
|
<div className="text-sm font-bold">Purpose:</div>
|
|
<div className="flex flex-row items-center justify-center gap-2 text-sm">
|
|
<PermitTypeIcon type={permit.type} />
|
|
<PermitTypeText type={permit.type} />
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export const PermitNameEditableDisplayRow: React.FC<{
|
|
name: string;
|
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
onUpdateName: (name: string) => void;
|
|
}> = ({ name, onUpdateName }) => {
|
|
return (
|
|
<div className="flex flex-row items-center justify-between gap-4">
|
|
<div className="text-sm font-bold">Name: (editable)</div>
|
|
<InputBase
|
|
name="permit-editable-display-name"
|
|
value={name}
|
|
placeholder="Unnamed Permit"
|
|
onChange={onUpdateName} // (value: string) => updatePermitName(address, permit.getHash(), value)}
|
|
inputClassName="text-right"
|
|
/>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export const PermitIssuerDisplayRow: React.FC<{ permit: PermitV2 }> = ({ permit }) => {
|
|
if (permit.type !== "recipient") return;
|
|
|
|
return (
|
|
<div className="flex flex-row items-center justify-between gap-4">
|
|
<div className={`text-sm font-bold`}>Issuer:</div>
|
|
<div className="text-sm">{truncateAddress(permit.issuer)}</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export const PermitRecipientDisplayRow: React.FC<{ permit: PermitV2 }> = ({ permit }) => {
|
|
if (permit.type === "self") return;
|
|
|
|
return (
|
|
<div className="flex flex-row items-center justify-between gap-4">
|
|
<div className={`text-sm font-bold`}>Recipient:</div>
|
|
<div className="text-sm">{truncateAddress(permit.recipient)}</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export const PermitExpirationDisplayRow: React.FC<{ permit: PermitV2 }> = ({ permit }) => {
|
|
const timestamp = getTimestamp();
|
|
const expired = permit.expiration <= timestamp;
|
|
|
|
return (
|
|
<div className="flex flex-row items-center justify-between gap-4">
|
|
<div className="text-sm font-bold">Expiration:</div>
|
|
<ValidityIndicator
|
|
validity={expired ? "error" : "success"}
|
|
validLabel={`${formattedTimestamp(permit.expiration)} (in ${timeUntilTimestamp(permit.expiration)})`}
|
|
invalidLabel={`Expired on ${formattedTimestamp(permit.expiration)}`}
|
|
/>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
const AccessItem: React.FC<{ children: React.ReactNode }> = ({ children }) => {
|
|
return <div className="text-sm px-2 border-primary border-2">{children}</div>;
|
|
};
|
|
|
|
const PermitContractsDisplayRow: React.FC<{ permit: PermitV2 }> = ({ permit }) => {
|
|
if (permit.contracts.length === 0) return;
|
|
|
|
return (
|
|
<div className="flex flex-row items-center justify-between flex-wrap">
|
|
<div className={`text-sm font-bold ml-4 mr-4`}>Contracts:</div>
|
|
{permit.contracts.map(contract => (
|
|
<AccessItem key={contract}>{truncateAddress(contract)}</AccessItem>
|
|
))}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
const PermitProjectsDisplayRow: React.FC<{ permit: PermitV2 }> = ({ permit }) => {
|
|
if (permit.projects.length === 0) return;
|
|
|
|
return (
|
|
<div className="flex flex-row items-center justify-between flex-wrap">
|
|
<div className={`text-sm font-bold ml-4 mr-4`}>Projects:</div>
|
|
{permit.projects.map(project => (
|
|
<AccessItem key={project}>{project}</AccessItem>
|
|
))}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export const PermitAccessDisplayRow: React.FC<{ permit: PermitV2 }> = ({ permit }) => {
|
|
const satisfies = usePermitSatisfiesRequirements(permit);
|
|
|
|
return (
|
|
<div className="flex flex-col w-full">
|
|
<div className={`text-sm font-bold`}>Access:</div>
|
|
|
|
{/* Access requirements not satisfied */}
|
|
{!satisfies && <span className="italic text-sm text-error"> ! dApp{"'"}s access requirements not met !</span>}
|
|
|
|
<PermitContractsDisplayRow permit={permit} />
|
|
<PermitProjectsDisplayRow permit={permit} />
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export const SignatureValidityIndicator: React.FC<{ validity: ValidityState }> = ({ validity }) => {
|
|
return <ValidityIndicator validity={validity} validLabel="Valid" invalidLabel="Missing" />;
|
|
};
|
|
|
|
export const PermitIssuerSignatureDisplayRow: React.FC<{ permit: PermitV2 }> = ({ permit }) => {
|
|
return (
|
|
<div className="flex flex-row items-center justify-between gap-4">
|
|
<div className="text-sm font-bold">{permit.type === "recipient" && "Issuer "}Signature:</div>
|
|
<SignatureValidityIndicator validity={permit.issuerSignature !== "0x" ? "success" : "error"} />
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export const PermitRecipientSignatureDisplayRow: React.FC<{ permit: PermitV2 }> = ({ permit }) => {
|
|
if (permit.type !== "recipient") return;
|
|
|
|
return (
|
|
<div className="flex flex-row items-center justify-between gap-4">
|
|
<div className="text-sm font-bold">Recipient Signature:</div>
|
|
<SignatureValidityIndicator validity={permit.recipientSignature !== "0x" ? "success" : "error"} />
|
|
</div>
|
|
);
|
|
};
|