Skip to content
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
281 changes: 163 additions & 118 deletions packages/ensjs/src/actions/wallet/setResolver.ts
Original file line number Diff line number Diff line change
@@ -1,119 +1,164 @@
import type {
Account,
Address,
Chain,
GetChainContractAddressErrorType,
WriteContractErrorType,
WriteContractParameters,
WriteContractReturnType,
} from 'viem'
import { writeContract } from 'viem/actions'
import { getAction } from 'viem/utils'
Account,
Address,
Chain,
GetChainContractAddressErrorType,
WriteContractErrorType,
WriteContractParameters,
WriteContractReturnType,
} from "viem";
import { labelhash } from "viem";
import { writeContract } from "viem/actions";
import { getAction } from "viem/utils";
import {
type ChainWithContracts,
getChainContractAddress,
type RequireClientContracts,
} from '../../clients/chain.js'
import { nameWrapperSetResolverSnippet } from '../../contracts/nameWrapper.js'
import { registrySetResolverSnippet } from '../../contracts/registry.js'
import type { ErrorType } from '../../errors/utils.js'
import type { Prettify, WriteTransactionParameters } from '../../types/index.js'
import { ASSERT_NO_TYPE_ERROR } from '../../types/internal.js'
type ChainWithContracts,
getChainContractAddress,
type RequireClientContracts,
} from "../../clients/chain.js";
import { nameWrapperSetResolverSnippet } from "../../contracts/nameWrapper.js";
import { registrySetResolverSnippet } from "../../contracts/registry.js";
import type { ErrorType } from "../../errors/utils.js";
import type {
Prettify,
WriteTransactionParameters,
} from "../../types/index.js";
import { ASSERT_NO_TYPE_ERROR } from "../../types/internal.js";
import {
type ClientWithOverridesErrorType,
clientWithOverrides,
} from '../../utils/clientWithOverrides.js'
import { type NamehashErrorType, namehash } from '../../utils/name/namehash.js'
type ClientWithOverridesErrorType,
clientWithOverrides,
} from "../../utils/clientWithOverrides.js";
import { type NamehashErrorType, namehash } from "../../utils/name/namehash.js";

export type SetResolverWriteParametersParameters = {
/** Name to set resolver for */
name: string
/** Contract to set resolver on */
contract: 'registry' | 'nameWrapper'
/** Resolver address to set */
resolverAddress: Address
}
/** Name to set resolver for */
name: string;
/** Contract to set resolver on - can be 'registry', 'nameWrapper', or an address of a namechain registry */
contract: "registry" | "nameWrapper" | Address;
/** Resolver address to set */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd recommend turning contract into optional "registry" | "name wrapper" and adding a new parameter called registryAddress to make this more descriptive and precise. You can use discriminated unions to keep it type safe.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think we should think about it more. i'll leave it as is for now

resolverAddress: Address;
};

export type SetResolverWriteParametersReturnType = ReturnType<
typeof setResolverWriteParameters
>
typeof setResolverWriteParameters
>;

export type SetResolverWriteParametersErrorType =
| ErrorType
| GetChainContractAddressErrorType
| NamehashErrorType
| ErrorType
| GetChainContractAddressErrorType
| NamehashErrorType;

// ================================
// Write parameters
// ================================

export const setResolverWriteParameters = <
chain extends Chain,
account extends Account,
chain extends Chain,
account extends Account,
>(
client: RequireClientContracts<
chain,
'ensNameWrapper' | 'ensRegistry',
account
>,
{ name, contract, resolverAddress }: SetResolverWriteParametersParameters,
client: RequireClientContracts<
chain,
"ensNameWrapper" | "ensRegistry",
account
>,
{ name, contract, resolverAddress }: SetResolverWriteParametersParameters,
) => {
ASSERT_NO_TYPE_ERROR(client)

if (contract !== 'registry' && contract !== 'nameWrapper')
throw new Error(`Unknown contract: ${contract}`)

const address = getChainContractAddress({
chain: client.chain,
contract: contract === 'nameWrapper' ? 'ensNameWrapper' : 'ensRegistry',
})

const args = [namehash(name), resolverAddress] as const
const functionName = 'setResolver'

const baseParams = {
address,
functionName,
args,
chain: client.chain,
account: client.account,
} as const

if (contract === 'nameWrapper')
return {
...baseParams,
abi: nameWrapperSetResolverSnippet,
} as const satisfies WriteContractParameters<
typeof nameWrapperSetResolverSnippet
>

return {
...baseParams,
abi: registrySetResolverSnippet,
} as const satisfies WriteContractParameters<
typeof registrySetResolverSnippet
>
}
ASSERT_NO_TYPE_ERROR(client);

// Handle legacy contracts
if (contract === "registry" || contract === "nameWrapper") {
const address = getChainContractAddress({
chain: client.chain,
contract: contract === "nameWrapper" ? "ensNameWrapper" : "ensRegistry",
});

const args = [namehash(name), resolverAddress] as const;
const functionName = "setResolver";

const baseParams = {
address,
functionName,
args,
chain: client.chain,
account: client.account,
} as const;

if (contract === "nameWrapper")
return {
...baseParams,
abi: nameWrapperSetResolverSnippet,
} as const satisfies WriteContractParameters<
typeof nameWrapperSetResolverSnippet
>;

return {
...baseParams,
abi: registrySetResolverSnippet,
} as const satisfies WriteContractParameters<
typeof registrySetResolverSnippet
>;
}

// Handle namechain contracts
const label = name.split(".")[0];
const tokenId = BigInt(labelhash(label));

const args = [tokenId, resolverAddress] as const;
const functionName = "setResolver";

const baseParams = {
address: contract as Address,
functionName,
args,
chain: client.chain,
account: client.account,
} as const;

const namechainSetResolverSnippet = [
{
inputs: [
{
name: "tokenId",
type: "uint256",
},
{
name: "resolver",
type: "address",
},
],
name: "setResolver",
outputs: [],
stateMutability: "nonpayable",
type: "function",
},
] as const;

return {
...baseParams,
abi: namechainSetResolverSnippet,
} as const satisfies WriteContractParameters<
typeof namechainSetResolverSnippet
>;
};

// ================================
// Action
// ================================

export type SetResolverParameters<
chain extends Chain,
account extends Account,
chainOverride extends ChainWithContracts<'ensNameWrapper' | 'ensRegistry'>,
chain extends Chain,
account extends Account,
chainOverride extends ChainWithContracts<"ensNameWrapper" | "ensRegistry">,
> = Prettify<
SetResolverWriteParametersParameters &
WriteTransactionParameters<chain, account, chainOverride>
>
SetResolverWriteParametersParameters &
WriteTransactionParameters<chain, account, chainOverride>
>;

export type SetResolverReturnType = WriteContractReturnType
export type SetResolverReturnType = WriteContractReturnType;

export type SetResolverErrorType =
| SetResolverWriteParametersErrorType
| ClientWithOverridesErrorType
| WriteContractErrorType
| SetResolverWriteParametersErrorType
| ClientWithOverridesErrorType
| WriteContractErrorType;

/**
* Sets a resolver for a name.
Expand All @@ -139,35 +184,35 @@ export type SetResolverErrorType =
* // 0x...
*/
export async function setResolver<
chain extends Chain,
account extends Account,
chainOverride extends ChainWithContracts<'ensNameWrapper' | 'ensRegistry'>,
chain extends Chain,
account extends Account,
chainOverride extends ChainWithContracts<"ensNameWrapper" | "ensRegistry">,
>(
client: RequireClientContracts<
chain,
'ensNameWrapper' | 'ensRegistry',
account
>,
{
name,
contract,
resolverAddress,
...txArgs
}: SetResolverParameters<chain, account, chainOverride>,
client: RequireClientContracts<
chain,
"ensNameWrapper" | "ensRegistry",
account
>,
{
name,
contract,
resolverAddress,
...txArgs
}: SetResolverParameters<chain, account, chainOverride>,
): Promise<SetResolverReturnType> {
ASSERT_NO_TYPE_ERROR(client)

const writeParameters = setResolverWriteParameters(
clientWithOverrides(client, txArgs),
{
name,
contract,
resolverAddress,
},
)
const writeContractAction = getAction(client, writeContract, 'writeContract')
return writeContractAction({
...writeParameters,
...txArgs,
} as WriteContractParameters)
ASSERT_NO_TYPE_ERROR(client);

const writeParameters = setResolverWriteParameters(
clientWithOverrides(client, txArgs),
{
name,
contract,
resolverAddress,
},
);
const writeContractAction = getAction(client, writeContract, "writeContract");
return writeContractAction({
...writeParameters,
...txArgs,
} as WriteContractParameters);
}
Loading