Skip to content

Commit

Permalink
feat: update wallet connection and session
Browse files Browse the repository at this point in the history
  • Loading branch information
brolag committed Feb 20, 2025
1 parent bd32258 commit ed22dc3
Show file tree
Hide file tree
Showing 6 changed files with 138 additions and 111 deletions.
2 changes: 1 addition & 1 deletion apps/web/src/app/_components/features/ProfileOptions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export function ProfileOptions({ address: _ }: ProfileOptionsProps) {

// Common options that are always shown
const commonOptions: ProfileOption[] = [
{ icon: UserIcon, label: t("user_profile"), href: "/user/user-profile" },
{ icon: UserIcon, label: t("user_profile"), href: "/user-profile" },
{
icon: HeartIcon,
label: t("favorite_products"),
Expand Down
81 changes: 58 additions & 23 deletions apps/web/src/app/_components/features/WalletConnect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
import { signIn, signOut } from "next-auth/react";
import { useRouter } from "next/navigation";
import { useEffect, useState } from "react";
import { toast } from "react-hot-toast";
import { useTranslation } from "react-i18next";
import { connect } from "starknetkit";
import { ARGENT_WEBWALLET_URL, MESSAGE } from "~/constants";
Expand All @@ -34,28 +35,43 @@ export default function WalletConnect({
}: WalletConnectProps) {
const [isClient, setIsClient] = useState(false);
const [isConnecting, setIsConnecting] = useState(false);
const { address } = useAccount();
const [connectionError, setConnectionError] = useState<string | null>(null);
const { address, isConnecting: isAutoConnecting } = useAccount();
const { connect: connectWallet, connectors } = useConnect();
const { disconnect } = useDisconnect();
const { signTypedDataAsync } = useSignTypedData(MESSAGE);
const { t } = useTranslation();
const router = useRouter();
const utils = api.useUtils();

// Reset error when modal opens
useEffect(() => {
if (isOpen) {
setConnectionError(null);
}
}, [isOpen]);

const handleConnectWallet = async (connector: Connector): Promise<void> => {
if (connector) {
try {
setIsConnecting(true);
setConnectionError(null);
const result = connectWallet({ connector });
console.log("connector result", result);
router.push("/marketplace");
} catch (error) {
console.error("Error connecting wallet:", error);
setConnectionError(t("error_connecting_wallet"));
} finally {
setIsConnecting(false);
}
}
};

const handleConnectArgentMobile = async (): Promise<void> => {
try {
setIsConnecting(true);
setConnectionError(null);
const result = await connect({
webWalletUrl: ARGENT_WEBWALLET_URL,
argentMobileOptions: {
Expand All @@ -65,20 +81,23 @@ export default function WalletConnect({
});

if (result?.connector) {
const connectorResult = connectWallet({
connectWallet({
connector: result.connector as unknown as Connector,
});
console.log("connectorResult", connectorResult);
router.push("/marketplace");
}
} catch (error) {
console.error("Error connecting Argent Mobile:", error);
setConnectionError(t("error_connecting_argent"));
} finally {
setIsConnecting(false);
}
};

const handleSignMessage = async (): Promise<void> => {
try {
setIsConnecting(true);
setConnectionError(null);
const signature = await signTypedDataAsync();

const signInResult = await signIn("credentials", {
Expand All @@ -90,17 +109,30 @@ export default function WalletConnect({

if (signInResult?.ok) {
await utils.user.getMe.prefetch();
toast.success(t("successfully_signed_in"));
onSuccess?.();
} else {
setConnectionError(t("error_signing_in"));
toast.error(t("error_signing_in"));
}
} catch (err) {
console.error(t("error_signing_message"), err);
setConnectionError(t("error_signing_message"));
toast.error(t("error_signing_message"));
} finally {
setIsConnecting(false);
}
};

const handleDisconnectWallet = (): void => {
disconnect();
void signOut();
router.push("/");
try {
disconnect();
router.push("/");
toast.success(t("successfully_disconnected"));
} catch (error) {
console.error("Error disconnecting:", error);
toast.error(t("error_disconnecting"));
}
};

useEffect(() => {
Expand All @@ -115,25 +147,27 @@ export default function WalletConnect({
</Text>
<H1 className="text-content-title">CofiBlocks</H1>
</div>
{isAutoConnecting && (
<div className="text-center">
<Text className="text-content-body-default">
{t("connecting_to_wallet")}
</Text>
</div>
)}
{connectionError && (
<div className="text-center text-red-500 mb-4">
<Text>{connectionError}</Text>
</div>
)}
<div className="flex flex-col justify-center items-center space-y-4">
{address ? (
<>
<Button
onClick={() => void handleSignMessage()}
variant="primary"
size="lg"
className="w-full max-w-[15rem] px-4 py-3 text-content-title text-base font-medium font-inter rounded-lg border border-surface-secondary-default transition-all duration-300 hover:bg-surface-secondary-hover"
>
{t("sign")}
</Button>
<button
onClick={handleDisconnectWallet}
className="block text-center text-content-title text-base font-normal font-inter underline transition-colors duration-300 hover:text-content-title-hover"
type="button"
>
{t("disconnect")}
</button>
</>
<button
onClick={handleDisconnectWallet}
className="block text-center text-content-title text-base font-normal font-inter underline transition-colors duration-300 hover:text-content-title-hover"
type="button"
>
{t("disconnect")}
</button>
) : (
<>
{isClient && (
Expand All @@ -158,6 +192,7 @@ export default function WalletConnect({
key={connector.id}
onClick={() => void handleConnectWallet(connector)}
className="w-full max-w-[15rem]"
disabled={!connector.available() || isConnecting}
>
<div className="flex items-center justify-between">
<div className="flex items-center">
Expand Down
100 changes: 43 additions & 57 deletions apps/web/src/app/_components/features/WalletConnectFlow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,7 @@
import { ChevronRightIcon } from "@heroicons/react/24/outline";
import Button from "@repo/ui/button";
import { Text } from "@repo/ui/typography";
import {
type Connector,
useAccount,
useConnect,
useDisconnect,
} from "@starknet-react/core";
import { type Connector, useAccount, useConnect } from "@starknet-react/core";
import { useRouter } from "next/navigation";
import { useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
Expand All @@ -18,20 +13,22 @@ import { ARGENT_WEBWALLET_URL } from "~/constants";
export default function WalletConnectFlow() {
const [isClient, setIsClient] = useState(false);
const [isConnecting, setIsConnecting] = useState(false);
const { address } = useAccount();
const [connectionError, setConnectionError] = useState<string | null>(null);
const { isConnecting: isAutoConnecting } = useAccount();
const { connect: connectWallet, connectors } = useConnect();
const { disconnect } = useDisconnect();
const { t } = useTranslation();
const router = useRouter();

const handleConnectWallet = async (connector: Connector): Promise<void> => {
if (connector) {
try {
setIsConnecting(true);
setConnectionError(null);
connectWallet({ connector });
router.push("/");
router.push("/marketplace");
} catch (error) {
console.error("Failed to connect wallet:", error);
setConnectionError(t("error_connecting_wallet"));
} finally {
setIsConnecting(false);
}
Expand All @@ -41,6 +38,7 @@ export default function WalletConnectFlow() {
const handleConnectArgentMobile = async (): Promise<void> => {
try {
setIsConnecting(true);
setConnectionError(null);
const result = await connect({
webWalletUrl: ARGENT_WEBWALLET_URL,
argentMobileOptions: {
Expand All @@ -53,27 +51,16 @@ export default function WalletConnectFlow() {
connectWallet({
connector: result.connector as unknown as Connector,
});
router.push("/");
router.push("/marketplace");
}
} catch (error) {
console.error("Error connecting Argent Mobile:", error);
setConnectionError(t("error_connecting_argent"));
} finally {
setIsConnecting(false);
}
};

const handleDisconnectWallet = (): void => {
disconnect();
router.push("/");
};

// Redirect to marketplace when address is available
useEffect(() => {
if (address) {
router.push("/marketplace");
}
}, [address, router]);

useEffect(() => {
setIsClient(true);
}, []);
Expand All @@ -85,52 +72,51 @@ export default function WalletConnectFlow() {
{t("connect_your_wallet")}
</Text>
</div>
{isAutoConnecting && (
<div className="text-center mb-4">
<Text className="text-content-body-default">
{t("connecting_to_wallet")}
</Text>
</div>
)}
{connectionError && (
<div className="text-center text-red-500 mb-4">
<Text>{connectionError}</Text>
</div>
)}
<div className="flex flex-col justify-center items-center space-y-4">
{address ? (
<Button
onClick={handleDisconnectWallet}
variant="secondary"
size="lg"
className="w-full max-w-[15rem]"
>
{t("disconnect")}
</Button>
) : (
{isClient && (
<>
{isClient && (
<>
<Button
onClick={() => void handleConnectArgentMobile()}
className="w-full max-w-[15rem]"
disabled={isConnecting}
>
<div className="flex items-center justify-between">
<div className="flex items-center">
<span>
{isConnecting ? t("connecting") : t("argent_mobile")}
</span>
</div>
<ChevronRightIcon className="h-5 w-5" />
</div>
</Button>
{Array.isArray(connectors) &&
connectors.map((connector) => (
<Button
onClick={() => void handleConnectArgentMobile()}
key={connector.id}
onClick={() => void handleConnectWallet(connector)}
className="w-full max-w-[15rem]"
disabled={isConnecting}
disabled={!connector.available() || isConnecting}
>
<div className="flex items-center justify-between">
<div className="flex items-center">
<span>
{isConnecting ? t("connecting") : t("argent_mobile")}
</span>
<span>{t(`${connector.id}`)}</span>
</div>
<ChevronRightIcon className="h-5 w-5" />
</div>
</Button>
{Array.isArray(connectors) &&
connectors.map((connector) => (
<Button
key={connector.id}
onClick={() => void handleConnectWallet(connector)}
className="w-full max-w-[15rem]"
disabled={!connector.available() || isConnecting}
>
<div className="flex items-center justify-between">
<div className="flex items-center">
<span>{t(`${connector.id}`)}</span>
</div>
<ChevronRightIcon className="h-5 w-5" />
</div>
</Button>
))}
</>
)}
))}
</>
)}
</div>
Expand Down
19 changes: 18 additions & 1 deletion apps/web/src/app/_components/features/checkout/OrderReview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,23 @@ import type { CartItem } from "~/store/cartAtom";
import Confirmation from "./Confirmation";
import { CurrencySelector } from "./CurrencySelector";

const getImageUrl = (src: string) => {
if (src.startsWith("Qm")) {
return `${process.env.NEXT_PUBLIC_GATEWAY_URL}/ipfs/${src}`;
}
if (src.startsWith("ipfs://")) {
return `${process.env.NEXT_PUBLIC_GATEWAY_URL}/ipfs/${src.replace("ipfs://", "")}`;
}
if (
src.startsWith("http://") ||
src.startsWith("https://") ||
src.startsWith("/")
) {
return src;
}
return "/images/cafe1.webp"; // Fallback image
};

interface OrderReviewProps {
readonly onNext: () => void;
readonly onCurrencySelect: (currency: string) => void;
Expand Down Expand Up @@ -116,7 +133,7 @@ export default function OrderReview({
<div key={item.id} className="space-y-6 mb-6">
<div className="flex items-start gap-4">
<Image
src={item.imageUrl}
src={getImageUrl(item.imageUrl)}
alt={item.name}
width={80}
height={80}
Expand Down
Loading

0 comments on commit ed22dc3

Please sign in to comment.