import { encodeFunctionData, type Account, type Address, type Hash, type SendTransactionParameters, type Transport, } from 'viem' import { sendTransaction } from 'viem/actions' import type { ChainWithPns, ClientWithAccount } from '../../contracts/consts.js' import { getChainContractAddress } from '../../contracts/getChainContractAddress.js' import { nameWrapperUnwrapPls2ldSnippet, nameWrapperUnwrapSnippet, } from '../../contracts/nameWrapper.js' import { AdditionalParameterSpecifiedError, RequiredParameterNotSpecifiedError, } from '../../errors/general.js' import type { Pls2ldName, Pls2ldNameSpecifier, GetNameType, SimpleTransactionRequest, WriteTransactionParameters, } from '../../types.js' import { getNameType } from '../../utils/getNameType.js' import { makeLabelNodeAndParent } from '../../utils/makeLabelNodeAndParent.js' type BaseUnwrapNameDataParameters = { /** The name to unwrap */ name: TName /** The recipient of the unwrapped name */ newOwnerAddress: Address /** The registrant of the unwrapped name (pls-2ld only) */ newRegistrantAddress?: Address } type Pls2ldUnwrapNameDataParameters = { name: Pls2ldName newRegistrantAddress: Address } type OtherUnwrapNameDataParameters = { name: string newRegistrantAddress?: never } export type UnwrapNameDataParameters< TName extends string, TNameType extends GetNameType = GetNameType, > = BaseUnwrapNameDataParameters & (TNameType extends Pls2ldNameSpecifier ? Pls2ldUnwrapNameDataParameters : OtherUnwrapNameDataParameters) export type UnwrapNameDataReturnType = SimpleTransactionRequest export type UnwrapNameParameters< TName extends string, TChain extends ChainWithPns, TAccount extends Account | undefined, TChainOverride extends ChainWithPns | undefined, > = UnwrapNameDataParameters & WriteTransactionParameters export type UnwrapNameReturnType = Hash export const makeFunctionData = < TName extends string, TChain extends ChainWithPns, TAccount extends Account | undefined, >( wallet: ClientWithAccount, { name, newOwnerAddress, newRegistrantAddress, }: UnwrapNameDataParameters, ): UnwrapNameDataReturnType => { const { labelhash, parentNode } = makeLabelNodeAndParent(name) const nameWrapperAddress = getChainContractAddress({ client: wallet, contract: 'pnsNameWrapper', }) const nameType = getNameType(name) if (nameType === 'pls-2ld') { if (!newRegistrantAddress) throw new RequiredParameterNotSpecifiedError({ parameter: 'newRegistrantAddress', details: 'Must provide newRegistrantAddress for pls-2ld names', }) return { to: nameWrapperAddress, data: encodeFunctionData({ abi: nameWrapperUnwrapPls2ldSnippet, functionName: 'unwrapPLS2LD', args: [labelhash, newRegistrantAddress, newOwnerAddress], }), } } if (newRegistrantAddress) throw new AdditionalParameterSpecifiedError({ parameter: 'newRegistrantAddress', allowedParameters: ['name', 'newOwnerAddress'], details: 'newRegistrantAddress can only be specified for pls-2ld names', }) return { to: nameWrapperAddress, data: encodeFunctionData({ abi: nameWrapperUnwrapSnippet, functionName: 'unwrap', args: [parentNode, labelhash, newOwnerAddress], }), } } /** * Unwraps a name. * @param wallet - {@link ClientWithAccount} * @param parameters - {@link UnwrapNameParameters} * @returns Transaction hash. {@link UnwrapNameReturnType} * * @example * import { createWalletClient, custom } from 'viem' * import { mainnet } from 'viem/chains' * import { addPnsContracts } from '@pnsdomains/pnsjs' * import { unwrapName } from '@pnsdomains/pnsjs/wallet' * * const wallet = createWalletClient({ * chain: addPnsContracts(mainnet), * transport: custom(window.ethereum), * }) * const hash = await unwrapName(wallet, { * name: 'example.pls', * newOwnerAddress: '0xFe89cc7aBB2C4183683ab71653C4cdc9B02D44b7', * newRegistrantAddress: '0xFe89cc7aBB2C4183683ab71653C4cdc9B02D44b7', * }) * // 0x... */ async function unwrapName< TName extends string, TChain extends ChainWithPns, TAccount extends Account | undefined, TChainOverride extends ChainWithPns | undefined = ChainWithPns, >( wallet: ClientWithAccount, { name, newOwnerAddress, newRegistrantAddress, ...txArgs }: UnwrapNameParameters, ): Promise { const data = makeFunctionData(wallet, { name, newOwnerAddress, newRegistrantAddress, } as UnwrapNameDataParameters) const writeArgs = { ...data, ...(txArgs as WriteTransactionParameters), } as SendTransactionParameters return sendTransaction(wallet, writeArgs) } unwrapName.makeFunctionData = makeFunctionData export default unwrapName