From b18615c237eff108f93e2c9d2c37c134a1f69dba Mon Sep 17 00:00:00 2001 From: v1rtl Date: Tue, 29 Oct 2024 21:51:30 +0200 Subject: [PATCH] wip --- src/components/pages/migrate/MigrationTab.tsx | 3 +- src/migration/bulkRenewal.ts | 43 -------- .../input/BulkRenewal/BulkRenewal-flow.tsx | 74 ++++++++++++- src/transaction-flow/transaction/bulkRenew.ts | 102 ++++++++++++++++++ src/utils/constants.ts | 2 + 5 files changed, 176 insertions(+), 48 deletions(-) delete mode 100644 src/migration/bulkRenewal.ts create mode 100644 src/transaction-flow/transaction/bulkRenew.ts diff --git a/src/components/pages/migrate/MigrationTab.tsx b/src/components/pages/migrate/MigrationTab.tsx index b42457fcf..bf1950728 100644 --- a/src/components/pages/migrate/MigrationTab.tsx +++ b/src/components/pages/migrate/MigrationTab.tsx @@ -27,6 +27,7 @@ import { useApprovedNamesForMigration } from '@app/hooks/migration/useApprovedNa import { makeIntroItem } from '@app/transaction-flow/intro' import { createTransactionItem, TransactionData } from '@app/transaction-flow/transaction' import { useTransactionFlow } from '@app/transaction-flow/TransactionFlowProvider' +import { REBATE_DATE } from '@app/utils/constants' import { MigrationNamesList, NameListTab } from './MigrationNamesList' import { MigrationSection } from './MigrationSection' @@ -545,7 +546,7 @@ const ExtensionTab = ({ const [activeTab, setNameListTab] = useState('eligible') const claimedNames = allNames.filter( - (name) => name.expiryDate && name.expiryDate.date > new Date(2030, 11, 31, 0, 0), + (name) => name.expiryDate && name.expiryDate.date > REBATE_DATE, ) const eligibleNames = allNames.filter((name) => !claimedNames.includes(name)) diff --git a/src/migration/bulkRenewal.ts b/src/migration/bulkRenewal.ts deleted file mode 100644 index 38b2ee012..000000000 --- a/src/migration/bulkRenewal.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { holesky, sepolia } from 'viem/chains' - -export const targetExpiryAbi = [ - { - inputs: [ - { - internalType: 'string[]', - name: 'names', - type: 'string[]', - }, - { - internalType: 'uint256', - name: 'targetExpiry', - type: 'uint256', - }, - ], - name: 'getTargetExpiryPriceData', - outputs: [ - { - internalType: 'uint256', - name: 'total', - type: 'uint256', - }, - { - internalType: 'uint256[]', - name: 'durations', - type: 'uint256[]', - }, - { - internalType: 'uint256[]', - name: 'prices', - type: 'uint256[]', - }, - ], - stateMutability: 'view', - type: 'function', - }, -] - -export const bulkRenewalContract = { - [holesky.id]: '0x3dCE478E4C880E96Ad3BF022acae38bef43F13eB', - [sepolia.id]: '0x0E714019e4BC65164d29960805259C1fA70E508a', -} diff --git a/src/transaction-flow/input/BulkRenewal/BulkRenewal-flow.tsx b/src/transaction-flow/input/BulkRenewal/BulkRenewal-flow.tsx index f6dacc973..35ab207b0 100644 --- a/src/transaction-flow/input/BulkRenewal/BulkRenewal-flow.tsx +++ b/src/transaction-flow/input/BulkRenewal/BulkRenewal-flow.tsx @@ -1,26 +1,92 @@ import { useState } from 'react' +import { namehash } from 'viem' +import { useClient, useReadContract } from 'wagmi' import { NameWithRelation } from '@ensdomains/ensjs/subgraph' import { Dialog } from '@ensdomains/thorin' +import { InvoiceItem } from '@app/components/@atoms/Invoice/Invoice' import { DateSelection } from '@app/components/@molecules/DateSelection/DateSelection' -import { ONE_YEAR } from '@app/utils/time' +import { createTransactionItem } from '@app/transaction-flow/transaction' +import { bulkRenewalContract } from '@app/transaction-flow/transaction/bulkRenew' +import { REBATE_DATE } from '@app/utils/constants' +import { calculateDatesDiff, secondsFromDateDiff, secondsToDate } from '@app/utils/date' +import { ONE_YEAR, secondsToYears } from '@app/utils/time' export type Props = { data: { names: NameWithRelation[] } } +const abi = [ + { + inputs: [ + { + internalType: 'string[]', + name: 'names', + type: 'string[]', + }, + { + internalType: 'uint256', + name: 'targetExpiry', + type: 'uint256', + }, + ], + name: 'getTargetExpiryPriceData', + outputs: [ + { + internalType: 'uint256', + name: 'total', + type: 'uint256', + }, + { + internalType: 'uint256[]', + name: 'durations', + type: 'uint256[]', + }, + { + internalType: 'uint256[]', + name: 'prices', + type: 'uint256[]', + }, + ], + stateMutability: 'view', + type: 'function', + }, +] as const + const BulkRenewalFlow = ({ data }: Props) => { - const sortedNames = data.names.toSorted((a, b) => a.expiryDate?.value - b.expiryDate?.value) + const sortedNames = data.names.toSorted((a, b) => a.expiryDate!.value! - b.expiryDate!.value!) + + const minDateDiff = calculateDatesDiff(sortedNames[0].expiryDate!.date, REBATE_DATE) + + const minSeconds = secondsFromDateDiff({ + startDate: sortedNames[0].expiryDate!.date, + additionalDays: minDateDiff.diff.days, + additionalMonths: minDateDiff.diff.months, + additionalYears: minDateDiff.diff.years, + }) - const [seconds, setSeconds] = useState(() => 5 * ONE_YEAR) + const [seconds, setSeconds] = useState(() => minSeconds) const [durationType, setDurationType] = useState<'years' | 'date'>('years') + // const client = useClient() + + // const { + // data: expiryData, + // error, + // status, + // } = useReadContract({ + // abi, + // address: bulkRenewalContract[client.chain.id!]!, + // functionName: 'getTargetExpiryPriceData', + // args: [data.names.map((name) => namehash(name.name!)), BigInt(seconds)], + // }) + return ( <> diff --git a/src/transaction-flow/transaction/bulkRenew.ts b/src/transaction-flow/transaction/bulkRenew.ts new file mode 100644 index 000000000..f8f2f07ef --- /dev/null +++ b/src/transaction-flow/transaction/bulkRenew.ts @@ -0,0 +1,102 @@ +import { TFunction } from 'react-i18next' +import { goerli, holesky, localhost, mainnet, sepolia } from 'viem/chains' +import { encodeFunctionData } from 'viem/utils' + +import type { Transaction, TransactionDisplayItem, TransactionFunctionParameters } from '@app/types' + +type Data = { names: `0x${string}`[]; durations: bigint[]; prices: bigint[] } + +export const targetExpiryAbi = [ + { + inputs: [ + { + internalType: 'string[]', + name: 'names', + type: 'string[]', + }, + { + internalType: 'uint256', + name: 'targetExpiry', + type: 'uint256', + }, + ], + name: 'getTargetExpiryPriceData', + outputs: [ + { + internalType: 'uint256', + name: 'total', + type: 'uint256', + }, + { + internalType: 'uint256[]', + name: 'durations', + type: 'uint256[]', + }, + { + internalType: 'uint256[]', + name: 'prices', + type: 'uint256[]', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { + internalType: 'string[]', + name: 'names', + type: 'string[]', + }, + { + internalType: 'uint256[]', + name: 'durations', + type: 'uint256[]', + }, + { + internalType: 'uint256[]', + name: 'prices', + type: 'uint256[]', + }, + ], + name: 'renewAllWithTargetExpiry', + outputs: [], + stateMutability: 'payable', + type: 'function', + }, +] as const + +export const bulkRenewalContract = { + [mainnet.id]: '0xnotdeployedyet', + [goerli.id]: '0xdeprecated', + [localhost.id]: '0xnotdeployedyet', + [holesky.id]: '0x76aafA281Ed5155f83926a12ACB92e237e322A8C', + [sepolia.id]: '0xf9c8c83adda8d52d9284cdbef23da10b5f9869bf', +} as const + +const displayItems = ( + { names }: Data, + t: TFunction<'translation', undefined>, +): TransactionDisplayItem[] => [ + { + label: 'names', + value: names.map((name) => `0x${name}`).join(', '), + }, + { + label: 'action', + value: t('transaction.info.fuses.CAN_EXTEND_EXPIRY'), + }, +] + +const transaction = async ({ client, data }: TransactionFunctionParameters) => { + return { + to: bulkRenewalContract[client.chain.id], + data: encodeFunctionData({ + abi: targetExpiryAbi, + functionName: 'renewAllWithTargetExpiry', + args: [data.names, data.durations, data.prices], + }), + } +} + +export default { displayItems, transaction } satisfies Transaction diff --git a/src/utils/constants.ts b/src/utils/constants.ts index 994abc021..1c5dd45ba 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -26,3 +26,5 @@ export const IS_DEV_ENVIRONMENT = process.env.NEXT_PUBLIC_PROVIDER export const INVALID_NAME = '[Invalid ENS Name]' + +export const REBATE_DATE = new Date(2030, 11, 31, 0, 0)