From 7f5156e08173886fa1493d7d76db779adf96d2b3 Mon Sep 17 00:00:00 2001 From: sim Date: Thu, 20 Jan 2022 19:01:54 +0900 Subject: [PATCH] BREAKING CHANGE: Deprecate tax --- src/data/queries/treasury.ts | 50 ------------- src/data/query.ts | 1 - src/pages/dashboard/Dashboard.module.scss | 8 +-- src/pages/dashboard/Dashboard.tsx | 2 - src/pages/dashboard/TaxRate.tsx | 42 ----------- src/txs/Tx.tsx | 86 +++-------------------- src/txs/swap/MultipleSwapContext.tsx | 26 +------ src/txs/swap/SwapForm.tsx | 1 - src/txs/swap/SwapMultipleForm.tsx | 31 +++----- src/txs/utils.ts | 32 --------- src/txs/wasm/ExecuteContractForm.tsx | 7 +- src/txs/wasm/ExecuteContractTx.tsx | 5 +- src/txs/wasm/InstantiateContractForm.tsx | 7 +- src/txs/wasm/InstantiateContractTx.tsx | 5 +- src/txs/wasm/TaxParams.tsx | 37 ---------- 15 files changed, 27 insertions(+), 313 deletions(-) delete mode 100644 src/data/queries/treasury.ts delete mode 100644 src/pages/dashboard/TaxRate.tsx delete mode 100644 src/txs/wasm/TaxParams.tsx diff --git a/src/data/queries/treasury.ts b/src/data/queries/treasury.ts deleted file mode 100644 index 1faa26663..000000000 --- a/src/data/queries/treasury.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { useQueries, useQuery } from "react-query" -import { isDenom, isDenomLuna } from "@terra.kitchen/utils" -import { queryKey, RefetchOptions } from "../query" -import { useLCDClient } from "./lcdClient" - -export const useTaxRate = (disabled = false) => { - const lcd = useLCDClient() - return useQuery( - [queryKey.treasury.taxRate], - async () => { - const taxRate = await lcd.treasury.taxRate() - return taxRate.toString() - }, - { ...RefetchOptions.INFINITY, enabled: !disabled } - ) -} - -const useGetQueryTaxCap = (disabled = false) => { - const lcd = useLCDClient() - - return (denom?: Denom) => ({ - queryKey: [queryKey.treasury.taxCap, denom], - queryFn: async () => { - if (!denom || !getShouldTax(denom)) return "0" - - try { - const taxCap = await lcd.treasury.taxCap(denom) - return taxCap.amount.toString() - } catch { - return String(1e6) - } - }, - ...RefetchOptions.INFINITY, - enabled: isDenom(denom) && !disabled, - }) -} - -export const useTaxCap = (denom?: Denom) => { - const getQueryTaxCap = useGetQueryTaxCap() - return useQuery(getQueryTaxCap(denom)) -} - -export const useTaxCaps = (denoms: Denom[], disabled = false) => { - const getQueryTaxCap = useGetQueryTaxCap(disabled) - return useQueries(denoms.map(getQueryTaxCap)) -} - -/* utils */ -export const getShouldTax = (token?: Token) => - isDenom(token) && !isDenomLuna(token) diff --git a/src/data/query.ts b/src/data/query.ts index 1d6b76d49..98935b962 100644 --- a/src/data/query.ts +++ b/src/data/query.ts @@ -67,7 +67,6 @@ export const queryKey = mirror({ unbondings: "", pool: "", }, - treasury: { taxRate: "", taxCap: "" }, tx: { txInfo: "", create: "" }, wasm: { contractInfo: "", contractQuery: "" }, diff --git a/src/pages/dashboard/Dashboard.module.scss b/src/pages/dashboard/Dashboard.module.scss index 5210b25b5..ee9616221 100644 --- a/src/pages/dashboard/Dashboard.module.scss +++ b/src/pages/dashboard/Dashboard.module.scss @@ -5,17 +5,13 @@ gap: var(--grid-gap); @include desktop { - grid-template-columns: repeat(5, 1fr); + grid-template-columns: repeat(4, 1fr); } } @media (min-width: $breakpoint) and (max-width: (1400px - 0.02)) { .header { grid-template-columns: repeat(2, 1fr); - grid-template-rows: auto repeat(2, 1fr); - } - - .price { - grid-column: 1 / span 2; + grid-template-rows: repeat(2, 1fr); } } diff --git a/src/pages/dashboard/Dashboard.tsx b/src/pages/dashboard/Dashboard.tsx index 2f7263a8e..7a1008e52 100644 --- a/src/pages/dashboard/Dashboard.tsx +++ b/src/pages/dashboard/Dashboard.tsx @@ -1,7 +1,6 @@ import { useTranslation } from "react-i18next" import { Col, Page } from "components/layout" import LunaPrice from "./LunaPrice" -import TaxRate from "./TaxRate" import Issuance from "./Issuance" import CommunityPool from "./CommunityPool" import StakingRatio from "./StakingRatio" @@ -16,7 +15,6 @@ const Dashboard = () => {
- diff --git a/src/pages/dashboard/TaxRate.tsx b/src/pages/dashboard/TaxRate.tsx deleted file mode 100644 index 9ccc08b10..000000000 --- a/src/pages/dashboard/TaxRate.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import { useTranslation } from "react-i18next" -import { useTaxRate } from "data/queries/treasury" -import { Card } from "components/layout" -import { ReadPercent } from "components/token" -import { TooltipIcon } from "components/display" -import DashboardContent from "./components/DashboardContent" -import DashboardTag from "./components/DashboardTag" - -const TaxRate = () => { - const { t } = useTranslation() - const { data: taxRate, ...state } = useTaxRate() - - const render = () => { - if (!taxRate) return null - return ( - {taxRate}} - footer={{t("Capped at 1 SDT")}} - /> - ) - } - - return ( - - {t("Tax rate")} - - } - size="small" - > - {render()} - - ) -} - -export default TaxRate diff --git a/src/txs/Tx.tsx b/src/txs/Tx.tsx index 347ac114b..561b08f67 100644 --- a/src/txs/Tx.tsx +++ b/src/txs/Tx.tsx @@ -24,11 +24,10 @@ import { has } from "utils/num" import { getAmount, sortCoins } from "utils/coin" import { getErrorMessage } from "utils/error" import { useCurrency } from "data/settings/Currency" -import { queryKey, combineState, RefetchOptions } from "data/query" +import { queryKey, RefetchOptions } from "data/query" import { useAddress, useNetwork } from "data/wallet" import { isBroadcastingState, latestTxState } from "data/queries/tx" import { useBankBalance, useIsWalletEmpty } from "data/queries/bank" -import { getShouldTax, useTaxCap, useTaxRate } from "data/queries/treasury" import { Pre } from "components/general" import { Flex, Grid } from "components/layout" @@ -57,8 +56,6 @@ interface Props { estimationTxValues?: TxValues createTx: (values: TxValues) => CreateTxOptions | undefined gasAdjustment?: number - preventTax?: boolean - taxes?: Coins excludeGasDenom?: (denom: string) => boolean /* render */ @@ -83,7 +80,7 @@ function Tx(props: Props) { const { token, decimals, amount, balance } = props const { initialGasDenom, estimationTxValues, createTx } = props const { gasAdjustment = DEFAULT_GAS_ADJUSTMENT } = props - const { preventTax, excludeGasDenom } = props + const { excludeGasDenom } = props const { children, onChangeMax } = props const { onPost, redirectAfterTx, queryKeys } = props @@ -104,12 +101,6 @@ function Tx(props: Props) { const bankBalance = useBankBalance() const { gasPrices } = useTx() - /* queries: conditional */ - const shouldTax = !preventTax && getShouldTax(token) - const { data: rate = "0", ...taxRateState } = useTaxRate(!shouldTax) - const { data: cap = "0", ...taxCapState } = useTaxCap(token) - const taxState = combineState(taxRateState, taxCapState) - /* simulation: estimate gas */ const simulationTx = estimationTxValues && createTx(estimationTxValues) const key = { @@ -173,7 +164,7 @@ function Tx(props: Props) { const getNativeMax = () => { if (!balance) return const gasAmount = gasFee.denom === initialGasDenom ? gasFee.amount : "0" - return calcMax({ balance, rate, cap, gasAmount }).max + return calcMax({ balance, gasAmount }) } const max = !gasFee.amount @@ -187,14 +178,8 @@ function Tx(props: Props) { if (max && isMax && onChangeMax) onChangeMax(toInput(max, decimals)) }, [decimals, isMax, max, onChangeMax]) - /* tax */ - const taxAmount = - token && amount && shouldTax - ? calcMinimumTaxAmount(amount, { rate, cap }) - : undefined - /* (effect): Log error on console */ - const failed = getErrorMessage(taxState.error ?? estimatedGasState.error) + const failed = getErrorMessage(estimatedGasState.error) useEffect(() => { if (process.env.NODE_ENV === "development" && failed) { console.groupCollapsed("Fee estimation failed") @@ -212,10 +197,6 @@ function Tx(props: Props) { const disabled = passwordRequired && !password ? t("Enter password") - : taxState.isLoading - ? t("Loading tax data...") - : taxState.error - ? t("Failed to load tax data") : estimatedGasState.isLoading ? t("Estimating fee...") : estimatedGasState.error @@ -242,10 +223,7 @@ function Tx(props: Props) { if (!tx) throw new Error("Tx is not defined") const gasCoins = new Coins([Coin.fromData(gasFee)]) - const taxCoin = token && taxAmount && new Coin(token, taxAmount) - const taxCoins = props.taxes ?? taxCoin - const feeCoins = taxCoins ? gasCoins.add(taxCoins) : gasCoins - const fee = new Fee(estimatedGas, feeCoins) + const fee = new Fee(estimatedGas, gasCoins) if (isWallet.multisig(wallet)) { const unsignedTx = await auth.create({ ...tx, fee }) @@ -275,7 +253,6 @@ function Tx(props: Props) { amount && new BigNumber(balance) .minus(amount) - .minus(taxAmount ?? 0) .minus((gasFee.denom === token && gasFee.amount) || 0) .toString() @@ -324,10 +301,6 @@ function Tx(props: Props) { const renderFee = (descriptions?: Contents) => { if (!estimatedGas) return null - const taxes = sortCoins(props.taxes ?? new Coins(), currency).filter( - ({ amount }) => has(amount) - ) - return (
@@ -338,28 +311,6 @@ function Tx(props: Props) { ))} - {has(taxAmount) && ( - <> -
{t("Tax")}
-
- -
- - )} - - {!!taxes.length && ( - <> -
{t("Tax")}
-
- {taxes.map((coin) => ( -

- -

- ))} -
- - )} -
{t("Gas")} {availableGasDenoms.length > 1 && ( @@ -503,37 +454,18 @@ export const getInitialGasDenom = (bankBalance: Coins, token?: Token) => { interface Params { balance: Amount - rate: string - cap: Amount gasAmount: Amount } -// Receive tax and gas information and return the maximum payment amount -export const calcMax = ({ balance, rate, cap, gasAmount }: Params) => { +// Receive gas and return the maximum payment amount +export const calcMax = ({ balance, gasAmount }: Params) => { const available = new BigNumber(balance).minus(gasAmount) - const tax = calcMinimumTaxAmount(available, { - rate: new BigNumber(rate).div(new BigNumber(1).plus(rate)), - cap, - }) - - const max = BigNumber.max(new BigNumber(available).minus(tax ?? 0), 0) + const max = BigNumber.max(new BigNumber(available), 0) .integerValue(BigNumber.ROUND_FLOOR) .toString() - return { max, tax } -} - -export const calcMinimumTaxAmount = ( - amount: BigNumber.Value, - { rate, cap }: { rate: BigNumber.Value; cap: BigNumber.Value } -) => { - const tax = BigNumber.min( - new BigNumber(amount).times(rate), - cap - ).integerValue(BigNumber.ROUND_FLOOR) - - return tax.gt(0) ? tax.toString() : undefined + return max } /* hooks */ diff --git a/src/txs/swap/MultipleSwapContext.tsx b/src/txs/swap/MultipleSwapContext.tsx index 50b16a65b..535c5aa91 100644 --- a/src/txs/swap/MultipleSwapContext.tsx +++ b/src/txs/swap/MultipleSwapContext.tsx @@ -1,20 +1,15 @@ import { FC, useMemo } from "react" import { useTranslation } from "react-i18next" -import { zipObj } from "ramda" import { isDenomTerraNative } from "@terra.kitchen/utils" import { getAmount, sortCoins } from "utils/coin" import createContext from "utils/createContext" import { useCurrency } from "data/settings/Currency" -import { combineState } from "data/query" import { useBankBalance, useTerraNativeLength } from "data/queries/bank" -import { useTaxCaps, useTaxRate } from "data/queries/treasury" import { readNativeDenom } from "data/token" import { Card } from "components/layout" import { Wrong } from "components/feedback" interface MultipleSwap { - taxRate: string - taxCaps: Record available: TokenItemWithBalance[] } @@ -31,19 +26,6 @@ const MultipleSwapContext: FC = ({ children }) => { .map(({ denom }) => denom) .filter(isDenomTerraNative) - /* treasury */ - const { data: taxRate, ...taxRateState } = useTaxRate() - const taxCapsState = useTaxCaps(denoms) - const taxCaps = taxCapsState.every(({ isSuccess }) => isSuccess) - ? zipObj( - denoms, - taxCapsState.map(({ data }) => { - if (!data) throw new Error() - return data - }) - ) - : undefined - const available = useMemo(() => { return denoms.map((denom) => { const balance = getAmount(bankBalance, denom) @@ -51,22 +33,20 @@ const MultipleSwapContext: FC = ({ children }) => { }) }, [bankBalance, denoms]) - const state = combineState(taxRateState, ...taxCapsState) - const render = () => { if (length < 2) return {t("Multiple swap requires at least 2 coins")} - if (!(taxRate && taxCaps && available)) return null + if (!available) return null return ( - + {children} ) } - return {render()} + return {render()} } export default MultipleSwapContext diff --git a/src/txs/swap/SwapForm.tsx b/src/txs/swap/SwapForm.tsx index 7db4c733e..08d48722d 100644 --- a/src/txs/swap/SwapForm.tsx +++ b/src/txs/swap/SwapForm.tsx @@ -230,7 +230,6 @@ const SwapForm = () => { initialGasDenom, estimationTxValues, createTx, - preventTax: mode === SwapMode.ONCHAIN, onPost: () => { // add custom token on ask cw20 if (!(askAsset && AccAddress.validate(askAsset) && askTokenItem)) return diff --git a/src/txs/swap/SwapMultipleForm.tsx b/src/txs/swap/SwapMultipleForm.tsx index 1930b68b1..6026c5bc5 100644 --- a/src/txs/swap/SwapMultipleForm.tsx +++ b/src/txs/swap/SwapMultipleForm.tsx @@ -4,7 +4,6 @@ import { useQuery } from "react-query" import { useForm } from "react-hook-form" import BigNumber from "bignumber.js" import { flatten, fromPairs } from "ramda" -import { Coin, Coins } from "@terra-money/terra.js" /* helpers */ import { has } from "utils/num" @@ -36,7 +35,7 @@ interface TxValues { // available > simulatable > simulated > selectable > offers // available: all assets -// simulatable: non-askAsset, balance exists except tax. +// simulatable: non-askAsset, balance. // selectable: simulated result value exists // offers: selected by the user const SwapMultipleForm = () => { @@ -47,7 +46,7 @@ const SwapMultipleForm = () => { const utils = useSwapUtils() const { getSwapMode, getSimulateFunction, getMsgsFunction } = utils const { activeDenoms } = useSwap() - const { taxRate, taxCaps, available } = useMultipleSwap() + const { available } = useMultipleSwap() const initialGasDenom = "uluna" /* options: askAsset */ @@ -75,14 +74,12 @@ const SwapMultipleForm = () => { .map((item) => { const { token: offerAsset, balance } = item const mode = getSwapMode({ offerAsset, askAsset }) - if (mode === SwapMode.ONCHAIN) - return { ...item, max: balance, tax: "0" } - const cap = taxCaps[offerAsset] - const max = calcMax({ balance, rate: taxRate, cap, gasAmount: "0" }) - return { ...item, ...max } + if (mode === SwapMode.ONCHAIN) return { ...item, max: balance } + const max = calcMax({ balance, gasAmount: "0" }) + return { ...item, max } }) .filter(({ token, max }) => token !== askAsset && has(max)), - [askAsset, available, getSwapMode, taxCaps, taxRate] + [askAsset, available, getSwapMode] ) /* simulate */ @@ -90,16 +87,16 @@ const SwapMultipleForm = () => { ["simulate.swap.multiple", simulatable, askAsset], async () => { const simulated = await Promise.allSettled( - simulatable.map(async ({ token: offerAsset, max: amount, tax }) => { + simulatable.map(async ({ token: offerAsset, max: amount }) => { const mode = getSwapMode({ offerAsset, askAsset }) try { const params = { amount, offerAsset, askAsset } const { value } = await getSimulateFunction(mode)(params) - return { offerAsset, mode, amount, tax, value } + return { offerAsset, mode, amount, value } } catch (error) { // errors because too small amount is simulated - return { offerAsset, mode, amount, tax, value: "0" } + return { offerAsset, mode, amount, value: "0" } } }) ) @@ -149,22 +146,12 @@ const SwapMultipleForm = () => { /* fee */ const estimationTxValues = useMemo(() => ({ askAsset }), [askAsset]) - const taxes = new Coins( - offers - .filter(({ tax }) => has(tax)) - .map(({ offerAsset, tax }) => { - if (!tax) throw new Error() - return new Coin(offerAsset, tax) - }) - ) - const excludeGasDenom = useCallback((denom) => !!state[denom], [state]) const tx = { initialGasDenom, estimationTxValues, createTx, - taxes, excludeGasDenom, onSuccess: { label: t("Wallet"), path: "/wallet" }, } diff --git a/src/txs/utils.ts b/src/txs/utils.ts index 50bc78430..f0afdce57 100644 --- a/src/txs/utils.ts +++ b/src/txs/utils.ts @@ -2,8 +2,6 @@ import BigNumber from "bignumber.js" import { readAmount, toAmount } from "@terra.kitchen/utils" import { Coin, Coins } from "@terra-money/terra.js" import { has } from "utils/num" -import { getShouldTax } from "data/queries/treasury" -import { calcMinimumTaxAmount } from "./Tx" export const getPlaceholder = (decimals = 6) => "0.".padEnd(decimals + 2, "0") @@ -24,33 +22,3 @@ export const getCoins = (coins: CoinInput[]) => { .map(({ amount, denom }) => new Coin(denom, amount)) ) } - -export interface TaxParams { - taxRate: string - taxCaps: Record -} - -export const calcTaxes = ( - coins: CoinInput[], - { taxRate, taxCaps }: TaxParams -) => { - if (!new BigNumber(taxRate).gt(0)) return - - return new Coins( - coins - .filter(({ input, denom }) => { - const amount = toAmount(input) - return has(amount) && getShouldTax(denom) - }) - .map(({ input, denom }) => { - const amount = toAmount(input) - const tax = calcMinimumTaxAmount(amount, { - rate: taxRate, - cap: taxCaps[denom], - }) - - if (!tax) throw new Error() - return new Coin(denom, tax) - }) - ) -} diff --git a/src/txs/wasm/ExecuteContractForm.tsx b/src/txs/wasm/ExecuteContractForm.tsx index e8eaa8947..71bb5a88d 100644 --- a/src/txs/wasm/ExecuteContractForm.tsx +++ b/src/txs/wasm/ExecuteContractForm.tsx @@ -13,10 +13,9 @@ import { useAddress } from "data/wallet" import { useBankBalance } from "data/queries/bank" import { Form, FormGroup, FormItem } from "components/form" import { Input, Select, TextArea } from "components/form" -import { calcTaxes, getCoins, getPlaceholder } from "../utils" +import { getCoins, getPlaceholder } from "../utils" import validate from "../validate" import Tx, { getInitialGasDenom } from "../Tx" -import { useTaxParams } from "./TaxParams" interface TxValues { msg: string @@ -33,7 +32,6 @@ const ExecuteContractForm = () => { const bankBalance = useBankBalance() /* tx context */ - const taxParams = useTaxParams() const initialGasDenom = getInitialGasDenom(bankBalance) const defaultItem = { denom: initialGasDenom } @@ -46,7 +44,6 @@ const ExecuteContractForm = () => { const { register, control, watch, handleSubmit, formState } = form const { errors } = formState const values = watch() - const { coins } = values const { fields, append, remove } = useFieldArray({ control, name: "coins" }) /* tx */ @@ -67,11 +64,9 @@ const ExecuteContractForm = () => { /* fee */ const estimationTxValues = useMemo(() => values, [values]) - const taxes = calcTaxes(coins, taxParams) const tx = { initialGasDenom, estimationTxValues, - taxes, createTx, onSuccess: { label: t("Contract"), path: "/contract" }, queryKeys: [ diff --git a/src/txs/wasm/ExecuteContractTx.tsx b/src/txs/wasm/ExecuteContractTx.tsx index e22be8085..1176d5a77 100644 --- a/src/txs/wasm/ExecuteContractTx.tsx +++ b/src/txs/wasm/ExecuteContractTx.tsx @@ -1,7 +1,6 @@ import { useTranslation } from "react-i18next" import { Page, Card } from "components/layout" import TxContext from "../TxContext" -import TaxParamsContext from "./TaxParams" import ExecuteContractForm from "./ExecuteContractForm" const ExecuteContractTx = () => { @@ -11,9 +10,7 @@ const ExecuteContractTx = () => { - - - + diff --git a/src/txs/wasm/InstantiateContractForm.tsx b/src/txs/wasm/InstantiateContractForm.tsx index 60d961043..44bb70770 100644 --- a/src/txs/wasm/InstantiateContractForm.tsx +++ b/src/txs/wasm/InstantiateContractForm.tsx @@ -13,10 +13,9 @@ import { useAddress } from "data/wallet" import { useBankBalance } from "data/queries/bank" import { Form, FormGroup, FormItem } from "components/form" import { Input, EditorInput, Select } from "components/form" -import { calcTaxes, getCoins, getPlaceholder } from "../utils" +import { getCoins, getPlaceholder } from "../utils" import validate from "../validate" import Tx, { getInitialGasDenom } from "../Tx" -import { useTaxParams } from "./TaxParams" interface TxValues { admin?: AccAddress @@ -31,7 +30,6 @@ const InstantiateContractForm = () => { const bankBalance = useBankBalance() /* tx context */ - const taxParams = useTaxParams() const initialGasDenom = getInitialGasDenom(bankBalance) const defaultItem = { denom: initialGasDenom } @@ -44,7 +42,6 @@ const InstantiateContractForm = () => { const { register, control, watch, handleSubmit, formState } = form const { errors } = formState const values = watch() - const { coins } = values const { fields, append, remove } = useFieldArray({ control, name: "coins" }) /* tx */ @@ -66,12 +63,10 @@ const InstantiateContractForm = () => { /* fee */ const estimationTxValues = useMemo(() => values, [values]) - const taxes = calcTaxes(coins, taxParams) const tx = { initialGasDenom, estimationTxValues, - taxes, createTx, onSuccess: { label: t("Contract"), path: "/contract" }, } diff --git a/src/txs/wasm/InstantiateContractTx.tsx b/src/txs/wasm/InstantiateContractTx.tsx index a0ac17a74..90675443c 100644 --- a/src/txs/wasm/InstantiateContractTx.tsx +++ b/src/txs/wasm/InstantiateContractTx.tsx @@ -1,7 +1,6 @@ import { useTranslation } from "react-i18next" import { Page, Card } from "components/layout" import TxContext from "../TxContext" -import TaxParamsContext from "./TaxParams" import InstantiateContractForm from "./InstantiateContractForm" const InstantiateContractTx = () => { @@ -11,9 +10,7 @@ const InstantiateContractTx = () => { - - - + diff --git a/src/txs/wasm/TaxParams.tsx b/src/txs/wasm/TaxParams.tsx deleted file mode 100644 index 7382d0774..000000000 --- a/src/txs/wasm/TaxParams.tsx +++ /dev/null @@ -1,37 +0,0 @@ -import { FC } from "react" -import { zipObj } from "ramda" -import createContext from "utils/createContext" -import { combineState } from "data/query" -import { useBankBalance } from "data/queries/bank" -import { useTaxCaps, useTaxRate } from "data/queries/treasury" -import { TaxParams } from "../utils" - -export const [useTaxParams, TaxParamsProvider] = - createContext("useTaxParams") - -const TaxParamsContext: FC = ({ children }) => { - const bankBalance = useBankBalance() - - const denoms = bankBalance.toArray().map(({ denom }) => denom) ?? [] - const { data: taxRate, ...taxRateState } = useTaxRate() - const taxCapsState = useTaxCaps(denoms) - const state = combineState(taxRateState, ...taxCapsState) - - if (!state.isSuccess || !taxRate) return null - - const taxCaps = zipObj( - denoms, - taxCapsState.map(({ data }) => { - if (!data) throw new Error() - return data - }) - ) - - return ( - - {children} - - ) -} - -export default TaxParamsContext