UNPKG

@saberhq/sail

Version:

Account caching and batched loading for React-based Solana applications.

103 lines 3.62 kB
import mapValues from "lodash.mapvalues"; import zip from "lodash.zip"; import { startTransition, useEffect, useMemo, useState } from "react"; import { getCacheKeyOfPublicKey, SailAccountParseError, useSail } from ".."; import { useAccountsData } from "../hooks/useAccountsData"; /** * Makes account parsers from a coder. * @param parsers * @returns */ export const makeParsersFromCoder = (parsers) => { return mapValues(parsers, (p) => (info) => p(info.accountInfo.data)); }; /** * Makes hooks for parsers. * @param parsers * @returns */ export const makeParserHooks = (parsers) => { const sailParsers = makeParsersFromCoder(parsers); return mapValues(sailParsers, (parser) => ({ useSingleData: (key) => useParsedAccountData(key, parser), useData: (keys) => useParsedAccountsData(keys, parser), })); }; /** * Parses accounts with the given parser. * * @deprecated use {@link useBatchedParsedAccounts} instead * @param keys * @param parser * @returns */ export const useParsedAccountsData = (keys, parser) => { const { onError } = useSail(); const data = useAccountsData(keys); const [parsed, setParsed] = useState(keys.reduce((acc, k) => { if (k) { acc[getCacheKeyOfPublicKey(k)] = undefined; } return acc; }, {})); useEffect(() => { startTransition(() => { setParsed((prevParsed) => { const nextParsed = { ...prevParsed }; zip(keys, data).forEach(([key, datum]) => { if (datum) { const key = getCacheKeyOfPublicKey(datum.accountId); const prevValue = prevParsed[key]; if (prevValue && prevValue.raw.length === datum.accountInfo.data.length && prevValue.raw.equals(datum.accountInfo.data)) { // preserve referential equality if buffers are equal return; } try { const parsed = parser(datum); nextParsed[key] = { ...datum, accountInfo: { ...datum.accountInfo, data: parsed, }, raw: datum.accountInfo.data, }; } catch (e) { onError(new SailAccountParseError(e, datum)); nextParsed[key] = null; return; } } if (key && datum === null) { nextParsed[getCacheKeyOfPublicKey(key)] = null; } }); return nextParsed; }); }); }, [data, keys, onError, parser]); return useMemo(() => { return keys.map((k) => { if (!k) { return k; } return parsed[getCacheKeyOfPublicKey(k)]; }); }, [keys, parsed]); }; /** * Loads the parsed data of a single account. * @returns */ export const useParsedAccountData = (key, parser) => { const theKey = useMemo(() => [key], [key]); const [data] = useParsedAccountsData(theKey, parser); return { loading: key !== undefined && data === undefined, data, }; }; //# sourceMappingURL=useParsedAccountsData.js.map