@macalinao/grill
Version:
Modern Solana development kit for React applications with automatic account batching, caching, and transaction notifications
191 lines • 7.9 kB
JavaScript
import { jsx as _jsx } from "react/jsx-runtime";
import { useCallback, useRef } from "react";
import { toast } from "sonner";
import { GrillHeadlessProvider } from "./grill-headless-provider.js";
/**
* Provider component for Solana account batching functionality with transaction toast notifications.
* Wraps GrillHeadlessProvider and adds automatic toast notifications via sonner.
*/
export const GrillProvider = ({ children, onTransactionStatusEvent, showToasts = true, successToastDuration = 5000, errorToastDuration = 7000, ...props }) => {
// Store toast IDs for each transaction
const toastIds = useRef(new Map());
const handleTransactionStatus = useCallback((event) => {
// Call custom handler if provided
onTransactionStatusEvent?.(event);
// Skip toast notifications if disabled
if (!showToasts) {
return;
}
const txId = event.id;
const existingToastId = toastIds.current.get(txId);
// Helper to create explorer link action
const createExplorerAction = (link) => ({
label: "View",
onClick: () => window.open(link, "_blank"),
});
switch (event.type) {
case "error-wallet-not-connected": {
// Clean up any existing toast
if (existingToastId) {
toast.dismiss(existingToastId);
toastIds.current.delete(txId);
}
toast.error("Wallet not connected", {
description: "Please connect your wallet to continue",
duration: errorToastDuration,
});
break;
}
case "error-transaction-send-failed": {
console.error("Error sending transaction", event);
const description = event.errorMessage;
if (existingToastId) {
// Update existing toast to error
toast.error(event.title, {
id: existingToastId,
description,
duration: errorToastDuration,
});
}
else {
// Create new error toast if somehow we don't have one
toast.error(event.title, {
description,
duration: errorToastDuration,
});
}
// Clean up toast ID after error
toastIds.current.delete(txId);
break;
}
case "preparing": {
// Clean up any existing toast for this transaction
if (existingToastId) {
toast.dismiss(existingToastId);
toastIds.current.delete(txId);
}
const toastId = toast.loading(event.title, {
description: "Building transaction",
});
toastIds.current.set(txId, toastId);
break;
}
case "awaiting-wallet-signature": {
// Update existing toast or create new one
const description = "Please approve in your wallet";
if (existingToastId) {
toast.loading(event.title, {
id: existingToastId,
description,
});
}
else {
const toastId = toast.loading(event.title, {
description,
});
toastIds.current.set(txId, toastId);
}
break;
}
case "waiting-for-confirmation": {
// Update existing toast or create new one
const description = `Transaction: ${event.sig.slice(0, 8)}...${event.sig.slice(-8)}`;
const action = createExplorerAction(event.explorerLink);
if (existingToastId) {
toast.loading(event.title, {
id: existingToastId,
description,
action,
});
}
else {
const toastId = toast.loading(event.title, {
description,
action,
});
toastIds.current.set(txId, toastId);
}
break;
}
case "confirmed": {
const description = `Transaction: ${event.sig.slice(0, 8)}...${event.sig.slice(-8)}`;
const action = createExplorerAction(event.explorerLink);
console.log({ event, existingToastId, description, action });
if (existingToastId) {
// Update existing toast to success
toast.success(event.title, {
id: existingToastId,
description,
duration: successToastDuration,
action,
});
}
else {
// Create new success toast if somehow we don't have one
toast.success(event.title, {
description,
duration: successToastDuration,
action,
});
}
// Clean up toast ID after success
toastIds.current.delete(txId);
break;
}
case "error-transaction-failed": {
console.error("Transaction failed", event);
const description = event.errorMessage;
const action = createExplorerAction(event.explorerLink);
if (existingToastId) {
// Update existing toast to error
toast.error(event.title, {
id: existingToastId,
description,
duration: errorToastDuration,
action,
});
}
else {
// Create new error toast if somehow we don't have one
toast.error(event.title, {
description,
duration: errorToastDuration,
action,
});
}
// Clean up toast ID after error
toastIds.current.delete(txId);
break;
}
case "error-simulation-failed": {
console.error("Simulation failed", event);
const description = `Simulation failed: ${event.errorMessage}`;
if (existingToastId) {
// Update existing toast to error
toast.error(event.title, {
id: existingToastId,
description,
duration: errorToastDuration,
});
}
else {
// Create new error toast if somehow we don't have one
toast.error(event.title, {
description,
duration: errorToastDuration,
});
}
// Clean up toast ID after error
toastIds.current.delete(txId);
break;
}
}
}, [
onTransactionStatusEvent,
showToasts,
successToastDuration,
errorToastDuration,
]);
return (_jsx(GrillHeadlessProvider, { onTransactionStatusEvent: handleTransactionStatus, ...props, children: children }));
};
//# sourceMappingURL=grill-provider.js.map