Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TW-687 Use balances from TZKT whenever possible #1049

Conversation

keshan3262
Copy link
Collaborator

No description provided.

@keshan3262 keshan3262 marked this pull request as ready for review January 12, 2024 15:37
lendihop
lendihop previously approved these changes Jan 15, 2024
@@ -18,8 +25,19 @@ type UseBalanceOptions = {
};

export function useBalance(assetSlug: string, address: string, opts: UseBalanceOptions = {}) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Switch-case in actions subscription doesn't keep type definition for actions' payloads. This is prone to errors slipping in.
Logic got quite convoluted. Ideally, it should look something like this:

function useRawBalance(assetSlug: string, address: string, opts: UseBalanceOptions = {}) {
  const dispatch = useDispatch();
  const nativeTezos = useTezos();
  const nativeRpcUrl = useMemo(() => nativeTezos.rpc.getRpcUrl(), [nativeTezos]);
  const { suspense = true, networkRpc = nativeRpcUrl, displayed = true, initial: fallbackData } = opts;
  const chainId = useCustomChainId(networkRpc, opts.suspense);
  const allBalances = useAllBalancesSelector();
  const assetMetadata = useAssetMetadata(assetSlug);

  const balances = useMemo(() => {
    if (!chainId) return null;

    const key = getKeyForBalancesRecord(address, chainId);

    return allBalances[key];
  }, [chainId, address]);

  const rawBalanceFromStore = balances?.data[assetSlug];

  const balancesAreKnownToStore = Boolean(balances);

  useEffect(() => {
    if (isKnownChainId(chainId) && !balancesAreKnownToStore) {
      dispatch(
        (assetSlug === TEZ_TOKEN_SLUG ? loadNativeTokenBalanceFromTzktAction : loadTokensBalancesFromTzktAction).submit(
          { chainId, publicKeyHash: address }
        )
      );
    }
  }, [balancesAreKnownToStore, chainId, address, dispatch]);

  const onChainSwrResponse = useRetryableSWR(
    displayed ? getBalanceSWRKey(tezos, assetSlug, address) : null,
    async () => {
      if (balancesAreKnownToStore) return;

      if (!assetMetadata) throw new Error('Metadata missing, when fetching balance');

      return fetchBalanceFromBlockchain(tezos, assetSlug, address, assetMetadata);
    },
    {
      suspense,
      revalidateOnFocus: false,
      dedupingInterval: 20_000,
      refreshInterval: isKnownChainId(chainId) ? 1000 : BLOCK_DURATION
    }
  );

  const value = rawBalanceFromStore ?? onChainSwrResponse.data;
  const isLoading = balances?.isLoading ?? onChainSwrResponse.isValidating;

  return { value, isLoading, assetMetadata };
}

export function useBalance(assetSlug: string, address: string, opts: UseBalanceOptions = {}) {
  const { value: rawValue, isLoading, assetMetadata } = useRawBalance(assetSlug, address, opts);

  const value = useMemo(() => {
    if (!rawValue || !assetMetadata) return opts.initial;

    return atomsToTokens(new BigNumber(rawValue), assetMetadata.decimals);
  }, [rawValue, assetMetadata]);

  return { value, isLoading };
}
  • Don't fallback on 0 in asset's decimals like so: metadata?.decimals ?? 0

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, this approach won't work as expected because there is no logic for suspense while balances are loading from TZKT. By the way, balancesAreKnownToStore is true at a part of that time

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

However, the code has been rewritten to rely on type definitions a bit more

Copy link
Collaborator

@alex-tsx alex-tsx Jan 30, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

balancesAreKnownToStore just need to point out, that balances are to be loaded from TZKT, not blockchain. E.g. chainId is supported by TZKT's APIs.

Suspense can be implemented for a custom hook. See: https://blog.logrocket.com/data-fetching-react-suspense

The main part are these lines of code, that make the whole hook much more understandable:

  const value = rawBalanceFromStore ?? onChainSwrResponse.data;
  const isLoading = balances?.isLoading ?? onChainSwrResponse.isValidating;

On balancesAreKnownToStore being true. Correction:

  useEffect(() => {
    if (isKnownChainId(chainId) && !(balancesAreKnownToStore && balances?.isLoading)) {
      // Same code here
    }
  }, [balances?.isLoading, balancesAreKnownToStore, chainId, address, dispatch]);

src/lib/temple/front/assets.ts Show resolved Hide resolved
src/app/store/balances/reducers.ts Outdated Show resolved Hide resolved
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants