1import { namehash, Contract } from 'ethers' 2import { CID } from 'multiformats/cid' 3import { base58btc } from 'multiformats/bases/base58' 7const publicResolverAbi = [ 8 'function setContenthash(bytes32 node, bytes calldata hash) external', 9 'function contenthash(bytes32 node) external view returns (bytes memory)', 12const ensRegistryAbi = [ 13 'function resolver(bytes32 node) external view returns (address)', 16const ensRegistryAddr = '0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e' 18export const cidToContenthash = (cidStr: string) => { 19 const cid = cidStr.startsWith('Qm') ? CID.parse(cidStr, base58btc) : CID.parse(cidStr) 20 const cidV1 = cid.version === 0 ? cid.toV1() : cid 21 const ipfsNsCode = 0xe3, ipfsProtoCode = 0x01 22 const cidBytes = cidV1.bytes 23 const contenthash = new Uint8Array(2 + cidBytes.length) 24 contenthash[0] = ipfsNsCode 25 contenthash[1] = ipfsProtoCode 26 contenthash.set(cidBytes, 2) 27 return '0x' + Buffer.from(contenthash).toString('hex') 30export const contenthashToCid = (contenthashHex: string): string | null => { 31 const bytes = Buffer.from(contenthashHex.slice(2), 'hex') 32 if (bytes.length < 3 || bytes[0] !== 0xe3 || bytes[1] !== 0x01) return null 33 return CID.decode(bytes.slice(2)).toString() 36export const ensGetContenthash = async ({ensName}: {ensName: string}) => { 38 const node = namehash(ensName) 39 const registry = new Contract(ensRegistryAddr, ensRegistryAbi, provider) 40 const resolverAddr = await registry.resolver(node) 41 if (resolverAddr === '0x0000000000000000000000000000000000000000') return null 42 const resolver = new Contract(resolverAddr, publicResolverAbi, provider) 44 const contenthash = await resolver.contenthash(node) 45 return contenthash === '0x' ? null : contenthash 51export const ensSetContenthash = async ({ensName, ipfsCid, wallet}: {ensName: string, ipfsCid: string, wallet: import('ethers').Wallet}) => { 53 const connectedWallet = wallet.connect(provider) 54 const node = namehash(ensName) 56 const registry = new Contract(ensRegistryAddr, ensRegistryAbi, provider) 57 const resolverAddr = await registry.resolver(node) 60 const resolver = new Contract(resolverAddr, publicResolverAbi, connectedWallet) 61 const contenthash = cidToContenthash(ipfsCid) 64 console.log(`Setting contenthash for ${ensName}...`) 65 const tx = await resolver.setContenthash(node, contenthash) 66 console.log(`Transaction sent: ${tx.hash}`) 68 const receipt = await tx.wait() 69 console.log(`Confirmed in block ${receipt.blockNumber}`) 71 return {txHash: tx.hash, blockNumber: receipt.blockNumber}