Skip to content

Commit

Permalink
feat: move wallet provider logic in react context
Browse files Browse the repository at this point in the history
  • Loading branch information
totraev committed Sep 26, 2024
1 parent ea459b9 commit 5fcdde1
Show file tree
Hide file tree
Showing 9 changed files with 262 additions and 211 deletions.
67 changes: 39 additions & 28 deletions src/app/components/Delegations/Delegations.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { networks } from "bitcoinjs-lib";
import type { networks } from "bitcoinjs-lib";
import { useEffect, useState } from "react";
import InfiniteScroll from "react-infinite-scroll-component";
import { useLocalStorage } from "usehooks-ts";
Expand All @@ -7,6 +7,7 @@ import { SignPsbtTransaction } from "@/app/common/utils/psbt";
import { LoadingTableList } from "@/app/components/Loading/Loading";
import { DelegationsPointsProvider } from "@/app/context/api/DelegationsPointsProvider";
import { useError } from "@/app/context/Error/ErrorContext";
import { useWallet } from "@/app/context/wallet/WalletProvider";
import { useHealthCheck } from "@/app/hooks/useHealthCheck";
import { QueryMeta } from "@/app/types/api";
import {
Expand Down Expand Up @@ -34,14 +35,10 @@ interface DelegationsProps {
delegationsAPI: DelegationInterface[];
delegationsLocalStorage: DelegationInterface[];
globalParamsVersion: GlobalParamsVersion;
publicKeyNoCoord: string;
btcWalletNetwork: networks.Network;
address: string;
signPsbtTx: SignPsbtTransaction;
pushTx: WalletProvider["pushTx"];
queryMeta: QueryMeta;
getNetworkFees: WalletProvider["getNetworkFees"];
isWalletConnected: boolean;
}

export const Delegations: React.FC<DelegationsProps> = ({
Expand All @@ -52,36 +49,50 @@ export const Delegations: React.FC<DelegationsProps> = ({
pushTx,
queryMeta,
getNetworkFees,
address,
btcWalletNetwork,
publicKeyNoCoord,
isWalletConnected,
}) => {
const { address, publicKeyNoCoord, connected, network } = useWallet();

return (
<DelegationsPointsProvider
publicKeyNoCoord={publicKeyNoCoord}
delegationsAPI={delegationsAPI}
isWalletConnected={isWalletConnected}
address={address}
>
<DelegationsContent
network && (
<DelegationsPointsProvider
publicKeyNoCoord={publicKeyNoCoord}
delegationsAPI={delegationsAPI}
delegationsLocalStorage={delegationsLocalStorage}
globalParamsVersion={globalParamsVersion}
signPsbtTx={signPsbtTx}
pushTx={pushTx}
queryMeta={queryMeta}
getNetworkFees={getNetworkFees}
isWalletConnected={connected}
address={address}
btcWalletNetwork={btcWalletNetwork}
publicKeyNoCoord={publicKeyNoCoord}
isWalletConnected={isWalletConnected}
/>
</DelegationsPointsProvider>
>
<DelegationsContent
delegationsAPI={delegationsAPI}
delegationsLocalStorage={delegationsLocalStorage}
globalParamsVersion={globalParamsVersion}
signPsbtTx={signPsbtTx}
pushTx={pushTx}
queryMeta={queryMeta}
getNetworkFees={getNetworkFees}
address={address}
btcWalletNetwork={network}
publicKeyNoCoord={publicKeyNoCoord}
isWalletConnected={connected}
/>
</DelegationsPointsProvider>
)
);
};

const DelegationsContent: React.FC<DelegationsProps> = ({
interface DelegationsContentProps {
delegationsAPI: DelegationInterface[];
delegationsLocalStorage: DelegationInterface[];
globalParamsVersion: GlobalParamsVersion;
publicKeyNoCoord: string;
btcWalletNetwork: networks.Network;
address: string;
signPsbtTx: SignPsbtTransaction;
pushTx: WalletProvider["pushTx"];
queryMeta: QueryMeta;
getNetworkFees: WalletProvider["getNetworkFees"];
isWalletConnected: boolean;
}

const DelegationsContent: React.FC<DelegationsContentProps> = ({
delegationsAPI,
delegationsLocalStorage,
globalParamsVersion,
Expand Down
15 changes: 6 additions & 9 deletions src/app/components/Header/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { useWallet } from "@/app/context/wallet/WalletProvider";
import { shouldDisplayTestingMsg } from "@/config";

import { ConnectSmall } from "../Connect/ConnectSmall";
Expand All @@ -8,19 +9,15 @@ import { ThemeToggle } from "../ThemeToggle/ThemeToggle";

interface HeaderProps {
loading?: boolean;
onConnect: () => void;
address: string;
btcWalletBalanceSat?: number;
onDisconnect: () => void;
}

export const Header: React.FC<HeaderProps> = ({
loading,
onConnect,
address,
btcWalletBalanceSat,
onDisconnect,
}) => {
const { address, open, disconnect } = useWallet();

return (
<nav>
<div className="bg-base-300 shadow-sm">
Expand All @@ -35,10 +32,10 @@ export const Header: React.FC<HeaderProps> = ({
</div>
<ConnectSmall
loading={loading}
onConnect={onConnect}
onConnect={open}
address={address}
btcWalletBalanceSat={btcWalletBalanceSat}
onDisconnect={onDisconnect}
onDisconnect={disconnect}
/>
<ThemeToggle />
</div>
Expand All @@ -49,7 +46,7 @@ export const Header: React.FC<HeaderProps> = ({
loading={loading}
address={address}
btcWalletBalanceSat={btcWalletBalanceSat}
onDisconnect={onDisconnect}
onDisconnect={disconnect}
/>
</div>
</div>
Expand Down
10 changes: 4 additions & 6 deletions src/app/components/Modals/ConnectModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,10 @@ export const ConnectModal: React.FC<ConnectModalProps> = ({
// Check if the browser wallet is injectable
if (window[BROWSER]) {
// Get the name and icon of the injected wallet
const name =
window[BROWSER].getWalletProviderName &&
(await window[BROWSER].getWalletProviderName());
const icon =
window[BROWSER].getWalletProviderIcon &&
(await window[BROWSER].getWalletProviderIcon());
const [name, icon] = await Promise.all([
window[BROWSER].getWalletProviderName?.(),
window[BROWSER].getWalletProviderIcon?.(),
]);
// Set the name and icon of the injected wallet if they exist
name && setInjectedWalletProviderName(`${name} (Browser)`);
icon && setInjectedWalletProviderIcon(icon);
Expand Down
12 changes: 5 additions & 7 deletions src/app/components/Staking/Form/States/WalletNotConnected.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
import Image from "next/image";

import { useWallet } from "@/app/context/wallet/WalletProvider";

import connectIcon from "./connect-icon.svg";
import walletIcon from "./wallet-icon.svg";

interface WalletNotConnectedProps {
onConnect: () => void;
}
export const WalletNotConnected = () => {
const { open } = useWallet();

export const WalletNotConnected: React.FC<WalletNotConnectedProps> = ({
onConnect,
}) => {
return (
<div className="flex flex-1 flex-col">
<div className="flex flex-1 flex-col items-center justify-center gap-2 py-12">
Expand All @@ -21,7 +19,7 @@ export const WalletNotConnected: React.FC<WalletNotConnectedProps> = ({
Please connect wallet to start staking
</p>
</div>
<button className="btn-primary btn" onClick={onConnect}>
<button className="btn-primary btn" onClick={open}>
<Image src={connectIcon} alt="Connect wallet" />
Connect wallet
</button>
Expand Down
29 changes: 13 additions & 16 deletions src/app/components/Staking/Staking.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useQuery, useQueryClient } from "@tanstack/react-query";
import { networks, Transaction } from "bitcoinjs-lib";
import { Transaction } from "bitcoinjs-lib";
import { Dispatch, SetStateAction, useEffect, useMemo, useState } from "react";
import { Tooltip } from "react-tooltip";
import { useLocalStorage } from "usehooks-ts";
Expand All @@ -13,6 +13,7 @@ import { LoadingView } from "@/app/components/Loading/Loading";
import { useError } from "@/app/context/Error/ErrorContext";
import { useGlobalParams } from "@/app/context/api/GlobalParamsProvider";
import { useStakingStats } from "@/app/context/api/StakingStatsProvider";
import { useWallet } from "@/app/context/wallet/WalletProvider";
import { useHealthCheck } from "@/app/hooks/useHealthCheck";
import { Delegation } from "@/app/types/delegations";
import { ErrorHandlerParam, ErrorState } from "@/app/types/errors";
Expand All @@ -32,7 +33,7 @@ import {
} from "@/utils/globalParams";
import { isStakingSignReady } from "@/utils/isStakingSignReady";
import { toLocalStorageDelegation } from "@/utils/local_storage/toLocalStorageDelegation";
import { UTXO, WalletProvider } from "@/utils/wallet/wallet_provider";
import type { UTXO } from "@/utils/wallet/wallet_provider";

import { FeedbackModal } from "../Modals/FeedbackModal";
import { PreviewModal } from "../Modals/PreviewModal";
Expand All @@ -58,32 +59,28 @@ interface OverflowProperties {
interface StakingProps {
btcHeight: number | undefined;
disabled?: boolean;
isWalletConnected: boolean;
isLoading: boolean;
onConnect: () => void;
btcWallet: WalletProvider | undefined;
btcWalletBalanceSat?: number;
btcWalletNetwork: networks.Network | undefined;
address: string | undefined;
publicKeyNoCoord: string;
setDelegationsLocalStorage: Dispatch<SetStateAction<Delegation[]>>;
availableUTXOs?: UTXO[] | undefined;
}

export const Staking: React.FC<StakingProps> = ({
btcHeight,
disabled = false,
isWalletConnected,
onConnect,
isLoading,
btcWallet,
btcWalletNetwork,
address,
publicKeyNoCoord,
setDelegationsLocalStorage,
btcWalletBalanceSat,
availableUTXOs,
}) => {
const {
connected,
address,
publicKeyNoCoord,
walletProvider: btcWallet,
network: btcWalletNetwork,
} = useWallet();

// Staking form state
const [stakingAmountSat, setStakingAmountSat] = useState(0);
const [stakingTimeBlocks, setStakingTimeBlocks] = useState(0);
Expand Down Expand Up @@ -537,8 +534,8 @@ export const Staking: React.FC<StakingProps> = ({
);
}
// Wallet is not connected
else if (!isWalletConnected) {
return <WalletNotConnected onConnect={onConnect} />;
else if (!connected) {
return <WalletNotConnected />;
}
// Wallet is connected but we are still loading the staking params
else if (isLoading || areMempoolFeeRatesLoading) {
Expand Down
13 changes: 12 additions & 1 deletion src/app/context/Error/ErrorContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import React, {
useState,
} from "react";

import { ErrorModal } from "@/app/components/Modals/ErrorModal";
import {
ErrorHandlerParam,
ErrorType,
Expand Down Expand Up @@ -92,7 +93,17 @@ export const ErrorProvider: React.FC<ErrorProviderProps> = ({ children }) => {
};

return (
<ErrorContext.Provider value={value}>{children}</ErrorContext.Provider>
<ErrorContext.Provider value={value}>
{children}
<ErrorModal
open={isErrorOpen}
errorMessage={error.message}
errorState={error.errorState}
onClose={hideError}
onRetry={retryErrorAction}
noCancel={isNoCancel}
/>
</ErrorContext.Provider>
);
};

Expand Down
Loading

0 comments on commit 5fcdde1

Please sign in to comment.