cosmology-tech / telescope

A TypeScript Transpiler for Cosmos Protobufs ⚛️
https://cosmology.zone/products/telescope
Apache License 2.0
145 stars 43 forks source link

react-query hooks #251

Closed pyramation closed 1 year ago

pyramation commented 2 years ago

https://gist.github.com/clockworkgr/ddac5242ae6f1a5338f536b89ea0acfb https://github.com/ignite/cli/blob/12cc6a19b92ece768dad5ec20948adedc2ca661c/ignite/pkg/cosmosgen/templates/composable/index.ts.tpl

export default function useCosmosBankV1Beta1() {
  const client = useClient();
  const QueryBalance = (address: string, query: any, options: any) => {
    const key = { type: "QueryBalance", address, query };
    return useQuery(
      [key],
      () => {
        const { address, query } = key;
        return client.cosmos.bank.v1beta1.query.queryBalance(address, query ?? undefined).then((res) => res.data);
      },
      options,
    );
  };
//.....
//....
}
pyramation commented 2 years ago
/**
 *
 * @param client
 * @param account
 * @param address address of the asset, like ujuno or ibc/aosetnuhaosentuhasoentuh
 * @param options
 * @return Coin in MICRO format
 */
const nativeBalanceQuery = <TData>({
  client,
  account,
  address,
  options,
}: UseNativeBalanceQueryOptionsParams<TData>): UseQueryOptions<Coin, Error, TData> => {
  return {
    ...options,
    queryKey: ['balance', account, address],
    queryFn: () => {
      if (!client || !account) return Promise.reject(new Error('Missing client or address'))
      return client.getBalance(account, address)
    },
    ...QueryOptions.DISABLE_WITHOUT(client && account, options?.enabled),
  }
}

https://gist.github.com/adairrr/90530228a9d7317e616ef08f66bd8e8d#file-usenativebalancequeries-ts

adairrr commented 2 years ago

I imagine that it would look something like this (as you mentioned above):

export interface BalanceQuery<TData> extends ReactQueryOptions<Coin, TData> {
  account: string | undefined
  address: string
}

export const useCosmosBankBalanceQuery = <TData>({
  account,
  options,
  address,
}: BalanceQuery<TData>) => {
  const { readOnlyClient } = useReadonlyClients()
  return useQuery(
    ['balance', account, address],
    () => {
      if (!client || !account) return Promise.reject(new Error('Missing client or address'))
      return client.cosmos.bank.v1beta1.query.queryBalance(address),
    },
    {
      select: (res) => res.data,
      ...options
    }
  )
}
pyramation commented 2 years ago

one idea @adairrr

  1. hooks for endpoints and RpcClients

    • useRpcEndpoint
    • useRpcClient
  2. a way to cache the clients

  3. here are all the hooks in action

caveat: strangely, it doesn't work on load, but if you edit code the hotloading somehow triggers a render and then all the hooks work great and fetches balance. I think it's a null value getting cached somehow

adairrr commented 2 years ago

For the RPC endpoint and client we could also just use normal React Contexts with something like :

// helper function that just breaks the provider and hook into an array
const [useTendermintClient, TendermintProvider] = createContext<{ client: Tendermint34Client{ }>('tendermintClients')
export const TendermintClientProvider: FC<PropsWithChildren<{ rpcEndpoint: string }>> = ({ rpcEndpoint }) => {
  const [tmClient, setTmClient] = useState<Tendermint34Client>()

  useEffect(() => {
    ;(async () => {
      if (rpcEndpoint) {
        const client = await Tendermint34Client.connect(rpcEndpoint)
        setTmClient(client)
      }
    })()
  }, [rpcEndpoint])

  if (!tmClient) return (<div>'connecting...'<div>)

  return (
    <TendermintProvider value={{ client: tmClient }}>
      {children}
    </TendermintProvider>
  )
}

export default useTendermintClient
pyramation commented 2 years ago

putting @adairrr 's gist here https://gist.github.com/adairrr/d300102ddab76a21aa0fd5329ac1fa01

pyramation commented 2 years ago

For the RPC endpoint and client we could also just use normal React Contexts

Yea that's probably more portable and better for the developer anyway. Good call!