Skip to content

Commit

Permalink
Merge pull request #228 from blockful-io/161-contenthash-table
Browse files Browse the repository at this point in the history
feat: add contenthash table
  • Loading branch information
pikonha authored Oct 29, 2024
2 parents 8901d8c + 9819ad2 commit ad4ecc6
Show file tree
Hide file tree
Showing 24 changed files with 500 additions and 203 deletions.
57 changes: 42 additions & 15 deletions packages/client/src/read.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,26 @@
*/

import { config } from 'dotenv'
import { Hex, createPublicClient, http } from 'viem'
import {
Hex,
createPublicClient,
http,
namehash,
decodeFunctionResult,
hexToString,
} from 'viem'
import { normalize } from 'viem/ens'
import { getChain } from './client'

import { abi as l1Abi } from '@blockful/contracts/out/L1Resolver.sol/L1Resolver.json'
config({
path: process.env.ENV_FILE || '../.env',
})

const {
UNIVERSAL_RESOLVER_ADDRESS: resolver,
CHAIN_ID: chainId = '31337',
RPC_URL: provider = 'http://127.0.0.1:8545/',
GATEWAY_URL: gateway = 'http://127.0.0.1:3000/{sender}/{data}.json',
UNIVERSAL_RESOLVER_ADDRESS: universalResolverAddress,
} = process.env

const chain = getChain(parseInt(chainId))
Expand All @@ -29,42 +36,62 @@ const client = createPublicClient({

// eslint-disable-next-line
const _ = (async () => {
const publicAddress = normalize('blockful.eth')
const name = normalize('lucas.arb.eth')

const twitter = await client.getEnsText({
name: publicAddress,
name,
key: 'com.twitter',
universalResolverAddress: resolver as Hex,
universalResolverAddress: universalResolverAddress as Hex,
gatewayUrls: [gateway],
})
const avatar = await client.getEnsAvatar({
name: publicAddress,
universalResolverAddress: resolver as Hex,
name,
universalResolverAddress: universalResolverAddress as Hex,
gatewayUrls: [gateway],
})

const address = await client.getEnsAddress({
name: publicAddress,
universalResolverAddress: resolver as Hex,
name,
universalResolverAddress: universalResolverAddress as Hex,
gatewayUrls: [gateway],
})
const addressBtc = await client.getEnsAddress({
name: publicAddress,
name,
coinType: 1,
universalResolverAddress: resolver as Hex,
universalResolverAddress: universalResolverAddress as Hex,
gatewayUrls: [gateway],
})
const name = await client.getEnsName({
const domainName = await client.getEnsName({
address: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266',
universalResolverAddress: resolver as Hex,
universalResolverAddress: universalResolverAddress as Hex,
gatewayUrls: [gateway],
})

const resolver = await client.getEnsResolver({
name,
universalResolverAddress: universalResolverAddress as Hex,
})
const encodedContentHash = (await client.readContract({
address: resolver,
functionName: 'contenthash',
abi: l1Abi,
args: [namehash(name)],
})) as Hex

const contentHash = hexToString(
decodeFunctionResult({
abi: l1Abi,
functionName: 'contenthash',
data: encodedContentHash,
}) as Hex,
)

console.log({
twitter,
avatar,
address,
addressBtc,
name,
name: domainName,
contentHash,
})
})()
39 changes: 19 additions & 20 deletions packages/client/src/write.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,19 @@

import { config } from 'dotenv'
import {
Hash,
Hex,
createPublicClient,
encodeFunctionData,
getChainContractAddress,
http,
namehash,
stringToHex,
toHex,
walletActions,
zeroHash,
} from 'viem'
import { normalize, packetToBytes } from 'viem/ens'
import { privateKeyToAccount } from 'viem/accounts'

import { abi as uAbi } from '@blockful/contracts/out/UniversalResolver.sol/UniversalResolver.json'
import { abi as l1Abi } from '@blockful/contracts/out/L1Resolver.sol/L1Resolver.json'
import { MessageData, DomainData } from '@blockful/gateway/src/types'
import { getRevertErrorData, getChain, handleDBStorage } from './client'
Expand All @@ -28,7 +26,7 @@ config({
path: process.env.ENV_FILE || '../.env',
})

let {
const {
UNIVERSAL_RESOLVER_ADDRESS: universalResolver,
RESOLVER_ADDRESS: resolver,
CHAIN_ID: chainId = '31337',
Expand All @@ -54,27 +52,18 @@ const _ = (async () => {
throw new Error('RESOLVER_ADDRESS is required')
}

const name = normalize('gibi.blockful.eth')
const name = normalize('gibi.arb.eth')
const encodedName = toHex(packetToBytes(name))
const node = namehash(name)
const signer = privateKeyToAccount(privateKey as Hex)

if (!universalResolver) {
universalResolver = getChainContractAddress({
chain: client.chain,
contract: 'ensUniversalResolver',
})
}

const [resolverAddr] = (await client.readContract({
address: universalResolver as Hex,
functionName: 'findResolver',
abi: uAbi,
args: [encodedName],
})) as Hash[]

const duration = 31556952000n

const resolverAddr = await client.getEnsResolver({
name,
universalResolverAddress: universalResolver as Hex,
})

// SUBDOMAIN PRICING

let value = 0n
Expand All @@ -97,7 +86,7 @@ const _ = (async () => {
encodeFunctionData({
functionName: 'setText',
abi: l1Abi,
args: [node, 'com.twitter', '@lucas'],
args: [node, 'com.twitter', `@${name}`],
}),
encodeFunctionData({
functionName: 'setAddr',
Expand All @@ -109,6 +98,16 @@ const _ = (async () => {
abi: l1Abi,
args: [node, 1n, '0x3a872f8FED4421E7d5BE5c98Ab5Ea0e0245169A0'],
}),
encodeFunctionData({
functionName: 'setContenthash',
abi: l1Abi,
args: [
node,
stringToHex(
'ipns://k51qzi5uqu5dgccx524mfjv7znyfsa6g013o6v4yvis9dxnrjbwojc62pt0450',
),
],
}),
]

const calldata = {
Expand Down
64 changes: 60 additions & 4 deletions packages/client/test/db.e2e.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ import {
Hex,
PrivateKeyAccount,
toHex,
stringToHex,
decodeFunctionResult,
} from 'viem'
import { assert, expect } from 'chai'
import { ApolloServer } from '@apollo/server'
Expand All @@ -61,6 +63,7 @@ import {
withSetAddr,
withSetText,
withRegisterDomain,
withSetContentHash,
} from '@blockful/gateway/src/handlers'
import {
DomainData,
Expand All @@ -70,7 +73,12 @@ import {
} from '@blockful/gateway/src/types'
import { domainResolver } from '@blockful/gateway/src/resolvers'
import { PostgresRepository } from '@blockful/gateway/src/repositories'
import { Text, Domain, Address } from '@blockful/gateway/src/entities'
import {
Text,
Domain,
Address,
Contenthash,
} from '@blockful/gateway/src/entities'
import { withSigner } from '@blockful/gateway/src/middlewares'
import {
EthereumClient,
Expand Down Expand Up @@ -190,6 +198,7 @@ function setupGateway(
withGetAddr(repo),
withSetAddr(repo, validator),
withGetContentHash(repo),
withSetContentHash(repo, validator),
)
server.makeApp('/').listen('3000')
}
Expand Down Expand Up @@ -256,7 +265,7 @@ describe('DatabaseResolver', () => {
datasource = new DataSource({
type: 'better-sqlite3',
database: './test.db',
entities: [Text, Domain, Address],
entities: [Text, Domain, Address, Contenthash],
synchronize: true,
})
repo = new PostgresRepository(await datasource.initialize())
Expand All @@ -267,7 +276,7 @@ describe('DatabaseResolver', () => {
})

beforeEach(async () => {
for (const entity of ['Text', 'Address', 'Domain']) {
for (const entity of ['Text', 'Address', 'Domain', 'Contenthash']) {
await datasource.getRepository(entity).clear()
}
})
Expand Down Expand Up @@ -772,6 +781,45 @@ describe('DatabaseResolver', () => {
const name = normalize('l1domain.eth')
const node = namehash(name)

it('should set and read contenthash from database', async () => {
const contentHash =
'ipns://k51qzi5uqu5dgccx524mfjv7znyfsa6g013o6v4yvis9dxnrjbwojc62pt0450'

const response = await offchainWriting({
name,
functionName: 'setContenthash',
abi: abiDBResolver,
args: [node, stringToHex(contentHash)],
universalResolverAddress,
signer: owner,
})

expect(response?.status).equal(200)

const [r] = (await client.readContract({
address: universalResolverAddress as Hex,
functionName: 'resolve',
abi: abiUniversalResolver,
args: [
toHex(packetToBytes(name)),
encodeFunctionData({
abi: abiDBResolver,
functionName: 'contenthash',
args: [node],
}),
],
})) as [Hex]

const actual = decodeFunctionResult({
abi: abiDBResolver,
functionName: 'contenthash',
data: r,
args: [node],
})

expect(actual).equal(stringToHex(contentHash))
})

it('should read the avatar from database', async () => {
const text = new Text()
text.domain = node
Expand Down Expand Up @@ -1207,6 +1255,14 @@ describe('DatabaseResolver', () => {
a.updatedAt = new Date()
await datasource.manager.save(a)

const ch = new Contenthash()
ch.domain = d.node
ch.contenthash =
'ipns://k51qzi5uqu5dgccx524mfjv7znyfsa6g013o6v4yvis9dxnrjbwojc62pt0450'
ch.resolver = '0x1resolver'
ch.resolverVersion = '1'
await datasource.manager.save(ch)

const response = await server.executeOperation({
query: `query Domain($name: String!) {
domain(name: $name) {
Expand Down Expand Up @@ -1274,7 +1330,7 @@ describe('DatabaseResolver', () => {
expect(subdomain.resolver).to.have.property('addr', '0x1')
expect(subdomain.resolver).to.have.property(
'contentHash',
d.contenthash,
ch.contenthash,
)
expect(subdomain.resolver.texts).to.eql([
{ key: t.key, value: t.value },
Expand Down
Loading

0 comments on commit ad4ecc6

Please sign in to comment.