Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor connection context #1325

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/keychain/global.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Controller } from "@/utils/controller";
import Controller from "./src/utils/controller";

declare global {
interface Window {
Expand Down
4 changes: 3 additions & 1 deletion packages/keychain/src/components/DeployController.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { ControllerError } from "@/utils/connection";
import { TransactionSummary } from "@/components/transaction/TransactionSummary";
import { ETH_CONTRACT_ADDRESS, useERC20Balance } from "@cartridge/utils";
import { Link } from "react-router-dom";
import { useController } from "@/hooks/controller";

export function DeployController({
onClose,
Expand All @@ -29,7 +30,8 @@ export function DeployController({
onClose: () => void;
ctrlError?: ControllerError;
}) {
const { controller, chainName, hasPrefundRequest } = useConnection();
const { chainName, hasPrefundRequest } = useConnection();
const { controller } = useController();
const { deploySelf, isDeploying } = useDeploy();
const [deployHash, setDeployHash] = useState<string>();
const [error, setError] = useState<Error>();
Expand Down
4 changes: 2 additions & 2 deletions packages/keychain/src/components/ExecutionContainer.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { useState, useCallback, useEffect, useRef } from "react";
import { Button } from "@cartridge/ui-next";
import { Container, Footer } from "@/components/layout";
import { useConnection } from "@/hooks/connection";
import { ControllerError } from "@/utils/connection";
import { ControllerErrorAlert, ErrorAlert } from "@/components/ErrorAlert";
import { Fees } from "./Fees";
Expand All @@ -11,6 +10,7 @@ import { ErrorCode } from "@cartridge/account-wasm/controller";
import { BannerProps } from "./layout/container/header/Banner";
import { parseControllerError } from "@/utils/connection/execute";
import isEqual from "lodash/isEqual";
import { useController } from "@/hooks/controller";

interface ExecutionContainerProps {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
Expand Down Expand Up @@ -41,7 +41,7 @@ export function ExecutionContainer({
children,
}: ExecutionContainerProps &
Pick<BannerProps, "title" | "description" | "icon">) {
const { controller } = useConnection();
const { controller } = useController();
const [maxFee, setMaxFee] = useState<bigint | null>(null);
const [ctrlError, setCtrlError] = useState<ControllerError | undefined>(
executionError,
Expand Down
19 changes: 18 additions & 1 deletion packages/keychain/src/components/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,31 @@ import { Pending } from "./pending";
import { Consent, Slot } from "./slot";
import { OcclusionDetector } from "./OcclusionDetector";
import { Fund } from "./slot/fund";
import { useConnection } from "@/hooks/connection";
import { useController } from "@/hooks/controller";
import { CreateController } from "./connect";
import { LoginMode } from "./connect/types";

export function App() {
const { origin } = useConnection();
const { controller } = useController();

// Only render in iframe with valid origin
if (window.self === window.top || !origin) {
return <></>;
}

// If no controller is set up, show the create controller screen
if (!controller) {
return <CreateController loginMode={LoginMode.Controller} />;
}

return (
<>
<OcclusionDetector />
<div style={{ position: "relative" }}>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/" element={<Home controller={controller} />} />
<Route path="authenticate" element={<Authenticate />} />
<Route path="session" element={<Session />} />
<Route path="slot" element={<Slot />}>
Expand Down
6 changes: 5 additions & 1 deletion packages/keychain/src/components/connect/CreateSession.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
import { VerifiedSessionSummary } from "@/components/session/VerifiedSessionSummary";
import { DEFAULT_SESSION_DURATION, NOW } from "@/const";
import { Button, Checkbox } from "@cartridge/ui-next";
import { useController } from "@/hooks/controller";
import { useUpgrade } from "@/hooks/upgrade";

export function CreateSession({
policies,
Expand All @@ -21,7 +23,9 @@
onConnect: (transaction_hash?: string, expiresAt?: bigint) => void;
isUpdate?: boolean;
}) {
const { controller, upgrade, chainId, theme, logout } = useConnection();
const { chainId, theme, logout } = useConnection();
const upgrade = useUpgrade();
const { controller } = useController();
const [isConnecting, setIsConnecting] = useState(false);
const [isConsent, setIsConsent] = useState(false);
const [duration, setDuration] = useState<bigint>(DEFAULT_SESSION_DURATION);
Expand Down Expand Up @@ -73,7 +77,7 @@
setError(e as unknown as Error);
setIsConnecting(false);
}
}, [controller, duration, policies, maxFee, onConnect]);

Check warning on line 80 in packages/keychain/src/components/connect/CreateSession.tsx

View workflow job for this annotation

GitHub Actions / ts-lint

React Hook useCallback has a missing dependency: 'expiresAt'. Either include it or remove the dependency array

const onSkipSession = useCallback(async () => {
if (!controller || !policies) return;
Expand Down
4 changes: 3 additions & 1 deletion packages/keychain/src/components/connect/RegisterSession.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { DEFAULT_SESSION_DURATION, NOW } from "@/const";
import { UnverifiedSessionSummary } from "@/components/session/UnverifiedSessionSummary";
import { VerifiedSessionSummary } from "@/components/session/VerifiedSessionSummary";
import { ParsedSessionPolicies } from "@/hooks/session";
import { useController } from "@/hooks/controller";

export function RegisterSession({
policies,
Expand All @@ -21,7 +22,8 @@ export function RegisterSession({
onConnect: (transaction_hash: string, expiresAt: bigint) => void;
publicKey?: string;
}) {
const { controller, theme } = useConnection();
const { theme } = useConnection();
const { controller } = useController();
const [duration, setDuration] = useState<bigint>(DEFAULT_SESSION_DURATION);
const [transactions, setTransactions] = useState<
| {
Expand Down
6 changes: 4 additions & 2 deletions packages/keychain/src/components/connect/Upgrade.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { BoltIcon, CircleIcon } from "@cartridge/ui-next";
import { ExecutionContainer } from "@/components/ExecutionContainer";
import { Content } from "@/components/layout";
import { useConnection } from "@/hooks/connection";
import { useController } from "@/hooks/controller";
import { useUpgrade } from "@/hooks/upgrade";

export const Upgrade = () => {
const { upgrade, controller } = useConnection();
const upgrade = useUpgrade();
const { controller } = useController();

return (
<ExecutionContainer
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import Controller from "@/utils/controller";
import { fetchAccount } from "./utils";
import { PopupCenter } from "@/utils/url";
import { useAccountQuery } from "@cartridge/utils/api/cartridge";
import { useController } from "@/hooks/controller";

export function useCreateController({
onCreated,
Expand All @@ -20,7 +21,8 @@ export function useCreateController({
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState<Error>();
const [pendingUsername, setPendingUsername] = useState<string>();
const { origin, policies, chainId, rpcUrl, setController } = useConnection();
const { origin, policies, chainId, rpcUrl } = useConnection();
const { setController } = useController();

useAccountQuery(
{ username: pendingUsername || "" },
Expand Down Expand Up @@ -77,7 +79,6 @@ export function useCreateController({
credentialId,
});

window.controller = controller;
setController(controller);
onCreated?.();
},
Expand Down
6 changes: 4 additions & 2 deletions packages/keychain/src/components/funding/DepositEth.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import { TokenPair, usePriceQuery } from "@cartridge/utils/api/cartridge";
import { ETH_CONTRACT_ADDRESS } from "@cartridge/utils";
import { toast } from "sonner";
import { DEFAULT_AMOUNT } from "./constants";
import { useController } from "@/hooks/controller";

type DepositEthProps = {
onComplete?: (deployHash?: string) => void;
Expand All @@ -52,7 +53,8 @@ export function DepositEth(innerProps: DepositEthProps) {

function DepositEthInner({ onComplete, onBack }: DepositEthProps) {
const { connectAsync, connectors, isPending: isConnecting } = useConnect();
const { controller, chainId } = useConnection();
const { chainId } = useConnection();
const { controller } = useController();
const { account: extAccount } = useAccount();

const [dollarAmount, setDollarAmount] = useState<number>(DEFAULT_AMOUNT);
Expand Down Expand Up @@ -245,7 +247,7 @@ function DepositEthInner({ onComplete, onBack }: DepositEthProps) {

function ExternalWalletProvider({ children }: PropsWithChildren) {
const { connectors } = useInjectedConnectors({});
const { controller } = useConnection();
const { controller } = useController();

if (!controller) {
return children;
Expand Down
4 changes: 3 additions & 1 deletion packages/keychain/src/components/funding/PurchaseCredits.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { Balance } from "./Balance";
import CheckoutForm from "./StripeCheckout";
import { isIframe } from "@cartridge/utils";
import { DEFAULT_AMOUNT } from "./constants";
import { useController } from "@/hooks/controller";

const STRIPE_API_PUBKEY =
"pk_test_51Kr6IXIS6lliDpf33KnwWDtIjRPWt3eAI9CuSLR6Vvc3GxHEwmSU0iszYbUlgUadSRluGKAFphe3JzltyjPAKiBK00al4RAFQu";
Expand All @@ -32,7 +33,8 @@ type PurchaseCreditsProps = {
};

export function PurchaseCredits({ isSlot, onBack }: PurchaseCreditsProps) {
const { controller, closeModal } = useConnection();
const { closeModal } = useConnection();
const { controller } = useController();

const [clientSecret, setClientSecret] = useState("");
const [isLoading, setisLoading] = useState<boolean>(false);
Expand Down
4 changes: 2 additions & 2 deletions packages/keychain/src/components/funding/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { Container, Content, Footer } from "@/components/layout";
import { useState } from "react";
import { useConnection } from "@/hooks/connection";
import {
Button,
ArrowIcon,
Expand All @@ -11,6 +10,7 @@ import {
import { DepositEth } from "./DepositEth";
import { PurchaseCredits } from "./PurchaseCredits";
import { Balance, BalanceType } from "./Balance";
import { useController } from "@/hooks/controller";

const enum FundingState {
SHOW_OPTIONS,
Expand All @@ -25,7 +25,7 @@ export type FundingProps = {
};

export function Funding({ title, isSlot, onComplete }: FundingProps) {
const { controller } = useConnection();
const { controller } = useController();
const [state, setState] = useState<FundingState>(FundingState.SHOW_OPTIONS);
const showBalances: BalanceType[] = isSlot ? ["credits"] : ["credits", "eth"];
const showCredits =
Expand Down
33 changes: 9 additions & 24 deletions packages/keychain/src/components/home.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,24 @@ import { ResponseCodes } from "@cartridge/controller";
import { useConnection } from "@/hooks/connection";
import { DeployCtx, ExecuteCtx, SignMessageCtx } from "@/utils/connection";
import { ConfirmTransaction } from "./transaction/ConfirmTransaction";
import { CreateController, CreateSession, Logout, Upgrade } from "./connect";
import { LoginMode } from "./connect/types";
import { CreateSession, Logout, Upgrade } from "./connect";
import { DeployController } from "./DeployController";
import { ErrorPage } from "./ErrorBoundary";
import { PurchaseCredits } from "./funding/PurchaseCredits";
import { Settings } from "./settings";
import { SignMessage } from "./SignMessage";
import { PageLoading } from "./Loading";
import { execute } from "@/utils/connection/execute";
import { usePostHog } from "@/hooks/posthog";
import Controller from "@/utils/controller";
import { useUpgrade } from "@/hooks/upgrade";

export function Home({ controller }: { controller: Controller }) {
const { context, setContext, error, policies } = useConnection();
const upgrade = useUpgrade();

export function Home() {
const { context, setContext, controller, error, policies, upgrade } =
useConnection();
const [hasSessionForPolicies, setHasSessionForPolicies] = useState<
boolean | undefined
>(undefined);
const posthog = usePostHog();

useEffect(() => {
if (controller && policies) {
controller.isRequestedSession(policies).then((isRequestedSession) => {
Expand All @@ -33,29 +32,15 @@ export function Home() {
}
}, [controller, policies]);

useEffect(() => {
if (context?.type) {
posthog?.capture(
`Call ${context.type.charAt(0).toUpperCase() + context.type.slice(1)}`,
);
}
}, [context?.type, posthog]);

if (window.self === window.top || !context?.origin) {
return <></>;
}

if (error) {
return <ErrorPage error={error} />;
}

// No controller, send to login
if (!controller) {
return <CreateController loginMode={LoginMode.Controller} />;
if (!context) {
return <></>;
}

if (!upgrade.isSynced || hasSessionForPolicies === undefined) {
// This is likely never observable in a real application but just in case.
return <PageLoading />;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ import { TimesIcon, Button } from "@cartridge/ui-next";
import { isIframe } from "@cartridge/utils";
import { useConnection } from "@/hooks/connection";
import { useCallback } from "react";
import { useUpgrade } from "@/hooks/upgrade";

export function CloseButton({ onClose }: { onClose?: () => void }) {
const { upgrade, logout, closeModal } = useConnection();
const { logout, closeModal } = useConnection();
const upgrade = useUpgrade();

const handleClose = useCallback(() => {
if (upgrade.available) {
Expand Down
5 changes: 0 additions & 5 deletions packages/keychain/src/components/provider/connection.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import { createContext } from "react";
import Controller from "@/utils/controller";
import { ConnectionCtx } from "@/utils/connection";
import { UpgradeInterface } from "@/hooks/upgrade";
import { ParsedSessionPolicies } from "@/hooks/session";
import { VerifiableControllerTheme } from "@/context/theme";

Expand All @@ -11,7 +9,6 @@ export const ConnectionContext = createContext<

export type ConnectionContextValue = {
context: ConnectionCtx;
controller?: Controller;
origin?: string;
rpcUrl?: string;
chainId?: string;
Expand All @@ -20,9 +17,7 @@ export type ConnectionContextValue = {
theme: VerifiableControllerTheme;
hasPrefundRequest: boolean;
error?: Error;
upgrade: UpgradeInterface;
setContext: (context: ConnectionCtx) => void;
setController: (controller: Controller) => void;
closeModal: () => void;
openModal: () => void;
logout: () => void;
Expand Down
20 changes: 11 additions & 9 deletions packages/keychain/src/components/provider/posthog.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import { PropsWithChildren, useEffect } from "react";
import { PostHogContext, PostHogWrapper } from "@/context/posthog";
import { useConnectionValue } from "@/hooks/connection";
import { useController } from "@/hooks/controller";

export function PostHogProvider({ children }: PropsWithChildren) {
const { controller, origin } = useConnectionValue();
export const posthog = new PostHogWrapper(import.meta.env.VITE_POSTHOG_KEY!, {

Check warning on line 6 in packages/keychain/src/components/provider/posthog.tsx

View workflow job for this annotation

GitHub Actions / ts-lint

Fast refresh only works when a file only exports components. Use a new file to share constants or functions between components
host: import.meta.env.VITE_POSTHOG_HOST,
persistence: "memory",
autocapture: false,
});

const posthog = new PostHogWrapper(import.meta.env.VITE_POSTHOG_KEY!, {
host: import.meta.env.VITE_POSTHOG_HOST,
persistence: "memory",
autocapture: false,
});
export function PostHogProvider({ children }: PropsWithChildren) {
const { origin } = useConnectionValue();
const { controller } = useController();

useEffect(() => {
if (controller) {
Expand All @@ -21,13 +23,13 @@
} else {
posthog.reset();
}
}, [posthog, controller]);
}, [controller]);

useEffect(() => {
if (origin) {
posthog.group("company", origin);
}
}, [posthog, origin]);
}, [origin]);

return (
<PostHogContext.Provider value={{ posthog }}>
Expand Down
4 changes: 3 additions & 1 deletion packages/keychain/src/components/session.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { useCallback, useEffect, useMemo, useState } from "react";
import { LoginMode } from "@/components/connect/types";
import { PageLoading } from "@/components/Loading";
import { useNavigate, useSearchParams } from "react-router-dom";
import { useController } from "@/hooks/controller";

type SessionResponse = {
username: string;
Expand Down Expand Up @@ -44,7 +45,8 @@ export function Session() {
[searchParams],
);

const { controller, policies, origin } = useConnection();
const { policies, origin } = useConnection();
const { controller } = useController();
const [isLoading, setIsLoading] = useState<boolean>(true);

// Handler for calling the callback uri.
Expand Down
Loading
Loading