https://ecency.com/hive-125125/@dkildar/ecency-developer-s-diary-1
Hello Ecenccials! This is the next part of the developer’s diary series from Ecency’s web developers. In the previous article we explained why we started the SDK and touched on architecture, project structure, and state management. Today we’ll dive into implementing Hive operations using React Query (RQ) and into sequential data streaming — both are core SDK responsibilities.
Hive operations
Remember: Hive is a blockchain-based system, which adds extra responsibility to keep the UI clean and deliver the best user experience. For blockchains we achieve both goals using pseudo-optimistic updates.
What is that? It’s when we update local state immediately after initiating a blockchain mutation, because the blockchain needs time to include and finalize the transaction. For example, updating a Hive account profile produces a Hive transaction; we should update the local copy of the account profile right away (following Hive’s account schema) so the UI responds instantly. Let's see how it looks in live(source):
export function useAccountUpdate(username: string) {
const queryClient = useQueryClient();
const { data } = useQuery(getAccountFullQueryOptions(username));
return useBroadcastMutation(
["accounts", "update", data?.name],
username,
(payload: Partial) => {
if (!data) {
throw new Error("[SDK][Accounts] – cannot update not existing account");
}
return [
[
"account_update2",
{
account: username,
json_metadata: "",
extensions: [],
posting_json_metadata: JSON.stringify({
profile: getBuiltProfile({ ...payload, data }),
}),
},
],
];
},
(_, variables) =>
queryClient.setQueryData(
getAccountFullQueryOptions(username).queryKey,
(data) => {
if (!data) {
return data;
}
const obj = R.clone(data);
obj.profile = getBuiltProfile({ ...variables, data });
return obj;
}
)
);
}
As shown, the typical pattern is: optimistic update (onSuccess
) → broadcast mutation → rollback on error (onError
). Using setQueryData
guarantees the local state is immediately up-to-date for the rest of the app.
Important: this pattern does not cover situations where the API returns 200 OK (transaction accepted for broadcasting) but the operation later proves invalid. In such cases we must detect the eventual failure using try/catch blocks.
Sequentially data streaming
Sometimes features depends on the batch of different API requests and this data can be fetched from different API hosts. For this cases We should write single queries for each request and combine them using one more query. Let's see an example(source):
export function getPointsAssetGeneralInfoQueryOptions(username: string) {
return queryOptions({
queryKey: ["assets", "points", "general-info", username],
staleTime: 60000,
refetchInterval: 90000,
queryFn: async () => {
await getQueryClient().prefetchQuery(getPointsQueryOptions(username));
const data = getQueryClient().getQueryData(
getPointsQueryOptions(username).queryKey
);
return {
name: "POINTS",
title: "Ecency Points",
price: 0.002,
accountBalance: +data?.points,
} satisfies GeneralAssetInfo;
},
});
}
As you can see above, we can access the queryClient instance and manipulate queries directly. Most of the time we need to retrieve query data one by one. A naïve approach would be to refetch each query individually, but imagine there are ten sub-queries depending on the same data—that would trigger ten separate network requests.
Instead, we use prefetchQuery. It queues a single fetch when no cached data exists, so in the example with ten sub-queries the data is fetched only once. Any new queries created afterwards won’t trigger another fetch because the data has already been prefetched. A second benefit is consistency: if you’ve made a manual change to the local data, prefetchQuery won’t overwrite it—it simply ensures the cache is warm and ready.
What about stale data?
All cached data will eventually become stale on the client. A user might stay on the same page for a long time, so we need to refresh the data periodically. React Query provides two key options for this: staleTime
and refetchInterval
.
staleTime
– Defines how long a query’s data is considered fresh. After this period the query is marked as stale, meaning the next time it’s accessed it will refetch automatically.refetchInterval
– Schedules background refetches at a fixed interval, even if the user isn’t interacting with the application. This keeps data updated without requiring a manual action.
All time-sensitive queries – such as account data, wallet balances, token history, and similar – should specify both properties to ensure the UI stays accurate.
Letter for Hive developers
The SDK can be integrated into any Hive client that uses React Query under the hood. It lets you remove boilerplate code and stop worrying about local state—everything just works automatically. Feel free to open pull requests or suggest improvements.
Source: https://github.com/ecency/sdk
This is second part of our series on the SDK and configurability. In the next posts we’ll see how SDK helps us in Configurability of Ecency Web. See you soon!