import { encodeFunctionData, type Account, type Hash, type SendTransactionParameters, type Transport, } from 'viem' import { sendTransaction } from 'viem/actions' import { bulkRenewalRenewAllSnippet } from '../../contracts/bulkRenewal.js' import type { ChainWithPns, ClientWithAccount } from '../../contracts/consts.js' import { plsRegistrarControllerRenewSnippet } from '../../contracts/plsRegistrarController.js' import { getChainContractAddress } from '../../contracts/getChainContractAddress.js' import { UnsupportedNameTypeError } from '../../errors/general.js' import type { Prettify, SimpleTransactionRequest, WriteTransactionParameters, } from '../../types.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 /** Value of all renewals */ value: bigint } export type RenewNamesDataReturnType = SimpleTransactionRequest & { value: bigint } export type RenewNamesParameters< TChain extends ChainWithPns, TAccount extends Account | undefined, TChainOverride extends ChainWithPns | undefined, > = Prettify< RenewNamesDataParameters & WriteTransactionParameters > export type RenewNamesReturnType = Hash export const makeFunctionData = < TChain extends ChainWithPns, TAccount extends Account | undefined, >( wallet: ClientWithAccount, { nameOrNames, duration, 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 !== 'pls-2ld') throw new UnsupportedNameTypeError({ nameType, supportedNameTypes: ['pls-2ld'], details: 'Only 2ld-pls renewals are currently supported', }) return label[0] }) if (labels.length === 1) { return { to: getChainContractAddress({ client: wallet, contract: 'pnsPlsRegistrarController', }), data: encodeFunctionData({ abi: plsRegistrarControllerRenewSnippet, functionName: 'renew', args: [labels[0], BigInt(duration)], }), value, } } return { to: getChainContractAddress({ client: wallet, contract: 'pnsBulkRenewal', }), data: encodeFunctionData({ abi: bulkRenewalRenewAllSnippet, functionName: 'renewAll', args: [labels, BigInt(duration)], }), 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 { addPnsContracts } from '@pnsdomains/pnsjs' * import { getPrice } from '@pnsdomains/pnsjs/public' * import { renewNames } from '@pnsdomains/pnsjs/wallet' * * const mainnetWithPns = addPnsContracts(mainnet) * const client = createPublicClient({ * chain: mainnetWithPns, * transport: http(), * }) * const wallet = createWalletClient({ * chain: mainnetWithPns, * transport: custom(window.ethereum), * }) * * const duration = 31536000 // 1 year * const { base, premium } = await getPrice(wallet, { * nameOrNames: 'example.pls', * duration, * }) * const value = (base + premium) * 110n / 100n // add 10% to the price for buffer * const hash = await renewNames(wallet, { * nameOrNames: 'example.pls', * duration, * value, * }) * // 0x... */ async function renewNames< TChain extends ChainWithPns, TAccount extends Account | undefined, TChainOverride extends ChainWithPns | undefined = ChainWithPns, >( 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