Skip to content

Commit

Permalink
Add expiration to session summary
Browse files Browse the repository at this point in the history
  • Loading branch information
tarrencev committed Jan 10, 2025
1 parent 603f720 commit 2ef1386
Show file tree
Hide file tree
Showing 10 changed files with 121 additions and 55 deletions.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
60 changes: 17 additions & 43 deletions packages/keychain/src/components/connect/CreateSession.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Container, Content, Footer } from "@/components/layout";
import { BigNumberish, shortString } from "starknet";
import { ControllerError } from "@/utils/connection";
import { useCallback, useEffect, useMemo, useState } from "react";
import { useCallback, useEffect, useState } from "react";
import { useConnection } from "@/hooks/connection";
import { ControllerErrorAlert } from "@/components/ErrorAlert";
import { SessionConsent } from "@/components/connect";
Expand All @@ -12,15 +12,7 @@ import { ParsedSessionPolicies } from "@/hooks/session";
import { UnverifiedSessionSummary } from "@/components/session/UnverifiedSessionSummary";
import { VerifiedSessionSummary } from "@/components/session/VerifiedSessionSummary";
import { DEFAULT_SESSION_DURATION } from "@/const";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
Button,
Checkbox,
} from "@cartridge/ui-next";
import { Button, Checkbox } from "@cartridge/ui-next";

export function CreateSession({
policies,
Expand All @@ -36,10 +28,6 @@ export function CreateSession({
const [isDisabled, setIsDisabled] = useState(false);
const [isConsent, setIsConsent] = useState(false);
const [duration, setDuration] = useState<bigint>(DEFAULT_SESSION_DURATION);
const expiresAt = useMemo(
() => duration + BigInt(Math.floor(Date.now() / 1000)),
[duration],
);
const [maxFee] = useState<BigNumberish>();
const [error, setError] = useState<ControllerError | Error>();

Expand Down Expand Up @@ -93,26 +81,26 @@ export function CreateSession({
});
}

await controller.createSession(expiresAt, policies, maxFee);
await controller.createSession(duration, policies, maxFee);
onConnect();
} catch (e) {
setError(e as unknown as Error);
setIsConnecting(false);
}
}, [controller, expiresAt, policies, maxFee, onConnect]);
}, [controller, duration, policies, maxFee, onConnect]);

const onSkipSession = useCallback(async () => {
if (!controller || !policies) return;
try {
setError(undefined);
setIsConnecting(true);
await controller.createSession(expiresAt, policies, maxFee);
await controller.createSession(duration, policies, maxFee);
onConnect();
} catch (e) {
setError(e as unknown as Error);
setIsConnecting(false);
}
}, [controller, expiresAt, policies, maxFee, onConnect]);
}, [controller, duration, policies, maxFee, onConnect]);

if (!upgrade.isSynced) {
return <></>;
Expand All @@ -139,35 +127,21 @@ export function CreateSession({
<Content gap={6}>
<SessionConsent isVerified={policies?.verified} />
{policies?.verified ? (
<VerifiedSessionSummary game={theme.name} policies={policies} />
<VerifiedSessionSummary
game={theme.name}
policies={policies}
duration={duration}
onDurationChange={setDuration}
/>
) : (
<UnverifiedSessionSummary policies={policies} />
<UnverifiedSessionSummary
policies={policies}
duration={duration}
onDurationChange={setDuration}
/>
)}
</Content>
<Footer>
<div className="flex items-center text-sm text-muted-foreground py-4 gap-2">
<div className="font-medium">Expires in </div>
<Select
value={duration.toString()}
onValueChange={(val) => setDuration(BigInt(val))}
>
<SelectTrigger className="w-28">
<SelectValue
defaultValue={(60 * 60 * 24).toString()}
placeholder="1 HR"
/>
</SelectTrigger>

<SelectContent>
<SelectItem value={(60 * 60).toString()}>1 HR</SelectItem>
<SelectItem value={(60 * 60 * 24).toString()}>24 HRS</SelectItem>
<SelectItem value={(60 * 60 * 24 * 7).toString()}>
1 WEEK
</SelectItem>
</SelectContent>
</Select>
</div>

{!policies?.verified && (
<div
className="flex items-center p-3 mb-3 gap-5 border border-solid-primary rounded-md cursor-pointer border-error-icon text-error-icon"
Expand Down
25 changes: 17 additions & 8 deletions packages/keychain/src/components/connect/RegisterSession.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
TransactionExecutionStatus,
TransactionFinalityStatus,
} from "starknet";
import { SESSION_EXPIRATION } from "@/const";
import { DEFAULT_SESSION_DURATION } from "@/const";
import { UnverifiedSessionSummary } from "@/components/session/UnverifiedSessionSummary";
import { VerifiedSessionSummary } from "@/components/session/VerifiedSessionSummary";
import { ParsedSessionPolicies } from "@/hooks/session";
Expand All @@ -22,7 +22,7 @@ export function RegisterSession({
publicKey?: string;
}) {
const { controller, theme } = useConnection();
const [expiresAt] = useState<bigint>(SESSION_EXPIRATION);
const [duration, setDuration] = useState<bigint>(DEFAULT_SESSION_DURATION);
const [transactions, setTransactions] = useState<
| {
contractAddress: string;
Expand All @@ -37,7 +37,7 @@ export function RegisterSession({
setTransactions(undefined);
} else {
controller
.registerSessionCalldata(expiresAt, policies, publicKey)
.registerSessionCalldata(duration, policies, publicKey)
.then((calldata) => {
setTransactions([
{
Expand All @@ -48,7 +48,7 @@ export function RegisterSession({
]);
});
}
}, [controller, expiresAt, policies, publicKey]);
}, [controller, duration, policies, publicKey]);

const onRegisterSession = useCallback(
async (maxFee?: bigint) => {
Expand All @@ -57,7 +57,7 @@ export function RegisterSession({
}

const { transaction_hash } = await controller.registerSession(
expiresAt,
duration,
policies,
publicKey,
maxFee,
Expand All @@ -73,7 +73,7 @@ export function RegisterSession({

onConnect(transaction_hash);
},
[controller, expiresAt, policies, publicKey, onConnect],
[controller, duration, policies, publicKey, onConnect],
);

return (
Expand All @@ -86,9 +86,18 @@ export function RegisterSession({
<Content>
<SessionConsent isVerified={policies?.verified} />
{policies?.verified ? (
<VerifiedSessionSummary game={theme.name} policies={policies} />
<VerifiedSessionSummary
game={theme.name}
policies={policies}
duration={duration}
onDurationChange={setDuration}
/>
) : (
<UnverifiedSessionSummary policies={policies} />
<UnverifiedSessionSummary
policies={policies}
duration={duration}
onDurationChange={setDuration}
/>
)}
</Content>
</ExecutionContainer>
Expand Down
66 changes: 66 additions & 0 deletions packages/keychain/src/components/session/ExpirationCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { ClockIcon } from "@cartridge/ui-next";
import { AccordionCard } from "./AccordionCard";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@cartridge/ui-next";

interface ExpirationCardProps {
duration: bigint;
onDurationChange: (duration: bigint) => void;
isExpanded?: boolean;
}

export function ExpirationCard({
duration,
onDurationChange,
isExpanded,
}: ExpirationCardProps) {
return (
<AccordionCard
icon={<ClockIcon variant="solid" />}
title="Session Expiration"
trigger={
<div className="text-xs text-muted-foreground">
Expires in&nbsp;
<span className="text-accent-foreground font-bold">
{formatDuration(duration)}
</span>
</div>
}
isExpanded={isExpanded}
>
<div className="flex flex-col gap-4 p-3 text-xs">
<div className="flex items-center justify-between">
<div className="text-muted-foreground">Duration</div>
<Select
value={duration.toString()}
onValueChange={(val) => onDurationChange(BigInt(val))}
>
<SelectTrigger className="w-28">
<SelectValue placeholder="1 HR" />
</SelectTrigger>
<SelectContent>
<SelectItem value={(60 * 60).toString()}>1 HR</SelectItem>
<SelectItem value={(60 * 60 * 24).toString()}>24 HRS</SelectItem>
<SelectItem value={(60 * 60 * 24 * 7).toString()}>
1 WEEK
</SelectItem>
</SelectContent>
</Select>
</div>
</div>
</AccordionCard>
);
}

function formatDuration(seconds: bigint): string {
const hours = Number(seconds) / 3600;
if (hours === 1) return "1 hour";
if (hours === 24) return "24 hours";
if (hours === 168) return "1 week";
return `${hours} hours`;
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,16 @@ import { ParsedSessionPolicies } from "@/hooks/session";

import { MessageCard } from "./MessageCard";
import { ContractCard } from "./ContractCard";
import { ExpirationCard } from "./ExpirationCard";

export function UnverifiedSessionSummary({
policies,
duration,
onDurationChange,
}: {
policies: ParsedSessionPolicies;
duration: bigint;
onDurationChange: (duration: bigint) => void;
}) {
return (
<div className="flex flex-col gap-4">
Expand All @@ -31,6 +36,8 @@ export function UnverifiedSessionSummary({
{policies.messages && policies.messages.length > 0 && (
<MessageCard messages={policies.messages} isExpanded />
)}

<ExpirationCard duration={duration} onDurationChange={onDurationChange} />
</div>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,18 @@ import { ParsedSessionPolicies } from "@/hooks/session";
import { AggregateCard } from "./AggregateCard";
import { CodeIcon } from "@cartridge/ui-next";
import { ContractCard } from "./ContractCard";
import { ExpirationCard } from "./ExpirationCard";

export function VerifiedSessionSummary({
game,
policies,
duration,
onDurationChange,
}: {
game: string;
policies: ParsedSessionPolicies;
duration: bigint;
onDurationChange: (duration: bigint) => void;
}) {
// Extract token and VRF contracts
const individual = Object.entries(policies.contracts ?? {}).filter(
Expand Down Expand Up @@ -44,6 +49,8 @@ export function VerifiedSessionSummary({
methods={contract.methods}
/>
))}

<ExpirationCard duration={duration} onDurationChange={onDurationChange} />
</div>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export function ConfirmTransaction() {
return (
<ExecutionContainer
Icon={TransactionDuoIcon}
title="Review Transaction"
title={`Review Transaction${transactions.length > 1 ? "s" : ""}`}
description={origin}
executionError={ctx.error}
transactions={ctx.transactions}
Expand Down
7 changes: 5 additions & 2 deletions packages/keychain/src/utils/controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ export default class Controller extends Account {
}

async createSession(
expiresAt: bigint,
duration: bigint,
policies: ParsedSessionPolicies,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
_maxFee?: BigNumberish,
Expand All @@ -106,6 +106,7 @@ export default class Controller extends Account {
throw new Error("Account not found");
}

const expiresAt = duration + BigInt(Math.floor(Date.now() / 1000));
await this.cartridge.createSession(toWasmPolicies(policies), expiresAt);
}

Expand All @@ -122,7 +123,7 @@ export default class Controller extends Account {
}

async registerSession(
expiresAt: bigint,
duration: bigint,
policies: ParsedSessionPolicies,
publicKey: string,
maxFee: BigNumberish,
Expand All @@ -131,6 +132,8 @@ export default class Controller extends Account {
throw new Error("Account not found");
}

const expiresAt = duration + BigInt(Math.floor(Date.now() / 1000));

return await this.cartridge.registerSession(
toWasmPolicies(policies),
expiresAt,
Expand Down
2 changes: 1 addition & 1 deletion packages/ui-next/src/components/icons/state/clock.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export const ClockIcon = memo(
forwardRef<SVGSVGElement, StateIconProps>(
({ className, size, variant, ...props }, forwardedRef) => (
<svg
viewBox="0 0 24 24"
viewBox="0 0 20 20"
className={iconVariants({ size, className })}
ref={forwardedRef}
{...props}
Expand Down

0 comments on commit 2ef1386

Please sign in to comment.