Skip to content

Commit d32d0c8

Browse files
committed
Refactor connection context
1 parent a7147f5 commit d32d0c8

29 files changed

+181
-160
lines changed

packages/keychain/global.d.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Controller } from "@/utils/controller";
1+
import Controller from "./src/utils/controller";
22

33
declare global {
44
interface Window {

packages/keychain/src/components/DeployController.tsx

+3-1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import { ControllerError } from "@/utils/connection";
2121
import { TransactionSummary } from "@/components/transaction/TransactionSummary";
2222
import { ETH_CONTRACT_ADDRESS, useERC20Balance } from "@cartridge/utils";
2323
import { Link } from "react-router-dom";
24+
import { useController } from "@/hooks/controller";
2425

2526
export function DeployController({
2627
onClose,
@@ -29,7 +30,8 @@ export function DeployController({
2930
onClose: () => void;
3031
ctrlError?: ControllerError;
3132
}) {
32-
const { controller, chainName, hasPrefundRequest } = useConnection();
33+
const { chainName, hasPrefundRequest } = useConnection();
34+
const { controller } = useController();
3335
const { deploySelf, isDeploying } = useDeploy();
3436
const [deployHash, setDeployHash] = useState<string>();
3537
const [error, setError] = useState<Error>();

packages/keychain/src/components/ExecutionContainer.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { useState, useCallback, useEffect, useRef } from "react";
22
import { Button } from "@cartridge/ui-next";
33
import { Container, Footer } from "@/components/layout";
4-
import { useConnection } from "@/hooks/connection";
54
import { ControllerError } from "@/utils/connection";
65
import { ControllerErrorAlert, ErrorAlert } from "@/components/ErrorAlert";
76
import { Fees } from "./Fees";
@@ -11,6 +10,7 @@ import { ErrorCode } from "@cartridge/account-wasm/controller";
1110
import { BannerProps } from "./layout/container/header/Banner";
1211
import { parseControllerError } from "@/utils/connection/execute";
1312
import isEqual from "lodash/isEqual";
13+
import { useController } from "@/hooks/controller";
1414

1515
interface ExecutionContainerProps {
1616
// eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -41,7 +41,7 @@ export function ExecutionContainer({
4141
children,
4242
}: ExecutionContainerProps &
4343
Pick<BannerProps, "title" | "description" | "icon">) {
44-
const { controller } = useConnection();
44+
const { controller } = useController();
4545
const [maxFee, setMaxFee] = useState<bigint | null>(null);
4646
const [ctrlError, setCtrlError] = useState<ControllerError | undefined>(
4747
executionError,

packages/keychain/src/components/app.tsx

+18-1
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,31 @@ import { Pending } from "./pending";
88
import { Consent, Slot } from "./slot";
99
import { OcclusionDetector } from "./OcclusionDetector";
1010
import { Fund } from "./slot/fund";
11+
import { useConnection } from "@/hooks/connection";
12+
import { useController } from "@/hooks/controller";
13+
import { CreateController } from "./connect";
14+
import { LoginMode } from "./connect/types";
1115

1216
export function App() {
17+
const { origin } = useConnection();
18+
const { controller } = useController();
19+
20+
// Only render in iframe with valid origin
21+
if (window.self === window.top || !origin) {
22+
return <></>;
23+
}
24+
25+
// If no controller is set up, show the create controller screen
26+
if (!controller) {
27+
return <CreateController loginMode={LoginMode.Controller} />;
28+
}
29+
1330
return (
1431
<>
1532
<OcclusionDetector />
1633
<div style={{ position: "relative" }}>
1734
<Routes>
18-
<Route path="/" element={<Home />} />
35+
<Route path="/" element={<Home controller={controller} />} />
1936
<Route path="authenticate" element={<Authenticate />} />
2037
<Route path="session" element={<Session />} />
2138
<Route path="slot" element={<Slot />}>

packages/keychain/src/components/connect/CreateSession.tsx

+5-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import { UnverifiedSessionSummary } from "@/components/session/UnverifiedSession
1111
import { VerifiedSessionSummary } from "@/components/session/VerifiedSessionSummary";
1212
import { DEFAULT_SESSION_DURATION, NOW } from "@/const";
1313
import { Button, Checkbox } from "@cartridge/ui-next";
14+
import { useController } from "@/hooks/controller";
15+
import { useUpgrade } from "@/hooks/upgrade";
1416

1517
export function CreateSession({
1618
policies,
@@ -21,7 +23,9 @@ export function CreateSession({
2123
onConnect: (transaction_hash?: string, expiresAt?: bigint) => void;
2224
isUpdate?: boolean;
2325
}) {
24-
const { controller, upgrade, chainId, theme, logout } = useConnection();
26+
const { chainId, theme, logout } = useConnection();
27+
const upgrade = useUpgrade();
28+
const { controller } = useController();
2529
const [isConnecting, setIsConnecting] = useState(false);
2630
const [isConsent, setIsConsent] = useState(false);
2731
const [duration, setDuration] = useState<bigint>(DEFAULT_SESSION_DURATION);

packages/keychain/src/components/connect/RegisterSession.tsx

+3-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { DEFAULT_SESSION_DURATION, NOW } from "@/const";
1111
import { UnverifiedSessionSummary } from "@/components/session/UnverifiedSessionSummary";
1212
import { VerifiedSessionSummary } from "@/components/session/VerifiedSessionSummary";
1313
import { ParsedSessionPolicies } from "@/hooks/session";
14+
import { useController } from "@/hooks/controller";
1415

1516
export function RegisterSession({
1617
policies,
@@ -21,7 +22,8 @@ export function RegisterSession({
2122
onConnect: (transaction_hash: string, expiresAt: bigint) => void;
2223
publicKey?: string;
2324
}) {
24-
const { controller, theme } = useConnection();
25+
const { theme } = useConnection();
26+
const { controller } = useController();
2527
const [duration, setDuration] = useState<bigint>(DEFAULT_SESSION_DURATION);
2628
const [transactions, setTransactions] = useState<
2729
| {

packages/keychain/src/components/connect/Upgrade.tsx

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
import { BoltIcon, CircleIcon } from "@cartridge/ui-next";
22
import { ExecutionContainer } from "@/components/ExecutionContainer";
33
import { Content } from "@/components/layout";
4-
import { useConnection } from "@/hooks/connection";
4+
import { useController } from "@/hooks/controller";
5+
import { useUpgrade } from "@/hooks/upgrade";
56

67
export const Upgrade = () => {
7-
const { upgrade, controller } = useConnection();
8+
const upgrade = useUpgrade();
9+
const { controller } = useController();
810

911
return (
1012
<ExecutionContainer

packages/keychain/src/components/connect/create/useCreateController.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import Controller from "@/utils/controller";
77
import { fetchAccount } from "./utils";
88
import { PopupCenter } from "@/utils/url";
99
import { useAccountQuery } from "@cartridge/utils/api/cartridge";
10+
import { useController } from "@/hooks/controller";
1011

1112
export function useCreateController({
1213
onCreated,
@@ -20,7 +21,8 @@ export function useCreateController({
2021
const [isLoading, setIsLoading] = useState(false);
2122
const [error, setError] = useState<Error>();
2223
const [pendingUsername, setPendingUsername] = useState<string>();
23-
const { origin, policies, chainId, rpcUrl, setController } = useConnection();
24+
const { origin, policies, chainId, rpcUrl } = useConnection();
25+
const { setController } = useController();
2426

2527
useAccountQuery(
2628
{ username: pendingUsername || "" },
@@ -77,7 +79,6 @@ export function useCreateController({
7779
credentialId,
7880
});
7981

80-
window.controller = controller;
8182
setController(controller);
8283
onCreated?.();
8384
},

packages/keychain/src/components/funding/DepositEth.tsx

+4-2
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import { TokenPair, usePriceQuery } from "@cartridge/utils/api/cartridge";
3636
import { ETH_CONTRACT_ADDRESS } from "@cartridge/utils";
3737
import { toast } from "sonner";
3838
import { DEFAULT_AMOUNT } from "./constants";
39+
import { useController } from "@/hooks/controller";
3940

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

5354
function DepositEthInner({ onComplete, onBack }: DepositEthProps) {
5455
const { connectAsync, connectors, isPending: isConnecting } = useConnect();
55-
const { controller, chainId } = useConnection();
56+
const { chainId } = useConnection();
57+
const { controller } = useController();
5658
const { account: extAccount } = useAccount();
5759

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

246248
function ExternalWalletProvider({ children }: PropsWithChildren) {
247249
const { connectors } = useInjectedConnectors({});
248-
const { controller } = useConnection();
250+
const { controller } = useController();
249251

250252
if (!controller) {
251253
return children;

packages/keychain/src/components/funding/PurchaseCredits.tsx

+3-1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import { Balance } from "./Balance";
1616
import CheckoutForm from "./StripeCheckout";
1717
import { isIframe } from "@cartridge/utils";
1818
import { DEFAULT_AMOUNT } from "./constants";
19+
import { useController } from "@/hooks/controller";
1920

2021
const STRIPE_API_PUBKEY =
2122
"pk_test_51Kr6IXIS6lliDpf33KnwWDtIjRPWt3eAI9CuSLR6Vvc3GxHEwmSU0iszYbUlgUadSRluGKAFphe3JzltyjPAKiBK00al4RAFQu";
@@ -32,7 +33,8 @@ type PurchaseCreditsProps = {
3233
};
3334

3435
export function PurchaseCredits({ isSlot, onBack }: PurchaseCreditsProps) {
35-
const { controller, closeModal } = useConnection();
36+
const { closeModal } = useConnection();
37+
const { controller } = useController();
3638

3739
const [clientSecret, setClientSecret] = useState("");
3840
const [isLoading, setisLoading] = useState<boolean>(false);

packages/keychain/src/components/funding/index.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { Container, Content, Footer } from "@/components/layout";
22
import { useState } from "react";
3-
import { useConnection } from "@/hooks/connection";
43
import {
54
Button,
65
ArrowIcon,
@@ -11,6 +10,7 @@ import {
1110
import { DepositEth } from "./DepositEth";
1211
import { PurchaseCredits } from "./PurchaseCredits";
1312
import { Balance, BalanceType } from "./Balance";
13+
import { useController } from "@/hooks/controller";
1414

1515
const enum FundingState {
1616
SHOW_OPTIONS,
@@ -25,7 +25,7 @@ export type FundingProps = {
2525
};
2626

2727
export function Funding({ title, isSlot, onComplete }: FundingProps) {
28-
const { controller } = useConnection();
28+
const { controller } = useController();
2929
const [state, setState] = useState<FundingState>(FundingState.SHOW_OPTIONS);
3030
const showBalances: BalanceType[] = isSlot ? ["credits"] : ["credits", "eth"];
3131
const showCredits =

packages/keychain/src/components/home.tsx

+9-24
Original file line numberDiff line numberDiff line change
@@ -4,25 +4,24 @@ import { ResponseCodes } from "@cartridge/controller";
44
import { useConnection } from "@/hooks/connection";
55
import { DeployCtx, ExecuteCtx, SignMessageCtx } from "@/utils/connection";
66
import { ConfirmTransaction } from "./transaction/ConfirmTransaction";
7-
import { CreateController, CreateSession, Logout, Upgrade } from "./connect";
8-
import { LoginMode } from "./connect/types";
7+
import { CreateSession, Logout, Upgrade } from "./connect";
98
import { DeployController } from "./DeployController";
109
import { ErrorPage } from "./ErrorBoundary";
1110
import { PurchaseCredits } from "./funding/PurchaseCredits";
1211
import { Settings } from "./settings";
1312
import { SignMessage } from "./SignMessage";
1413
import { PageLoading } from "./Loading";
1514
import { execute } from "@/utils/connection/execute";
16-
import { usePostHog } from "@/hooks/posthog";
15+
import Controller from "@/utils/controller";
16+
import { useUpgrade } from "@/hooks/upgrade";
17+
18+
export function Home({ controller }: { controller: Controller }) {
19+
const { context, setContext, error, policies } = useConnection();
20+
const upgrade = useUpgrade();
1721

18-
export function Home() {
19-
const { context, setContext, controller, error, policies, upgrade } =
20-
useConnection();
2122
const [hasSessionForPolicies, setHasSessionForPolicies] = useState<
2223
boolean | undefined
2324
>(undefined);
24-
const posthog = usePostHog();
25-
2625
useEffect(() => {
2726
if (controller && policies) {
2827
controller.isRequestedSession(policies).then((isRequestedSession) => {
@@ -33,29 +32,15 @@ export function Home() {
3332
}
3433
}, [controller, policies]);
3534

36-
useEffect(() => {
37-
if (context?.type) {
38-
posthog?.capture(
39-
`Call ${context.type.charAt(0).toUpperCase() + context.type.slice(1)}`,
40-
);
41-
}
42-
}, [context?.type, posthog]);
43-
44-
if (window.self === window.top || !context?.origin) {
45-
return <></>;
46-
}
47-
4835
if (error) {
4936
return <ErrorPage error={error} />;
5037
}
5138

52-
// No controller, send to login
53-
if (!controller) {
54-
return <CreateController loginMode={LoginMode.Controller} />;
39+
if (!context) {
40+
return <></>;
5541
}
5642

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

packages/keychain/src/components/layout/container/header/CloseButton.tsx

+3-1
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@ import { TimesIcon, Button } from "@cartridge/ui-next";
22
import { isIframe } from "@cartridge/utils";
33
import { useConnection } from "@/hooks/connection";
44
import { useCallback } from "react";
5+
import { useUpgrade } from "@/hooks/upgrade";
56

67
export function CloseButton({ onClose }: { onClose?: () => void }) {
7-
const { upgrade, logout, closeModal } = useConnection();
8+
const { logout, closeModal } = useConnection();
9+
const upgrade = useUpgrade();
810

911
const handleClose = useCallback(() => {
1012
if (upgrade.available) {

packages/keychain/src/components/provider/connection.tsx

-5
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
import { createContext } from "react";
2-
import Controller from "@/utils/controller";
32
import { ConnectionCtx } from "@/utils/connection";
4-
import { UpgradeInterface } from "@/hooks/upgrade";
53
import { ParsedSessionPolicies } from "@/hooks/session";
64
import { VerifiableControllerTheme } from "@/context/theme";
75

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

1210
export type ConnectionContextValue = {
1311
context: ConnectionCtx;
14-
controller?: Controller;
1512
origin?: string;
1613
rpcUrl?: string;
1714
chainId?: string;
@@ -20,9 +17,7 @@ export type ConnectionContextValue = {
2017
theme: VerifiableControllerTheme;
2118
hasPrefundRequest: boolean;
2219
error?: Error;
23-
upgrade: UpgradeInterface;
2420
setContext: (context: ConnectionCtx) => void;
25-
setController: (controller: Controller) => void;
2621
closeModal: () => void;
2722
openModal: () => void;
2823
logout: () => void;

packages/keychain/src/components/provider/posthog.tsx

+11-9
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
11
import { PropsWithChildren, useEffect } from "react";
22
import { PostHogContext, PostHogWrapper } from "@/context/posthog";
33
import { useConnectionValue } from "@/hooks/connection";
4+
import { useController } from "@/hooks/controller";
45

5-
export function PostHogProvider({ children }: PropsWithChildren) {
6-
const { controller, origin } = useConnectionValue();
6+
export const posthog = new PostHogWrapper(import.meta.env.VITE_POSTHOG_KEY!, {
7+
host: import.meta.env.VITE_POSTHOG_HOST,
8+
persistence: "memory",
9+
autocapture: false,
10+
});
711

8-
const posthog = new PostHogWrapper(import.meta.env.VITE_POSTHOG_KEY!, {
9-
host: import.meta.env.VITE_POSTHOG_HOST,
10-
persistence: "memory",
11-
autocapture: false,
12-
});
12+
export function PostHogProvider({ children }: PropsWithChildren) {
13+
const { origin } = useConnectionValue();
14+
const { controller } = useController();
1315

1416
useEffect(() => {
1517
if (controller) {
@@ -21,13 +23,13 @@ export function PostHogProvider({ children }: PropsWithChildren) {
2123
} else {
2224
posthog.reset();
2325
}
24-
}, [posthog, controller]);
26+
}, [controller]);
2527

2628
useEffect(() => {
2729
if (origin) {
2830
posthog.group("company", origin);
2931
}
30-
}, [posthog, origin]);
32+
}, [origin]);
3133

3234
return (
3335
<PostHogContext.Provider value={{ posthog }}>

packages/keychain/src/components/session.tsx

+3-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { useCallback, useEffect, useMemo, useState } from "react";
1111
import { LoginMode } from "@/components/connect/types";
1212
import { PageLoading } from "@/components/Loading";
1313
import { useNavigate, useSearchParams } from "react-router-dom";
14+
import { useController } from "@/hooks/controller";
1415

1516
type SessionResponse = {
1617
username: string;
@@ -44,7 +45,8 @@ export function Session() {
4445
[searchParams],
4546
);
4647

47-
const { controller, policies, origin } = useConnection();
48+
const { policies, origin } = useConnection();
49+
const { controller } = useController();
4850
const [isLoading, setIsLoading] = useState<boolean>(true);
4951

5052
// Handler for calling the callback uri.

0 commit comments

Comments
 (0)