@shogun-sdk/one-shot
Version:
Shogun SDK - One Shot: React Components and hooks for cross-chain swaps
106 lines • 4.08 kB
JavaScript
import { LEGO_API } from '@shogun-sdk/money-legos';
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { useShogunLego } from './../contexts/ShogunLegoContext.js';
/* ==============================
🔹 useLego Hook
============================== */
/**
* Hook to validate and prepare transaction data for purchasing NFTs.
*
* @param {UseLegoProps} props - The NFT items, token details, and user address.
* @returns {UseLegoResult} - Status, error message (if any), response data, loading state, and a refetch function.
*/
export const useLego = ({ items, token, userAddress }) => {
const { API_KEY } = useShogunLego();
// ✅ State for handling API responses, errors, and loading status
const [data, setData] = useState(null);
const [error, setError] = useState(null);
const [isLoading, setIsLoading] = useState(false);
// ✅ Ref to manage API request cancellation
const abortControllerRef = useRef(null);
// ✅ Memoized API request body to prevent unnecessary recalculations
const requestBody = useMemo(() => {
if (!items.length || !token.address || !userAddress)
return null;
return JSON.stringify({
tokenIn: {
address: token.address,
decimals: token.decimals,
chainId: token.chainId,
},
nft: items,
address: userAddress,
});
}, [items, token.address, token.decimals, token.chainId, userAddress]);
// ✅ Function to fetch data from the API
const fetchData = useCallback(async () => {
if (!requestBody) {
setError('Invalid parameters provided to useLego hook.');
return;
}
// Cancel any ongoing request before making a new one
if (abortControllerRef.current) {
abortControllerRef.current.abort();
}
// Create a new AbortController for the current request
const abortController = new AbortController();
abortControllerRef.current = abortController;
setIsLoading(true);
setError(null);
try {
const response = await fetch(`${LEGO_API}/nft/purchase`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-api-key': API_KEY,
},
body: requestBody,
signal: abortController.signal, // ✅ Allows request cancellation
});
// Prevent state updates if request was aborted
if (abortController.signal.aborted) {
return;
}
if (!response.ok) {
throw new Error(`API Error: ${response.statusText}`);
}
const result = await response.json();
setData(result?.data?.execute);
}
catch (err) {
if (err instanceof Error && err.name !== 'AbortError') {
console.error('NFT Purchase API Error:', err);
setError(err.message);
}
}
finally {
// Ensure loading state resets only if this is the latest request
if (abortControllerRef.current === abortController) {
setIsLoading(false);
abortControllerRef.current = null;
}
}
}, [API_KEY, requestBody]);
// ✅ Auto-fetch data when dependencies change
useEffect(() => {
if (requestBody) {
fetchData();
}
// Cleanup function to abort any ongoing requests when dependencies change
return () => {
if (abortControllerRef.current) {
abortControllerRef.current.abort();
abortControllerRef.current = null;
}
};
}, [fetchData, requestBody]);
// ✅ Return hook state and refetch function
return {
status: !error && !!data,
error,
data,
isLoading,
refetch: fetchData,
};
};
//# sourceMappingURL=useLego.js.map