import { encodeFunctionData, type Account, type Address, type Hash, type SendTransactionParameters, type Transport, } from 'viem' import { sendTransaction } from 'viem/actions' import { parseAccount } from 'viem/utils' import type { ChainWithPns, ClientWithAccount } from '../../contracts/consts.js' import { getChainContractAddress } from '../../contracts/getChainContractAddress.js' import { reverseRegistrarSetNameForAddrSnippet, reverseRegistrarSetNameSnippet, } from '../../contracts/reverseRegistrar.js' import type { Prettify, SimpleTransactionRequest, WriteTransactionParameters, } from '../../types.js' type BaseSetPrimaryNameDataParameters = { /** The name to set as primary */ name: string /** The address to set the primary name for */ address?: Address /** The resolver address to use */ resolverAddress?: Address } type SelfSetPrimaryNameDataParameters = { address?: never resolverAddress?: never } type OtherSetPrimaryNameDataParameters = { address: Address resolverAddress?: Address } export type SetPrimaryNameDataParameters = BaseSetPrimaryNameDataParameters & (SelfSetPrimaryNameDataParameters | OtherSetPrimaryNameDataParameters) export type SetPrimaryNameDataReturnType = SimpleTransactionRequest export type SetPrimaryNameParameters< TChain extends ChainWithPns, TAccount extends Account | undefined, TChainOverride extends ChainWithPns | undefined, > = Prettify< SetPrimaryNameDataParameters & WriteTransactionParameters > export type SetPrimaryNameReturnType = Hash export const makeFunctionData = < TChain extends ChainWithPns, TAccount extends Account, >( wallet: ClientWithAccount, { name, address, resolverAddress = getChainContractAddress({ client: wallet, contract: 'pnsPublicResolver', }), }: SetPrimaryNameDataParameters, ): SetPrimaryNameDataReturnType => { const reverseRegistrarAddress = getChainContractAddress({ client: wallet, contract: 'pnsReverseRegistrar', }) if (address) { return { to: reverseRegistrarAddress, data: encodeFunctionData({ abi: reverseRegistrarSetNameForAddrSnippet, functionName: 'setNameForAddr', args: [ address, wallet.account.address, resolverAddress || getChainContractAddress({ client: wallet, contract: 'pnsPublicResolver', }), name, ], }), } } return { to: reverseRegistrarAddress, data: encodeFunctionData({ abi: reverseRegistrarSetNameSnippet, functionName: 'setName', args: [name], }), } } /** * Sets a primary name for an address. * @param wallet - {@link ClientWithAccount} * @param parameters - {@link SetPrimaryNameParameters} * @returns Transaction hash. {@link SetPrimaryNameReturnType} * * @example * import { createWalletClient, custom } from 'viem' * import { mainnet } from 'viem/chains' * import { addPnsContracts } from '@pnsdomains/pnsjs' * import { setPrimaryName } from '@pnsdomains/pnsjs/wallet' * * const wallet = createWalletClient({ * chain: addPnsContracts(mainnet), * transport: custom(window.ethereum), * }) * const hash = await setPrimaryName(wallet, { * name: 'pns.pls', * }) * // 0x... */ async function setPrimaryName< TChain extends ChainWithPns, TAccount extends Account | undefined, TChainOverride extends ChainWithPns | undefined = ChainWithPns, >( wallet: ClientWithAccount, { name, address, resolverAddress, ...txArgs }: SetPrimaryNameParameters, ): Promise { const data = makeFunctionData( { ...wallet, account: parseAccount((txArgs.account || wallet.account)!), } as ClientWithAccount, { name, address, resolverAddress } as SetPrimaryNameDataParameters, ) const writeArgs = { ...data, ...txArgs, } as SendTransactionParameters return sendTransaction(wallet, writeArgs) } setPrimaryName.makeFunctionData = makeFunctionData export default setPrimaryName