From a21e6f19a93b39920438c4e660dc8274672c6c5b Mon Sep 17 00:00:00 2001 From: Pedro Rezende Date: Fri, 7 Jun 2024 18:01:54 +0200 Subject: [PATCH] Namadillo: preferring user selected RPC url and improving queries (#859) * feat(namadillo): using user selected rpc intead of .env constant * feat(namadillo): refactoring and avoiding duplicate queries * refactor(namadillo): adding a version property instead of using localStorage key * feat(namadillo): updating reference for native token in accounts --- apps/namadillo/src/App/App.tsx | 2 -- .../src/App/Staking/StakingOverview.tsx | 9 --------- apps/namadillo/src/hooks/useOnChainChanged.ts | 18 ------------------ apps/namadillo/src/hooks/useSdk.tsx | 13 ++++++------- apps/namadillo/src/slices/accounts/atoms.ts | 8 ++------ apps/namadillo/src/slices/fees.ts | 14 +++----------- apps/namadillo/src/slices/settings.ts | 13 ++++++++++++- apps/namadillo/src/slices/validators.ts | 10 +++++----- 8 files changed, 28 insertions(+), 59 deletions(-) delete mode 100644 apps/namadillo/src/hooks/useOnChainChanged.ts diff --git a/apps/namadillo/src/App/App.tsx b/apps/namadillo/src/App/App.tsx index 0b3b88ddd..95a8e8cb1 100644 --- a/apps/namadillo/src/App/App.tsx +++ b/apps/namadillo/src/App/App.tsx @@ -5,7 +5,6 @@ import { TopNavigation } from "App/Common/TopNavigation"; import { AnimatePresence } from "framer-motion"; import { createBrowserHistory } from "history"; import { useSmallScreen } from "hooks/useIsSmallScren"; -import { useOnChainChanged } from "hooks/useOnChainChanged"; import { useOnNamadaExtensionAttached } from "hooks/useOnNamadaExtensionAttached"; import { useTransactionCallback } from "hooks/useTransactionCallbacks"; import { useTransactionNotifications } from "hooks/useTransactionNotifications"; @@ -19,7 +18,6 @@ export const history = createBrowserHistory({ window }); export function App(): JSX.Element { useOnNamadaExtensionAttached(); - useOnChainChanged(); useTransactionNotifications(); useTransactionCallback(); diff --git a/apps/namadillo/src/App/Staking/StakingOverview.tsx b/apps/namadillo/src/App/Staking/StakingOverview.tsx index 205cefb5d..b7a9b835a 100644 --- a/apps/namadillo/src/App/Staking/StakingOverview.tsx +++ b/apps/namadillo/src/App/Staking/StakingOverview.tsx @@ -4,8 +4,6 @@ import { PageWithSidebar } from "App/Common/PageWithSidebar"; import { ValidatorDiversification } from "App/Sidebars/ValidatorDiversification"; import { YourStakingDistribution } from "App/Sidebars/YourStakingDistribution"; import { useAtomValue } from "jotai"; -import { useEffect } from "react"; -import { defaultAccountAtom } from "slices/accounts"; import { namadaExtensionConnectedAtom } from "slices/settings"; import { myValidatorsAtom, @@ -25,7 +23,6 @@ import { UnbondingAmountsTable } from "./UnbondingAmountsTable"; // * user can also navigate to sibling view for validator details export const StakingOverview = (): JSX.Element => { const isConnected = useAtomValue(namadaExtensionConnectedAtom); - const { data: account } = useAtomValue(defaultAccountAtom); const myValidators = useAtomValue(myValidatorsAtom); const unbondedAmounts = useAtomValue(unbondedAmountByAddressAtom); const stakedByAddress = useAtomValue(stakedAmountByAddressAtom); @@ -34,12 +31,6 @@ export const StakingOverview = (): JSX.Element => { const hasUnbonded = unbondedAmounts.isSuccess && Object.keys(unbondedAmounts.data).length > 0; - useEffect(() => { - if (isConnected && account) { - myValidators.refetch(); - } - }, [isConnected, account]); - return (
diff --git a/apps/namadillo/src/hooks/useOnChainChanged.ts b/apps/namadillo/src/hooks/useOnChainChanged.ts deleted file mode 100644 index 50d4c1840..000000000 --- a/apps/namadillo/src/hooks/useOnChainChanged.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { useEffectSkipFirstRender } from "@namada/hooks"; -import { useAtomValue } from "jotai"; -import { accountBalanceAtom, defaultAccountAtom } from "slices/accounts"; -import { chainAtom } from "slices/chain"; -import { minimumGasPriceAtom } from "slices/fees"; - -export const useOnChainChanged = (): void => { - const chain = useAtomValue(chainAtom); - const balances = useAtomValue(accountBalanceAtom); - const accounts = useAtomValue(defaultAccountAtom); - const gasPrice = useAtomValue(minimumGasPriceAtom); - - useEffectSkipFirstRender(() => { - balances.refetch(); - accounts.refetch(); - gasPrice.refetch(); - }, [chain]); -}; diff --git a/apps/namadillo/src/hooks/useSdk.tsx b/apps/namadillo/src/hooks/useSdk.tsx index f4c3d9146..3641306e2 100644 --- a/apps/namadillo/src/hooks/useSdk.tsx +++ b/apps/namadillo/src/hooks/useSdk.tsx @@ -1,18 +1,17 @@ import initSdk from "@heliax/namada-sdk/inline-init"; import { Sdk, getSdk } from "@heliax/namada-sdk/web"; +import { createStore } from "jotai"; import { createContext, useContext, useEffect, useState } from "react"; - -const { - NAMADA_INTERFACE_NAMADA_URL: rpcUrl = "http://localhost:27657", - NAMADA_INTERFACE_NAMADA_TOKEN: - token = "tnam1qxgfw7myv4dh0qna4hq0xdg6lx77fzl7dcem8h7e", -} = process.env; +import { nativeTokenAtom, rpcUrlAtom } from "slices/settings"; export const SdkContext = createContext(null); const initializeSdk = async (): Promise => { const { cryptoMemory } = await initSdk(); - const sdk = getSdk(cryptoMemory, rpcUrl, "", token); + const store = createStore(); + const rpcUrl = store.get(rpcUrlAtom); + const nativeToken = store.get(nativeTokenAtom); + const sdk = getSdk(cryptoMemory, rpcUrl, "", nativeToken); return sdk; }; diff --git a/apps/namadillo/src/slices/accounts/atoms.ts b/apps/namadillo/src/slices/accounts/atoms.ts index 79750a87e..486fe4b7e 100644 --- a/apps/namadillo/src/slices/accounts/atoms.ts +++ b/apps/namadillo/src/slices/accounts/atoms.ts @@ -2,18 +2,13 @@ import { Account } from "@namada/types"; import BigNumber from "bignumber.js"; import { atomWithQuery } from "jotai-tanstack-query"; import { shouldUpdateBalanceAtom } from "slices/etc"; -import { namadaExtensionConnectedAtom } from "slices/settings"; +import { namadaExtensionConnectedAtom, nativeTokenAtom } from "slices/settings"; import { fetchAccountBalance, fetchAccounts, fetchDefaultAccount, } from "./services"; -const { - NAMADA_INTERFACE_NAMADA_TOKEN: - tokenAddress = "tnam1qxgfw7myv4dh0qna4hq0xdg6lx77fzl7dcem8h7e", -} = process.env; - export const accountsAtom = atomWithQuery((get) => { const isExtensionConnected = get(namadaExtensionConnectedAtom); return { @@ -34,6 +29,7 @@ export const defaultAccountAtom = atomWithQuery((get) => { export const accountBalanceAtom = atomWithQuery((get) => { const defaultAccount = get(defaultAccountAtom); + const tokenAddress = get(nativeTokenAtom); const enablePolling = get(shouldUpdateBalanceAtom); return { enabled: !!tokenAddress && defaultAccount.isSuccess, diff --git a/apps/namadillo/src/slices/fees.ts b/apps/namadillo/src/slices/fees.ts index ae58cc715..a614cdeeb 100644 --- a/apps/namadillo/src/slices/fees.ts +++ b/apps/namadillo/src/slices/fees.ts @@ -2,24 +2,17 @@ import BigNumber from "bignumber.js"; import { getSdkInstance } from "hooks"; import invariant from "invariant"; import { atomWithQuery } from "jotai-tanstack-query"; -import { chainAtom } from "slices/chain"; +import { nativeTokenAtom } from "./settings"; // TODO: remove harcoding of gas limit export const GAS_LIMIT = new BigNumber(20_000); -const { - NAMADA_INTERFACE_NAMADA_TOKEN: - nativeToken = "tnam1qxgfw7myv4dh0qna4hq0xdg6lx77fzl7dcem8h7e", -} = process.env; - export const minimumGasPriceAtom = atomWithQuery((get) => { - const chain = get(chainAtom); + const nativeToken = get(nativeTokenAtom); return { - queryKey: ["minimum-gas-price-" + chain.chainId], + queryKey: ["minimum-gas-price", nativeToken], queryFn: async () => { const { rpc } = await getSdkInstance(); - // TODO: Can nativeToken ever be undefined? - invariant(!!nativeToken, "Native token is undefined"); const result = await rpc.queryGasCosts(); const nativeTokenCost = result.find(([token]) => token === nativeToken); invariant(!!nativeTokenCost, "Error querying minimum gas price"); @@ -28,7 +21,6 @@ export const minimumGasPriceAtom = atomWithQuery((get) => { !asBigNumber.isNaN(), "Error converting minimum gas price to BigNumber" ); - return asBigNumber; }, }; diff --git a/apps/namadillo/src/slices/settings.ts b/apps/namadillo/src/slices/settings.ts index 7df9de4c1..ad7d10603 100644 --- a/apps/namadillo/src/slices/settings.ts +++ b/apps/namadillo/src/slices/settings.ts @@ -3,10 +3,12 @@ import { Getter, Setter, atom } from "jotai"; import { atomWithStorage } from "jotai/utils"; type SettingsStorage = { + version: string; fiat: CurrencyType; hideBalances: boolean; rpcUrl: string; chainId: string; + nativeToken: string; signArbitraryEnabled: boolean; }; @@ -20,12 +22,16 @@ export const namadaExtensionConnectedAtom = atom( export const namadilloSettingsAtom = atomWithStorage( "namadillo:settings", { + version: "0.1", fiat: "usd", hideBalances: false, rpcUrl: process.env.NAMADA_INTERFACE_NAMADA_URL || "", chainId: process.env.NAMADA_INTERFACE_NAMADA_CHAIN_ID || "", + nativeToken: process.env.NAMADA_INTERFACE_NAMADA_TOKEN || "", signArbitraryEnabled: false, - } + }, + undefined, + { getOnInit: true } ); const changeSettings = @@ -55,6 +61,11 @@ export const chainIdAtom = atom( changeSettings("chainId") ); +export const nativeTokenAtom = atom( + (get) => get(namadilloSettingsAtom).nativeToken, + changeSettings("nativeToken") +); + export const signArbitraryEnabledAtom = atom( (get) => get(namadilloSettingsAtom).signArbitraryEnabled, changeSettings("signArbitraryEnabled") diff --git a/apps/namadillo/src/slices/validators.ts b/apps/namadillo/src/slices/validators.ts index a7b27ab5f..eafa70db0 100644 --- a/apps/namadillo/src/slices/validators.ts +++ b/apps/namadillo/src/slices/validators.ts @@ -6,8 +6,8 @@ import { atomWithQuery, } from "jotai-tanstack-query"; import { defaultAccountAtom } from "slices/accounts"; -import { chainAtom } from "./chain"; import { shouldUpdateBalanceAtom } from "./etc"; +import { rpcUrlAtom } from "./settings"; type Unique = { uuid: string; @@ -52,8 +52,8 @@ const toValidator = (address: string): Validator => ({ export const allValidatorsAtom = atomWithQuery((get) => ({ queryKey: ["all-validators"], queryFn: async () => { - const { rpc } = get(chainAtom); - const query = new Query(rpc); + const rpcUrl = get(rpcUrlAtom); + const query = new Query(rpcUrl); const queryResult = (await query.query_all_validator_addresses()) as string[]; return queryResult.map(toValidator); @@ -72,8 +72,8 @@ export const myValidatorsAtom = atomWithQuery((get) => { enabled: account.isSuccess, refetchInterval: enablePolling ? 1000 : false, queryFn: async (): Promise => { - const { rpc } = get(chainAtom); - const query = new Query(rpc); + const rpcUrl = get(rpcUrlAtom); + const query = new Query(rpcUrl); const myValidatorsRes = await query.query_my_validators([ account.data?.address, ]);