Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/upgrade-tx-notifications'
Browse files Browse the repository at this point in the history
  • Loading branch information
RedBeardEth committed Oct 6, 2024
2 parents 1a5b019 + 9aada3c commit b935417
Show file tree
Hide file tree
Showing 13 changed files with 145 additions and 48 deletions.
14 changes: 8 additions & 6 deletions apps/nextjs/src/app/(app)/account/assets/BridgeNftWrapper.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
"use client";

import { useEffect, useMemo, useState } from "react";
import useStore from "@/hooks/useStore";
import { useTransactionManager } from "@/stores/useTransasctionManager";
import { useState } from "react";
import { usePendingRealmsWithdrawals } from "@/hooks/bridge/data/usePendingRealmsWithdrawals";
import EthereumLogo from "@/icons/ethereum.svg";
import StarknetLogo from "@/icons/starknet.svg";
import { useUIStore } from "@/providers/UIStoreProvider";
import { TriangleAlert } from "lucide-react";
import { useAccount } from "wagmi";
import { TransactionFinalityStatus } from "starknet";

import { CollectionAddresses, Collections } from "@realms-world/constants";

Expand All @@ -30,11 +32,11 @@ import { Portfolio } from "./Portfolio";
import { useUserTokens } from "@/hooks/reservoir/useUserTokens";

export const BridgeNftWrapper = () => {
const [activeChain, setActiveChain] = useState("l2");
const { address: l1Address } = useAccount();
const [activeChain, setActiveChain] = useState("l1");
const { address } = useAccount();
const { data: pendingWithdrawals } = usePendingRealmsWithdrawals({
address: l1Address,
status: "ACCEPTED_ON_L1",
address,
status: TransactionFinalityStatus.ACCEPTED_ON_L1,
});
const { toggleAccount } = useUIStore((state) => state);
const { tokens, isLoading } = useUserTokens({
Expand Down
2 changes: 2 additions & 0 deletions apps/nextjs/src/app/(app)/games/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export const metadata: Metadata = {


export default async function Page() {

const games = await reader.collections.games.all();
return (
<PageLayout title="Onchain Games">
Expand All @@ -24,5 +25,6 @@ export default async function Page() {

</div>
</PageLayout>

);
}
7 changes: 7 additions & 0 deletions apps/nextjs/src/app/_components/TopNav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import PieChart from "@/icons/pie-chart.svg";
import RealmsL3 from "@/icons/realms_l3.svg";
import { useUIStore } from "@/providers/UIStoreProvider";
import { HammerIcon, Menu /*, ShieldQuestion*/ } from "lucide-react";
import useStore from "@/hooks/useStore";
import { useTransactionManager } from "@/stores/useTransasctionManager";
import Crown from "@/icons/crown.svg";
import { Button } from "@realms-world/ui/components/ui/button";
import {
Expand All @@ -21,8 +23,11 @@ import { EthereumLoginButton } from "./wallet/EthereumLoginButton";
import { LordsDropdown } from "./wallet/LordsDropdown";
import { StarknetLoginButton } from "./wallet/StarknetLoginButton";


export const TopNav = () => {
const { toggleSidebar } = useUIStore((state) => state);
const transactionState = useStore(useTransactionManager, (state) => state);
const newTransactionCount = transactionState?.newTransactionCount;

const aboutLinks = [
/*{
Expand Down Expand Up @@ -144,9 +149,11 @@ export const TopNav = () => {
textClass="group-hover:block"
/>
<StarknetLoginButton
buttonClass="relative"
textClass="group-hover:block"
variant={"default"}
openAccount
newTransactionCount={newTransactionCount}
/>
</div>
</div>
Expand Down
2 changes: 1 addition & 1 deletion apps/nextjs/src/app/_components/wallet/ExplorerLink.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export const ExplorerLink = ({
return (
<Button key={text} variant={"outline"} size={"xs"} asChild>
<Link href={explorerURL} target="_blank">
{text ?? isL1 ? "Etherscan" : "Starkscan"}
{text}
<ExternalLinkIcon className="h-4" />
</Link>
</Button>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,14 @@ export const StarknetLoginButton = ({
textClass,
buttonClass,
children,
newTransactionCount
}: {
openAccount?: boolean;
variant?: VariantProps<typeof buttonVariants>["variant"];
textClass?: string;
buttonClass?: string;
children?: React.ReactNode;
children?: React.ReactNode,
newTransactionCount?: number
}) => {
const { address, isConnected, isConnecting } = useAccount();
const { toggleAccount, toggleStarknetLogin } = useUIStore((state) => state);
Expand Down Expand Up @@ -52,6 +54,9 @@ export const StarknetLoginButton = ({
}
</span>
</span>
{(isConnected && newTransactionCount) && newTransactionCount > 0 ? <span
className={'bg-green-600 w-[20px] absolute -top-1.5 -right-1.5 rounded-full text-black'}
>{newTransactionCount}</span> : null}
</Button>
);
};
32 changes: 28 additions & 4 deletions apps/nextjs/src/app/_components/wallet/WalletSheet.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
"use client";

import { Suspense } from "react";
import { Suspense, useEffect, useRef } from "react";
import Link from "next/link";
import { Account } from "@/app/(app)/bridge/Account";
import Bridge from "@/icons/bridge.svg";
import { useUIStore } from "@/providers/UIStoreProvider";
import { useAccount as useL2Account, useNetwork } from "@starknet-react/core";

import useStore from "@/hooks/useStore";
import { useTransactionManager } from "@/stores/useTransasctionManager";
import { Button } from "@realms-world/ui/components/ui/button";
import { Dialog, DialogContent, DialogHeader, DialogTrigger } from "@realms-world/ui/components/ui/dialog";
import { ScrollArea } from "@realms-world/ui/components/ui/scroll-area";
Expand All @@ -15,9 +16,13 @@ import { Tabs, TabsContent, TabsList, TabsTrigger } from "@realms-world/ui/compo
import { WrongNetworkModal } from "../modal/WrongNetworkModal";
import EthereumAccount from "./EthereumAccount";
import StarkAccount from "./StarkAccount";
import { TransactionList } from "./transactions/TransactionList";
import { QueryTransactionList, LocalStorageTransactionList } from "./transactions/TransactionList";

export const WalletSheet = () => {
const transactionState = useStore(useTransactionManager, (state) => state);
const newTransactionCount = transactionState?.newTransactionCount;
const allTransactionsProcessed = transactionState?.allTransactionsProcessed

const {
isConnected: isL2Connected,
chainId,
Expand All @@ -29,6 +34,23 @@ export const WalletSheet = () => {

const { isAccountOpen, toggleAccount } = useUIStore((state) => state);

function usePrevious(isAccountOpen: boolean) {
const ref = useRef<boolean>();
useEffect(() => {
ref.current = isAccountOpen;
}, [isAccountOpen]);
return ref.current;
}


//after user closes wallet sheet, reset transactioncount and alltransactionsprocessed in localstorage
const previousAccountOpenState = usePrevious(isAccountOpen)
useEffect(() => {
if (isAccountOpen === false && previousAccountOpenState === true) {
transactionState?.resetTransacationCount()
}
}, [isAccountOpen])

const tabs = [
{
name: "Mainnet",
Expand Down Expand Up @@ -112,7 +134,9 @@ export const WalletSheet = () => {
</Dialog>
</div>
</div>
<TransactionList />
{/* if newTransactioncount is greater than zero, toggle querylist to add new transaction to combinedTransactions */}
{/* alltrsansactionsprocessed === false handles the scenario where user has not opened their wallet sheet yet. IE incognito window, or the localstorage state isn't set yet */}
{((newTransactionCount && newTransactionCount > 0) || allTransactionsProcessed === false) ? <QueryTransactionList /> : <LocalStorageTransactionList />}
</div>
</SheetContent>
</Sheet>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { CombinedTransaction } from "@/hooks/useTransactions";
import type { CombinedTransaction } from "@/stores/useTransasctionManager";
import { useCallback } from "react";
import { SUPPORTED_L2_CHAIN_ID } from "@/constants/env";
import { TransactionType } from "@/constants/transactions";
Expand Down Expand Up @@ -28,15 +28,15 @@ export const TransactionAction = ({ tx }: { tx: CombinedTransaction }) => {
}));
if (txHash) {
transactions?.addTx({
hash: txHash,
hash: txHash || '',
type: TransactionType.BRIDGE_REALMS_L2_TO_L1_CONFIRM,
chainId: SUPPORTED_L2_CHAIN_ID,
status: "complete",
timestamp: new Date().getTime(),
timestamp: new Date(Date.now())
});
toast({
title: TransactionType.BRIDGE_REALMS_L2_TO_L1_CONFIRM,
description: `${tokenIds.length} Realms are being withdrawn to your L1 wallet`,
description: `${tokenIds?.length} Realms are being withdrawn to your L1 wallet`,
});
}
}, [writeAsync, transactions, tx]);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import type { CombinedTransaction } from "@/hooks/useTransactions";
import type { Transaction } from "@/stores/useTransasctionManager";
import type { CombinedTransaction } from "@/stores/useTransasctionManager";
import { SUPPORTED_L2_CHAIN_ID } from "@/constants/env";
import { TransactionType } from "@/constants/transactions";

Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,39 @@
import { useTransactions } from "@/hooks/useTransactions";

import { useLocalStorageTransactions } from "@/hooks/useLocalStorageTransactions";
import { ScrollArea } from "@realms-world/ui/components/ui/scroll-area";

import { TransactionItem } from "./TransactionItem";
import useStore from "@/hooks/useStore";
import { useTransactionManager } from "@/stores/useTransasctionManager";
import { useEffect } from "react";

export const TransactionList = () => {
export const QueryTransactionList = () => {
const { transactions } = useTransactions();
const transactionState = useStore(useTransactionManager, (state) => state);
// after useTransactions fires, update stored combinedtransactions in localstorage
useEffect(() => {
transactionState?.updateCombinedTransactions(transactions);
}, [transactions]);
return (
<div className="mt-2 flex h-full w-full flex-grow flex-col border-b p-2">
<span className="mb-2 font-sans text-sm">Transactions</span>
<ScrollArea className="pr-2 [&>[data-radix-scroll-area-viewport]]:max-h-[500px]">
{transactions?.map((tx, index) => {
return <TransactionItem tx={tx} key={tx.hash + index} />;
})}
</ScrollArea>
</div>
);
};


export const LocalStorageTransactionList = () => {
// if newTransactioncount is 0, use localstorage transactions instead
const { transactions } = useLocalStorageTransactions();
return (
<div className="mt-2 flex h-full w-full flex-grow flex-col border-b p-2">
<span className="mb-2 font-sans text-sm">Transactions</span>
<ScrollArea className="pr-2 [&>[data-radix-scroll-area-viewport]]:max-h-[500px]">
{transactions.map((tx, index) => {
{transactions?.map((tx, index) => {
return <TransactionItem tx={tx} key={tx.hash + index} />;
})}
</ScrollArea>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ export const usePendingRealmsWithdrawals = ({
} else {
variables.status = ["ACCEPTED_ON_L1", "FINISHED"];
}

return useQuery({
queryKey: ["pendingRealmsWithdrawals" + address + status],
queryFn: async () =>
Expand All @@ -67,6 +68,5 @@ export const usePendingRealmsWithdrawals = ({
return res.data?.withdrawals;
}),
enabled: !!address,
refetchInterval: 20000,
});
};
9 changes: 9 additions & 0 deletions apps/nextjs/src/hooks/useLocalStorageTransactions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import useStore from "@/hooks/useStore";
import { useTransactionManager } from "@/stores/useTransasctionManager";

export const useLocalStorageTransactions = () => {
const transactionState = useStore(useTransactionManager, (state) => state);
return {
transactions: transactionState?.combinedTransactions,
};
};
41 changes: 19 additions & 22 deletions apps/nextjs/src/hooks/useTransactions.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { Transaction } from "@/stores/useTransasctionManager";
import type { RealmsWithdrawal, RealmsWithdrawalEvent } from "@/types/subgraph";
import { useMemo } from "react";
import type { CombinedTransaction } from "@/stores/useTransasctionManager";
import type { RealmsWithdrawalEvent } from "@/types/subgraph";
import { useEffect, useMemo } from "react";
import { SUPPORTED_L1_CHAIN_ID, SUPPORTED_L2_CHAIN_ID } from "@/constants/env";
import {
BridgeTransactionType,
Expand All @@ -14,36 +14,29 @@ import { useAccount as useStarknetAccount } from "@starknet-react/core";
import { useAccount } from "wagmi";

import type { RouterInputs, RouterOutputs } from "@realms-world/api";
import type { ChainId } from "@realms-world/constants";
import { ChainId } from "@realms-world/constants";
import { padAddress } from "@realms-world/utils";

export interface CombinedTransaction
extends Transaction,
Partial<RealmsWithdrawal> {
tokenIds?: string[];
}

export const useTransactions = () => {
const transactions = useStore(
useTransactionManager,
(state) => state.transactions,
);
const transactionState = useStore(useTransactionManager, (state) => state);
const transactions = transactionState?.transactions;

const { address } = useAccount();
const { address: l2Address } = useStarknetAccount();

// grabs all pending realm withdrawals
const { data: pendingWithdrawals } = usePendingRealmsWithdrawals({ address });

const filters: RouterInputs["erc721Bridge"]["all"] = useMemo(
() => ({
l1Account: padAddress(address),
l2Account: padAddress(l2Address),
}),
[address, l2Address],
);

const { data: l2BridgeTransactions } = api.erc721Bridge.all.useQuery(
filters,
{
refetchInterval: 30000,
enabled: !!address || !!l2Address,
},
);
Expand All @@ -67,6 +60,7 @@ export const useTransactions = () => {
},
]),
);

pendingWithdrawals?.forEach((withdrawal) => {
if (withdrawal.req_hash) {
const matchingTransaction = map.get(withdrawal.req_hash);
Expand Down Expand Up @@ -109,7 +103,7 @@ export const useTransactions = () => {
const transactionsArray = Array.from(l2TransactionsMap.values()).map(
(tx) => ({
...tx,
req_hash: tx.req_hash ? BigInt(tx.req_hash) : undefined,
req_hash: tx.req_hash ? tx.req_hash : undefined,
}),
);
// Add transactions to the map, deduplicating by hash
Expand All @@ -120,11 +114,13 @@ export const useTransactions = () => {
});

// Add any additional transactions that might not be in the l2TransactionsMap
(transactions ?? []).forEach((tx) => {
if (tx.hash && !transactionsMap.has(tx.hash)) {
transactionsMap.set(tx.hash, tx);
}
});
if (transactions?.length) {
transactions.forEach((tx) => {
if (tx.hash && !transactionsMap.has(tx.hash)) {
transactionsMap.set(tx.hash, tx);
}
});
}

// Convert the map back to an array
const deduplicatedArray = Array.from(transactionsMap.values());
Expand All @@ -138,6 +134,7 @@ export const useTransactions = () => {

return deduplicatedArray;
}, [l2TransactionsMap, transactions]);

return {
transactions: combinedTransactions,
};
Expand Down
Loading

0 comments on commit b935417

Please sign in to comment.