Change hook logic

merge-requests/3333/head
danidfra 2025-03-21 16:51:17 -03:00
rodzic 3307ae57fb
commit 27aa66d279
12 zmienionych plików z 166 dodań i 189 usunięć

Wyświetl plik

@ -29,7 +29,6 @@ import thumbUpIcon from '@tabler/icons/outline/thumb-up.svg';
import trashIcon from '@tabler/icons/outline/trash.svg';
import uploadIcon from '@tabler/icons/outline/upload.svg';
import volume3Icon from '@tabler/icons/outline/volume-3.svg';
import { useEffect } from 'react';
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
import { useHistory, useRouteMatch } from 'react-router-dom';
@ -49,8 +48,7 @@ import DropdownMenu from 'soapbox/components/dropdown-menu/index.ts';
import PureStatusReactionWrapper from 'soapbox/components/pure-status-reaction-wrapper.tsx';
import StatusActionButton from 'soapbox/components/status-action-button.tsx';
import HStack from 'soapbox/components/ui/hstack.tsx';
import { useCashu } from 'soapbox/features/zap/hooks/useCashu.ts';
import { useApi } from 'soapbox/hooks/useApi.ts';
import { useNutzapRequest, useWallet } from 'soapbox/features/zap/hooks/useHooks.ts';
import { useAppDispatch } from 'soapbox/hooks/useAppDispatch.ts';
import { useAppSelector } from 'soapbox/hooks/useAppSelector.ts';
import { useDislike } from 'soapbox/hooks/useDislike.ts';
@ -166,7 +164,6 @@ const PureStatusActionBar: React.FC<IPureStatusActionBar> = ({
statusActionButtonTheme = 'default',
}) => {
const intl = useIntl();
const api = useApi(); // TODO: Remove this part after patrick implement in backend
const history = useHistory();
const dispatch = useAppDispatch();
const match = useRouteMatch<{ groupSlug: string }>('/group/:groupSlug');
@ -183,8 +180,9 @@ const PureStatusActionBar: React.FC<IPureStatusActionBar> = ({
const features = useFeatures();
const { boostModal, deleteModal } = useSettings();
const { wallet, getWallet, nutzapsList } = useCashu();
const isNutzapped = Object.keys(nutzapsList).some((nutzap)=> nutzap === status.id); // TODO: Remove "getWallet" to
const { wallet } = useWallet();
const { nutzapsList } = useNutzapRequest();
const isNutzapped = Object.keys(nutzapsList).some((nutzap)=> nutzap === status.id); // TODO: Remove "getWallet" after been in backend
const { account } = useOwnAccount();
const isStaff = account ? account.staff : false;
@ -200,12 +198,6 @@ const PureStatusActionBar: React.FC<IPureStatusActionBar> = ({
const { unpinFromGroup, pinToGroup } = usePinGroup();
const { initReport } = useInitReport();
useEffect(
() => {
getWallet(api, false);
} // TODO: Remove
, []);
if (!status) {
return null;
}

Wyświetl plik

@ -29,7 +29,6 @@ import thumbUpIcon from '@tabler/icons/outline/thumb-up.svg';
import trashIcon from '@tabler/icons/outline/trash.svg';
import uploadIcon from '@tabler/icons/outline/upload.svg';
import volume3Icon from '@tabler/icons/outline/volume-3.svg';
import { useEffect } from 'react';
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
import { useHistory, useRouteMatch } from 'react-router-dom';
@ -50,8 +49,7 @@ import DropdownMenu from 'soapbox/components/dropdown-menu/index.ts';
import StatusActionButton from 'soapbox/components/status-action-button.tsx';
import StatusReactionWrapper from 'soapbox/components/status-reaction-wrapper.tsx';
import HStack from 'soapbox/components/ui/hstack.tsx';
import { useCashu } from 'soapbox/features/zap/hooks/useCashu.ts';
import { useApi } from 'soapbox/hooks/useApi.ts';
import { useNutzapRequest, useWallet } from 'soapbox/features/zap/hooks/useHooks.ts';
import { useAppDispatch } from 'soapbox/hooks/useAppDispatch.ts';
import { useAppSelector } from 'soapbox/hooks/useAppSelector.ts';
import { useFeatures } from 'soapbox/hooks/useFeatures.ts';
@ -162,7 +160,6 @@ const StatusActionBar: React.FC<IStatusActionBar> = ({
}) => {
const intl = useIntl();
const history = useHistory();
const api = useApi(); // TODO: Remove this part after patrick implement in backend
const dispatch = useAppDispatch();
const match = useRouteMatch<{ groupSlug: string }>('/group/:groupSlug');
@ -178,7 +175,8 @@ const StatusActionBar: React.FC<IStatusActionBar> = ({
const features = useFeatures();
const { boostModal, deleteModal } = useSettings();
const { wallet, getWallet, nutzapsList } = useCashu();
const { wallet } = useWallet();
const { nutzapsList } = useNutzapRequest();
const isNutzapped = Object.keys(nutzapsList).some((nutzap)=> nutzap === status.id);
const { account } = useOwnAccount();
@ -188,12 +186,6 @@ const StatusActionBar: React.FC<IStatusActionBar> = ({
const { toggleReblog } = useReblog();
const { bookmark, unbookmark } = useBookmark();
useEffect(
() => {
getWallet(api, false);
} // TODO: remove
, []);
if (!status) {
return null;
}

Wyświetl plik

@ -21,7 +21,6 @@ import userIcon from '@tabler/icons/outline/user.svg';
import { useMutation } from '@tanstack/react-query';
import { List as ImmutableList } from 'immutable';
import { nip19 } from 'nostr-tools';
import { useEffect } from 'react';
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
import { useHistory } from 'react-router-dom';
@ -45,9 +44,8 @@ import VerificationBadge from 'soapbox/components/verification-badge.tsx';
import MovedNote from 'soapbox/features/account-timeline/components/moved-note.tsx';
import ActionButton from 'soapbox/features/ui/components/action-button.tsx';
import SubscriptionButton from 'soapbox/features/ui/components/subscription-button.tsx';
import { useCashu } from 'soapbox/features/zap/hooks/useCashu.ts';
import { useWallet } from 'soapbox/features/zap/hooks/useHooks.ts';
import { usePaymentMethod } from 'soapbox/features/zap/usePaymentMethod.ts';
import { useApi } from 'soapbox/hooks/useApi.ts';
import { useAppDispatch } from 'soapbox/hooks/useAppDispatch.ts';
import { useAppSelector } from 'soapbox/hooks/useAppSelector.ts';
import { useFeatures } from 'soapbox/hooks/useFeatures.ts';
@ -113,7 +111,6 @@ interface IHeader {
const Header: React.FC<IHeader> = ({ account }) => {
const intl = useIntl();
const history = useHistory();
const api = useApi(); // TODO: Remove this part after patrick implement in backend
const dispatch = useAppDispatch();
const features = useFeatures();
@ -124,7 +121,7 @@ const Header: React.FC<IHeader> = ({ account }) => {
const { software } = useAppSelector((state) => parseVersion(state.instance.version));
const { wallet, getWallet } = useCashu();
const { wallet } = useWallet();
const { getOrCreateChatByAccountId } = useChats();
@ -145,13 +142,6 @@ const Header: React.FC<IHeader> = ({ account }) => {
},
});
useEffect(
() => {
getWallet(api, false);
} // TODO: remove
, []);
if (!account) {
return (
<div>

Wyświetl plik

@ -19,7 +19,7 @@ import Input from 'soapbox/components/ui/input.tsx';
import Stack from 'soapbox/components/ui/stack.tsx';
import Text from 'soapbox/components/ui/text.tsx';
import { SelectDropdown } from 'soapbox/features/forms/index.tsx';
import { useCashu } from 'soapbox/features/zap/hooks/useCashu.ts';
import { useWallet } from 'soapbox/features/zap/hooks/useHooks.ts';
import { useApi } from 'soapbox/hooks/useApi.ts';
import { useOwnAccount } from 'soapbox/hooks/useOwnAccount.ts';
import { Quote, quoteSchema } from 'soapbox/schemas/wallet.ts';
@ -90,7 +90,7 @@ const NewMint = ({ onBack, list }: NewMintProps) => {
const [currentState, setCurrentState] = useState<'loading' | 'paid' | 'default'>('default');
const api = useApi();
const intl = useIntl();
const { getWallet } = useCashu();
const { getWallet } = useWallet();
const now = Math.floor(Date.now() / 1000);
@ -112,7 +112,7 @@ const NewMint = ({ onBack, list }: NewMintProps) => {
toast.success(intl.formatMessage(messages.paidMessage));
onBack();
// onChange();
getWallet(api);
getWallet(); // TODO: Remove
handleClean();
setCurrentState('default');
}
@ -236,8 +236,7 @@ const NewMint = ({ onBack, list }: NewMintProps) => {
};
const Balance = () => {
const api = useApi();
const { wallet, getWallet } = useCashu();
const { wallet } = useWallet();
const [amount, setAmount] = useState(0);
const [mints, setMints] = useState<string[]>([]);
const { account } = useOwnAccount();
@ -248,10 +247,6 @@ const Balance = () => {
newMint: <NewMint onBack={() => setCurrent('balance')} list={mints} />,
};
useEffect(() => {
getWallet(api);
}, []);
useEffect(
() => {
if (wallet){

Wyświetl plik

@ -11,8 +11,7 @@ import Stack from 'soapbox/components/ui/stack.tsx';
import SvgIcon from 'soapbox/components/ui/svg-icon.tsx';
import Text from 'soapbox/components/ui/text.tsx';
import { MintEditor } from 'soapbox/features/wallet/components/editable-lists.tsx';
import { useCashu } from 'soapbox/features/zap/hooks/useCashu.ts';
import { useApi } from 'soapbox/hooks/useApi.ts';
import { useWallet } from 'soapbox/features/zap/hooks/useHooks.ts';
import { useOwnAccount } from 'soapbox/hooks/useOwnAccount.ts';
const messages = defineMessages({
@ -23,13 +22,12 @@ const messages = defineMessages({
});
const CreateWallet = () => {
const api = useApi();
const intl = useIntl();
const { account } = useOwnAccount();
const [formActive, setFormActive] = useState(false);
const [isLoading, setIsLoading] = useState(false);
const [mints, setMints] = useState<string[]>([]);
const { createWallet } = useCashu();
const { createWallet } = useWallet();
const handleSubmit = async () => {
setIsLoading(true);
@ -39,7 +37,7 @@ const CreateWallet = () => {
relays: [],
};
await createWallet(api, walletInfo);
await createWallet(walletInfo);
setIsLoading(false);
};

Wyświetl plik

@ -2,7 +2,6 @@ import arrowBarDownIcon from '@tabler/icons/outline/arrow-bar-down.svg';
import arrowBarUpIcon from '@tabler/icons/outline/arrow-bar-up.svg';
import moreIcon from '@tabler/icons/outline/dots-circle-horizontal.svg';
import questionIcon from '@tabler/icons/outline/question-mark.svg';
import { useEffect } from 'react';
import { FormattedDate, defineMessages, useIntl } from 'react-intl';
import Button from 'soapbox/components/ui/button.tsx';
@ -12,8 +11,7 @@ import Spinner from 'soapbox/components/ui/spinner.tsx';
import Stack from 'soapbox/components/ui/stack.tsx';
import SvgIcon from 'soapbox/components/ui/svg-icon.tsx';
import Text from 'soapbox/components/ui/text.tsx';
import { useCashu } from 'soapbox/features/zap/hooks/useCashu.ts';
import { useApi } from 'soapbox/hooks/useApi.ts';
import { useTransactions } from 'soapbox/features/zap/hooks/useHooks.ts';
import { useOwnAccount } from 'soapbox/hooks/useOwnAccount.ts';
const themes = {
@ -95,15 +93,8 @@ const TransactionItem = (e: { amount: number; created_at: number ; direction: '
const Transactions = () => {
const intl = useIntl();
const api = useApi();
const { account } = useOwnAccount();
const { transactions, getTransactions } = useCashu();
useEffect(
() => {
getTransactions(api);
}
, []);
const { transactions } = useTransactions();
if (!account) {
return null;

Wyświetl plik

@ -5,7 +5,7 @@ import Button from 'soapbox/components/ui/button.tsx';
import { Column } from 'soapbox/components/ui/column.tsx';
import Stack from 'soapbox/components/ui/stack.tsx';
import { MintEditor } from 'soapbox/features/wallet/components/editable-lists.tsx';
import { useCashu } from 'soapbox/features/zap/hooks/useCashu.ts';
import { useWallet } from 'soapbox/features/zap/hooks/useHooks.ts';
import { useApi } from 'soapbox/hooks/useApi.ts';
import toast from 'soapbox/toast.tsx';
import { isURL } from 'soapbox/utils/auth.ts';
@ -23,7 +23,7 @@ const messages = defineMessages({
const WalletMints = () => {
const intl = useIntl();
const api = useApi();
const { wallet, getWallet } = useCashu();
const { wallet } = useWallet();
const [relays, setRelays] = useState<string[]>([]);
const [initialMints, setInitialMints] = useState<string[]>([]);
@ -56,10 +56,6 @@ const WalletMints = () => {
}
};
useEffect(() => {
getWallet(api, false);
}, []);
useEffect(
() => {
if (wallet) {

Wyświetl plik

@ -5,7 +5,7 @@ import Button from 'soapbox/components/ui/button.tsx';
import { Column } from 'soapbox/components/ui/column.tsx';
import Stack from 'soapbox/components/ui/stack.tsx';
import { RelayEditor } from 'soapbox/features/wallet/components/editable-lists.tsx';
import { useCashu } from 'soapbox/features/zap/hooks/useCashu.ts';
import { useWallet } from 'soapbox/features/zap/hooks/useHooks.ts';
import { useApi } from 'soapbox/hooks/useApi.ts';
import toast from 'soapbox/toast.tsx';
import { isURL } from 'soapbox/utils/auth.ts';
@ -23,7 +23,7 @@ const messages = defineMessages({
const WalletRelays = () => {
const intl = useIntl();
const api = useApi();
const { wallet, getWallet } = useCashu();
const { wallet } = useWallet();
const [relays, setRelays] = useState<string[]>([]);
const [initialRelays, setInitialRelays] = useState<string[]>([]);
@ -55,10 +55,6 @@ const WalletRelays = () => {
}
};
useEffect(() => {
getWallet(api, false);
}, []);
useEffect(
() => {
if (wallet) {

Wyświetl plik

@ -1,4 +1,3 @@
import { useEffect, useState } from 'react';
import { defineMessages, useIntl } from 'react-intl';
import List, { ListItem } from 'soapbox/components/list.tsx';
@ -10,15 +9,14 @@ import { SelectDropdown } from 'soapbox/features/forms/index.tsx';
import Balance from 'soapbox/features/wallet/components/balance.tsx';
import CreateWallet from 'soapbox/features/wallet/components/create-wallet.tsx';
import Transactions from 'soapbox/features/wallet/components/transactions.tsx';
import { useCashu } from 'soapbox/features/zap/hooks/useCashu.ts';
import { useWallet } from 'soapbox/features/zap/hooks/useHooks.ts';
import { usePaymentMethod } from 'soapbox/features/zap/usePaymentMethod.ts';
import { useApi } from 'soapbox/hooks/useApi.ts';
import { useOwnAccount } from 'soapbox/hooks/useOwnAccount.ts';
const messages = defineMessages({
payment: { id: 'wallet.payment', defaultMessage: 'Payment Method' },
relays: { id: 'wallet.relays', defaultMessage: 'Relays' },
relays: { id: 'wallet.relays', defaultMessage: 'Wallet Relays' },
transactions: { id: 'wallet.transactions', defaultMessage: 'Transactions' },
wallet: { id: 'wallet', defaultMessage: 'Wallet' },
management: { id: 'wallet.management', defaultMessage: 'Wallet Management' },
@ -32,19 +30,12 @@ const paymentMethods = {
/** User Wallet page. */
const Wallet = () => {
const api = useApi();
const intl = useIntl();
const { account } = useOwnAccount();
const { wallet: walletData, getWallet } = useCashu();
const [isLoading, setIsLoading] = useState<boolean>(true);
const { wallet: walletData, isLoading } = useWallet();
const { method, changeMethod } = usePaymentMethod();
useEffect(() => {
getWallet(api);
setIsLoading(false);
}, []);
if (!account) return null;
return (

Wyświetl plik

@ -21,9 +21,8 @@ import Input from 'soapbox/components/ui/input.tsx';
import Stack from 'soapbox/components/ui/stack.tsx';
import SvgIcon from 'soapbox/components/ui/svg-icon.tsx';
import Text from 'soapbox/components/ui/text.tsx';
import { useCashu } from 'soapbox/features/zap/hooks/useCashu.ts';
import { useNutzapRequest } from 'soapbox/features/zap/hooks/useHooks.ts';
import { usePaymentMethod } from 'soapbox/features/zap/usePaymentMethod.ts';
import { useApi } from 'soapbox/hooks/useApi.ts';
import { useAppDispatch } from 'soapbox/hooks/useAppDispatch.ts';
import { emojifyText } from 'soapbox/utils/emojify.tsx';
import { capitalize } from 'soapbox/utils/strings.ts';
@ -57,7 +56,6 @@ const messages = defineMessages({
const PayRequestForm = ({ account, status, onClose }: IPayRequestForm) => {
const intl = useIntl();
const api = useApi();
const dispatch = useAppDispatch();
const [zapComment, setZapComment] = useState('');
const [amount, setAmount] = useState(50);
@ -66,7 +64,7 @@ const PayRequestForm = ({ account, status, onClose }: IPayRequestForm) => {
const { method: paymentMethod } = usePaymentMethod();
const isCashu = paymentMethod === 'cashu';
const hasZapSplit = zapArrays.length > 0 && !isCashu;
const { nutzapRequest } = useCashu();
const { nutzapRequest } = useNutzapRequest();
const handleSubmit = async (e?: React.FormEvent<Element>) => {
e?.preventDefault();
@ -74,7 +72,7 @@ const PayRequestForm = ({ account, status, onClose }: IPayRequestForm) => {
const splitData = { hasZapSplit, zapSplitAccounts, splitValues };
if (isCashu) {
nutzapRequest(api, account, amount, zapComment, status);
nutzapRequest(account, amount, zapComment, status);
dispatch(closeModal('PAY_REQUEST'));
return;
}

Wyświetl plik

@ -1,100 +0,0 @@
import { produce } from 'immer';
import { create } from 'zustand';
import { MastodonClient } from 'soapbox/api/MastodonClient.ts';
import { Transactions, WalletData, baseWalletSchema, transactionsSchema } from 'soapbox/schemas/wallet.ts';
import toast from 'soapbox/toast.tsx';
import type { Account as AccountEntity, Status as StatusEntity } from 'soapbox/types/entities.ts';
interface IWalletInfo {
mints: string[];
relays: string[];
}
interface ICashuState {
nutzapsList: Record<string, { status: StatusEntity; amount: number; comment: string }>;
isLoading: boolean;
error: string | null;
wallet: WalletData | null;
transactions: Transactions | null;
createWallet: (api: MastodonClient, walletInfo: IWalletInfo) => Promise<void>;
getTransactions: (api: MastodonClient) => Promise<void>;
getWallet: (api: MastodonClient, hasMessage?: boolean) => Promise<void>;
nutzapRequest: (api: MastodonClient, account: AccountEntity, amount: number, comment: string, status?: StatusEntity) => void;
}
// TODO: Convert it into a custom hook after the backend is finished
export const useCashu = create<ICashuState>((set) => ({
nutzapsList: {},
isLoading: false,
error: null,
wallet: null,
transactions: null,
createWallet: async (api, walletInfo) => {
try {
const response = await api.put('/api/v1/ditto/cashu/wallet', walletInfo);
const data = await response.json();
if (data) {
const normalizedData = baseWalletSchema.parse(data);
toast.success('Wallet created successfully'); // TO DO: create translated text
set({ wallet: normalizedData });
}
} catch (e) {
toast.error('An error has occurred'); // TO DO: create translated text
}
},
getWallet: async (api, hasMessage = true) => {
try {
const response = await api.get('/api/v1/ditto/cashu/wallet');
const data: WalletData = await response.json();
if (data) {
const normalizedData = baseWalletSchema.parse(data);
set({ wallet: normalizedData });
}
} catch (error) {
if (hasMessage) toast.error('Wallet not found');
}
},
getTransactions: async (api) => {
try {
const response = await api.get('/api/v1/ditto/cashu/transactions');
const data: WalletData = await response.json();
if (data) {
const normalizedData = transactionsSchema.parse(data);
set({ transactions: normalizedData });
}
} catch (error) {
toast.error('Transactions not found');
}
},
nutzapRequest: async (api, account, amount, comment, status) => {
set((state) => ({ ...state, isLoading: true, error: null }));
try {
const response = await api.post('/api/v1/ditto/cashu/nutzap', {
amount,
comment,
account_id: account.id,
status_id: status?.id,
});
const data = await response.json();
set(produce((state) => {
if (status) state.nutzapsList[status.id] = { status, amount, comment };
state.isLoading = false;
}));
toast.success(data.message || 'Nutzap sent successfully!');
} catch (e) {
set((state) => ({ ...state, isLoading: false, error: e instanceof Error ? e.message : 'An unexpected error occurred' }));
toast.error(e instanceof Error ? e.message : 'An unexpected error occurred');
}
},
}));

Wyświetl plik

@ -0,0 +1,138 @@
import { useEffect, useState } from 'react';
import { useApi } from 'soapbox/hooks/useApi.ts';
import { Transactions, WalletData, baseWalletSchema, transactionsSchema } from 'soapbox/schemas/wallet.ts';
import toast from 'soapbox/toast.tsx';
import type { Account as AccountEntity, Status as StatusEntity } from 'soapbox/types/entities.ts';
interface IWalletInfo {
mints: string[];
relays: string[];
}
const useWallet = () => {
const api = useApi();
const [wallet, setWallet] = useState<WalletData | null>(null);
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
const createWallet = async (walletInfo: IWalletInfo) => {
setIsLoading(true);
try {
const response = await api.put('/api/v1/ditto/cashu/wallet', walletInfo);
const data = await response.json();
if (data) {
const normalizedData = baseWalletSchema.parse(data);
toast.success('Wallet created successfully');
setWallet(normalizedData);
}
} catch (err) {
const messageError = err instanceof Error ? err.message : 'An error has occurred';
setError(messageError);
toast.error(messageError);
} finally {
setIsLoading(false);
}
};
const getWallet = async (hasMessage = true) => {
setIsLoading(true);
try {
const response = await api.get('/api/v1/ditto/cashu/wallet');
const data: WalletData = await response.json();
if (data) {
const normalizedData = baseWalletSchema.parse(data);
setWallet(normalizedData);
}
} catch (err) {
const messageError = err instanceof Error ? err.message : 'Wallet not found';
if (hasMessage) toast.error(messageError);
setError(messageError);
} finally {
setIsLoading(false);
}
};
useEffect(() => {
if (!wallet) {
getWallet(false);
}
}, [wallet]);
return { wallet, isLoading, error, createWallet, getWallet };
};
const useTransactions = () => {
const api = useApi();
const [transactions, setTransactions] = useState<Transactions | null>(null);
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
const getTransactions = async () => {
setIsLoading(true);
try {
const response = await api.get('/api/v1/ditto/cashu/transactions');
const data: Transactions = await response.json();
if (data) {
const normalizedData = transactionsSchema.parse(data);
setTransactions(normalizedData);
}
} catch (err) {
const messageError = err instanceof Error ? err.message : 'Transactions not found';
toast.error(messageError);
setError(messageError);
} finally {
setIsLoading(false);
}
};
useEffect(() => {
if (!transactions) {
getTransactions();
}
}, [transactions]);
return { transactions, isLoading, error, getTransactions };
};
const useNutzapRequest = () => {
const api = useApi();
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
const [nutzapsList, setNutzapsList] = useState<Record<string, { status: StatusEntity; amount: number; comment: string }>>({});
const nutzapRequest = async (account: AccountEntity, amount: number, comment: string, status?: StatusEntity) => {
setIsLoading(true);
setError(null);
try {
const response = await api.post('/api/v1/ditto/cashu/nutzap', {
amount,
comment,
account_id: account.id,
status_id: status?.id,
});
const data = await response.json();
if (status) {
setNutzapsList((prevState) => ({
...prevState,
[status.id]: { status, amount, comment },
}));
}
toast.success(data.message || 'Nutzap sent successfully!');
} catch (err) {
const messageError = err instanceof Error ? err.message : 'An unexpected error occurred';
setError(messageError);
toast.error(messageError);
} finally {
setIsLoading(false);
}
};
return { nutzapsList, isLoading, error, nutzapRequest };
};
export { useWallet, useTransactions, useNutzapRequest };