🌳
pt0/serverF/ethersF/ensSetContenthashAI.mts
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}) => {
37 const provider = getAlchemyProv('homestead')
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)
43 try {
44 const contenthash = await resolver.contenthash(node)
45 return contenthash === '0x' ? null : contenthash
46 } catch {
47 return null
48 }
51export const ensSetContenthash = async ({ensName, ipfsCid, wallet}: {ensName: string, ipfsCid: string, wallet: import('ethers').Wallet}) => {
52 const provider = getAlchemyProv('homestead')
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)
58 betLog({ensName, resolverAddr})
60 const resolver = new Contract(resolverAddr, publicResolverAbi, connectedWallet)
61 const contenthash = cidToContenthash(ipfsCid)
62 betLog({ipfsCid, contenthash})
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}