import { type Account, type Hash, type Hex, type SendTransactionParameters, type Transport, encodeFunctionData, } from 'viem' import { sendTransaction } from 'viem/actions' import { bulkRenewalRenewAllSnippet } from '../../contracts/bulkRenewal.js' import type { ChainWithEns, ClientWithAccount } from '../../contracts/consts.js' import { ethRegistrarControllerRenewSnippet } from '../../contracts/ethRegistrarController.js' import { getChainContractAddress } from '../../contracts/getChainContractAddress.js' import { UnsupportedNameTypeError } from '../../errors/general.js' import type { Prettify, SimpleTransactionRequest, WriteTransactionParameters, } from '../../types.js' import { EMPTY_BYTES32 } from '../../utils/consts.js' import { getNameType } from '../../utils/getNameType.js' export type RenewNamesDataParameters = { /** Name or names to renew */ nameOrNames: string | string[] /** Duration to renew name(s) for */ duration: bigint | number /** Referrer data */ referrer?: Hex /** Value of all renewals */ value: bigint } export type RenewNamesDataReturnType = SimpleTransactionRequest & { value: bigint } export type RenewNamesParameters< TChain extends ChainWithEns, TAccount extends Account | undefined, TChainOverride extends ChainWithEns | undefined, > = Prettify< RenewNamesDataParameters & WriteTransactionParameters > export type RenewNamesReturnType = Hash export const makeFunctionData = < TChain extends ChainWithEns, TAccount extends Account | undefined, >( wallet: ClientWithAccount, { nameOrNames, duration, referrer = EMPTY_BYTES32, value, }: RenewNamesDataParameters, ): RenewNamesDataReturnType => { const names = Array.isArray(nameOrNames) ? nameOrNames : [nameOrNames] const labels = names.map((name) => { const label = name.split('.') const nameType = getNameType(name) if (nameType !== 'eth-2ld') throw new UnsupportedNameTypeError({ nameType, supportedNameTypes: ['eth-2ld'], details: 'Only 2ld-eth renewals are currently supported', }) return label[0] }) if (labels.length === 1) { return { to: getChainContractAddress({ client: wallet, contract: 'ensEthRegistrarController', }), data: encodeFunctionData({ abi: ethRegistrarControllerRenewSnippet, functionName: 'renew', args: [labels[0], BigInt(duration), referrer], }), value, } } return { to: getChainContractAddress({ client: wallet, contract: 'ensBulkRenewal', }), data: encodeFunctionData({ abi: bulkRenewalRenewAllSnippet, functionName: 'renewAll', args: [labels, BigInt(duration), referrer], }), value, } } /** * Renews a name or names for a specified duration. * @param wallet - {@link ClientWithAccount} * @param parameters - {@link RenewNamesParameters} * @returns Transaction hash. {@link RenewNamesReturnType} * * @example * import { createPublicClient, createWalletClient, http, custom } from 'viem' * import { mainnet } from 'viem/chains' * import { addEnsContracts } from '@etn-sc/ensjs' * import { getPrice } from '@etn-sc/ensjs/public' * import { renewNames } from '@etn-sc/ensjs/wallet' * * const mainnetWithEns = addEnsContracts(mainnet) * const client = createPublicClient({ * chain: mainnetWithEns, * transport: http(), * }) * const wallet = createWalletClient({ * chain: mainnetWithEns, * transport: custom(window.ethereum), * }) * * const duration = 31536000 // 1 year * const { base, premium } = await getPrice(wallet, { * nameOrNames: 'example.eth', * duration, * }) * const value = (base + premium) * 110n / 100n // add 10% to the price for buffer * const hash = await renewNames(wallet, { * nameOrNames: 'example.eth', * duration, * value, * }) * // 0x... */ async function renewNames< TChain extends ChainWithEns, TAccount extends Account | undefined, TChainOverride extends ChainWithEns | undefined = ChainWithEns, >( wallet: ClientWithAccount, { nameOrNames, duration, value, ...txArgs }: RenewNamesParameters, ): Promise { const data = makeFunctionData(wallet, { nameOrNames, duration, value }) const writeArgs = { ...data, ...txArgs, } as SendTransactionParameters return sendTransaction(wallet, writeArgs) } renewNames.makeFunctionData = makeFunctionData export default renewNames