diff --git a/src/transaction-flow/input/BulkRenewal/BulkRenewal-flow.tsx b/src/transaction-flow/input/BulkRenewal/BulkRenewal-flow.tsx
index e708353ac..e330142ad 100644
--- a/src/transaction-flow/input/BulkRenewal/BulkRenewal-flow.tsx
+++ b/src/transaction-flow/input/BulkRenewal/BulkRenewal-flow.tsx
@@ -1,18 +1,21 @@
import { useState } from 'react'
import { useTranslation } from 'react-i18next'
import styled, { css } from 'styled-components'
-import { useClient, useReadContract } from 'wagmi'
+import { useAccount, useBalance, useClient, useEstimateGas, useReadContract } from 'wagmi'
import { NameWithRelation } from '@ensdomains/ensjs/subgraph'
import { Dialog, Heading, Helper, OutlinkSVG, Typography } from '@ensdomains/thorin'
+import { CacheableComponent } from '@app/components/@atoms/CacheableComponent'
import { Calendar } from '@app/components/@atoms/Calendar/Calendar'
-import { InvoiceItem } from '@app/components/@atoms/Invoice/Invoice'
+import { Invoice, InvoiceItem } from '@app/components/@atoms/Invoice/Invoice'
import { PlusMinusControl } from '@app/components/@atoms/PlusMinusControl/PlusMinusControl'
import { EligibleForTokens } from '@app/components/pages/migrate/EligibleForTokens'
+import { useEstimateGasWithStateOverride } from '@app/hooks/chain/useEstimateGasWithStateOverride'
import { createTransactionItem } from '@app/transaction-flow/transaction'
import { bulkRenewalContract } from '@app/transaction-flow/transaction/bulkRenew'
-import { REBATE_DATE } from '@app/utils/constants'
+import { CURRENCY_FLUCTUATION_BUFFER_PERCENTAGE, REBATE_DATE } from '@app/utils/constants'
+import useUserConfig from '@app/utils/useUserConfig'
import { formatDurationOfDates } from '@app/utils/utils'
export type Props = { data: { names: NameWithRelation[] } }
@@ -106,15 +109,29 @@ const YearsViewSwitch = styled.button(
`,
)
-const BulkRenewalFlow = ({ data }: Props) => {
- // Sort from the ones that expire earlier to later
- const sortedNames = data.names.toSorted((a, b) => a.expiryDate!.value! - b.expiryDate!.value!)
+const GasEstimationCacheableComponent = styled(CacheableComponent)(
+ ({ theme }) => css`
+ width: 100%;
+ gap: ${theme.space['4']};
+ display: flex;
+ flex-direction: column;
+ `,
+)
+const BulkRenewalFlow = ({ data }: Props) => {
const [date, setDate] = useState(REBATE_DATE)
const [durationType, setDurationType] = useState<'years' | 'date'>('date')
const client = useClient()
+ const { address } = useAccount()
+
+ const { data: balance } = useBalance({
+ address,
+ })
+
+ const dateAsBigInt = BigInt(date.getTime() / 1000)
+
const {
data: expiryData,
error,
@@ -123,13 +140,52 @@ const BulkRenewalFlow = ({ data }: Props) => {
abi,
address: bulkRenewalContract[client.chain.id!]!,
functionName: 'getTargetExpiryPriceData',
- args: [data.names.map((name) => name.labelName!), BigInt(date.getTime() / 1000)],
+ args: [data.names.map((name) => name.labelName!), dateAsBigInt],
+ })
+
+ const [total, durations, prices] = expiryData! as [bigint, bigint[], bigint[]]
+
+ const {
+ data: { gasEstimate: estimatedGasLimit, gasCost: transactionFee },
+ error: estimateGasLimitError,
+ isLoading: isEstimateGasLoading,
+ gasPrice,
+ } = useEstimateGasWithStateOverride({
+ transactions: [
+ {
+ name: 'bulkRenew',
+ data: {
+ names: data.names.map((name) => name.labelhash),
+ durations,
+ prices,
+ },
+ stateOverride: [{ address: address! }],
+ },
+ ],
})
- const { t } = useTranslation()
+ const { t } = useTranslation(['transactionFlow', 'common'])
const now = new Date()
+ const { userConfig, setCurrency } = useUserConfig()
+ const currencyDisplay = userConfig.currency === 'fiat' ? userConfig.fiat : 'eth'
+
+ const items: InvoiceItem[] = [
+ {
+ label: t('input.extendNames.invoice.extension', {
+ time: formatDurationOfDates({ startDate: now, endDate: date, t }),
+ }),
+ value: dateAsBigInt,
+ bufferPercentage: CURRENCY_FLUCTUATION_BUFFER_PERCENTAGE,
+ },
+ {
+ label: t('input.extendNames.invoice.transaction'),
+ value: transactionFee,
+ bufferPercentage: CURRENCY_FLUCTUATION_BUFFER_PERCENTAGE,
+ },
+ ]
+
return (
<>
@@ -179,8 +235,14 @@ const BulkRenewalFlow = ({ data }: Props) => {
- {status}
{error ? {error.message} : null}
+
+
+ {(!!estimateGasLimitError ||
+ (!!estimatedGasLimit && !!balance?.value && balance.value < estimatedGasLimit)) && (
+ {t('input.extendNames.gasLimitError')}
+ )}
+
>
)
diff --git a/src/transaction-flow/transaction/index.ts b/src/transaction-flow/transaction/index.ts
index 96a04cc5d..6a9dda0ac 100644
--- a/src/transaction-flow/transaction/index.ts
+++ b/src/transaction-flow/transaction/index.ts
@@ -2,6 +2,7 @@ import approveDnsRegistrar from './approveDnsRegistrar'
import approveNameWrapper from './approveNameWrapper'
import approveNameWrapperForMigration from './approveNameWrapperForMigration'
import approveRegistrarForMigration from './approveRegistrarForMigration'
+import bulkRenew from './bulkRenew'
import burnFuses from './burnFuses'
import changePermissions from './changePermissions'
import claimDnsName from './claimDnsName'
@@ -37,6 +38,7 @@ export const transactions = {
approveRegistrarForMigration,
approveNameWrapper,
burnFuses,
+ bulkRenew,
changePermissions,
claimDnsName,
commitName,