import { BaseError, decodeFunctionResult, encodeFunctionData, getContractError, type Address, type Hex, } from 'viem' import type { ClientWithPns } from '../../contracts/consts.js' import { getChainContractAddress } from '../../contracts/getChainContractAddress.js' import { nameWrapperGetDataSnippet } from '../../contracts/nameWrapper.js' import type { DateWithValue, GenericPassthrough, Prettify, TransactionRequestWithPassthrough, } from '../../types.js' import { EMPTY_ADDRESS } from '../../utils/consts.js' import { decodeFuses, type DecodedFuses } from '../../utils/fuses.js' import { generateFunction, type GeneratedFunction, } from '../../utils/generateFunction.js' import { makeSafeSecondsDate } from '../../utils/makeSafeSecondsDate.js' import { namehash } from '../../utils/normalise.js' export type GetWrapperDataParameters = { /** Name to get wrapper data for */ name: string } export type GetWrapperDataReturnType = Prettify<{ /** Fuse object */ fuses: DecodedFuses & { value: number } /** Expiry of the name */ expiry: DateWithValue | null /** Owner of the name */ owner: Address } | null> const encode = ( client: ClientWithPns, { name }: GetWrapperDataParameters, ): TransactionRequestWithPassthrough => { const address = getChainContractAddress({ client, contract: 'pnsNameWrapper', }) const args = [BigInt(namehash(name))] as const return { to: address, data: encodeFunctionData({ abi: nameWrapperGetDataSnippet, functionName: 'getData', args, }), passthrough: { address, args }, } } const decode = async ( _client: ClientWithPns, data: Hex | BaseError, passthrough: GenericPassthrough, ): Promise => { if (typeof data === 'object') throw getContractError(data, { abi: nameWrapperGetDataSnippet, functionName: 'getData', args: passthrough.args, address: passthrough.address, }) as BaseError const [owner, fuses, expiry] = decodeFunctionResult({ abi: nameWrapperGetDataSnippet, functionName: 'getData', data, }) if (owner === EMPTY_ADDRESS) { return null } const fuseObj = decodeFuses(fuses) const expiryDate = expiry > 0 ? makeSafeSecondsDate(expiry) : null return { fuses: { ...fuseObj, value: fuses, }, expiry: expiryDate ? { date: expiryDate, value: expiry, } : null, owner, } } type BatchableFunctionObject = GeneratedFunction /** * Gets the wrapper data for a name. * @param client - {@link ClientWithPns} * @param parameters - {@link GetWrapperDataParameters} * @returns Wrapper data object, or null if name is not wrapped. {@link GetWrapperDataReturnType} * * @example * import { createPublicClient, http } from 'viem' * import { mainnet } from 'viem/chains' * import { addPnsContracts } from '@pnsdomains/pnsjs' * import { getWrapperData } from '@pnsdomains/pnsjs/public' * * const client = createPublicClient({ * chain: addPnsContracts(mainnet), * transport: http(), * }) * const result = await getWrapperData(client, { name: 'ilikelasagna.pls' }) */ const getWrapperData = generateFunction({ encode, decode }) as (( client: ClientWithPns, { name }: GetWrapperDataParameters, ) => Promise) & BatchableFunctionObject export default getWrapperData