Hooks
Hooks are built on top of the providers and the core Manager API. Make sure your component tree is wrapped with ManagerProvider or CocoCashuProvider.
Operation Hook Contract
The operation hooks intentionally mirror manager.ops.* instead of inventing a separate React-only workflow model. One hook instance owns one active operation.
currentOperationis the authoritative operation record to render from.executeResultis only for execute-specific returned data, such as the token returned byuseSendOperation().execute().- Creation methods such as
prepare(...)bind the hook to the operation they create. - Follow-up methods such as
execute(),checkPayment(),finalize(),cancel(),reclaim(), andrefresh()operate on the currently bound operation, so app code should not pass anoperationIdto those methods. - The optional hook argument is initial-only. Use it to seed a resume screen from an operation object or load one persisted operation by id on mount.
- The hooks subscribe to lifecycle events and update the bound operation when the manager emits a newer state for that operation id.
refresh()is for stale persisted operations, recovery screens, or explicit user refresh actions. It is not needed as happy-path polling.reset()clears the hook's local binding,executeResult,status, anderror. It does not roll back or delete the persisted operation.status,error,isLoading, andisErrordescribe the hook's current local async action. If a second stateful action is started while one is already running, the second call rejects and does not replace the loading/error state from the first action.
For state-machine details, see Send Operations, Receive Operations, Mint Operations, and Melt Operations.
useSendOperation
Use this for the full send lifecycle, including resume, reclaim, and finalize flows.
import { useSendOperation } from '@cashu/coco-react';
const {
prepare,
execute,
currentOperation,
executeResult,
refresh,
cancel,
reclaim,
finalize,
listPrepared,
listInFlight,
status,
error,
reset,
isLoading,
isError,
} = useSendOperation();
await prepare({ mintUrl, amount: 100 });
// after the user reviews the prepared operation:
const { operation, token } = await execute();currentOperation is the persisted operation state you render from. Once the hook is bound, methods such as execute(), refresh(), cancel(), reclaim(), and finalize() operate on that bound operation. You can also start from persisted work with useSendOperation(initialOperationOrId).
The initialOperationOrId argument is initial-only. If a component stays mounted and you need to switch the hook to a different persisted operation, remount the hook or component with a new React key. Changing the hook argument on a later render does not rebind the hook.
useReceiveOperation
Use this to decode, prepare, execute, resume, and cancel receives via manager.ops.receive.*.
import { useReceiveOperation } from '@cashu/coco-react';
const { prepare, execute, currentOperation, refresh, cancel } = useReceiveOperation();
const preparedReceive = await prepare({ token });
if (preparedReceive.state === 'prepared') {
await execute();
}useMintOperation
Use this for quote-backed mint lifecycles and remote payment checks. Quote creation, import, lookup, listing, and refresh stay on manager.quotes.mint; the hook binds only to a local mint operation after prepare().
import { useManager, useMintOperation } from '@cashu/coco-react';
const manager = useManager();
const {
prepare,
execute,
checkPayment,
finalize,
currentOperation,
executeResult,
listPending,
listInFlight,
} = useMintOperation();
const quote = await manager.quotes.mint.create({
mintUrl,
amount: 100,
method: 'bolt11',
});
const pendingMint = await prepare({ quote, amount: 100 });
if (pendingMint.state === 'pending') {
await checkPayment();
}prepare() binds the hook to a pending mint operation. Import existing quotes with manager.quotes.mint.import(...), then call prepare(...) if the UI is ready to track redemption as an operation. Keep using manager.quotes.mint.refresh(...) when a component only needs quote-level state, such as an onchain quote receiving more funds.
useMeltOperation
Use this for outbound payment flows such as bolt11 melts.
import { useManager, useMeltOperation } from '@cashu/coco-react';
const manager = useManager();
const { prepare, execute, refresh, finalize, reclaim, currentOperation } = useMeltOperation();
const quote = await manager.quotes.melt.create({
mintUrl,
method: 'bolt11',
methodData: { invoice },
});
const preparedMelt = await prepare({ quote });
if (preparedMelt.state === 'prepared') {
await execute();
}Derived-data Hooks
The existing derived-data hooks remain available for balance and history views.
import { useBalances, usePaginatedHistory, useTrustedBalance } from '@cashu/coco-react';
const { balances, refresh: refreshBalances } = useBalances();
const {
history,
loadMore,
goToPage,
refresh: refreshHistory,
hasMore,
isFetching,
} = usePaginatedHistory(50);
const { balances: trustedBalances } = useTrustedBalance();useBalances() returns the full wallet snapshot:
balances.byMint[mintUrl].spendablebalances.byMint[mintUrl].reservedbalances.byMint[mintUrl].totalbalances.total
useTrustedBalance() applies the same structured shape, filtered to trusted mints only.