Skip to content

Commit

Permalink
fix: use the recommended approach for nomspace resolution (#23)
Browse files Browse the repository at this point in the history
BREAKING CHANGE because it changes the parameters for constructing the nomspace
resolution.
  • Loading branch information
silasbw authored Feb 9, 2022
1 parent a11bbba commit 5500e28
Show file tree
Hide file tree
Showing 6 changed files with 1,998 additions and 861 deletions.
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"test": "jest && prettier --check \"./**/*.ts\" && eslint --ext=.tsx,.ts,.json src/ scripts/",
"prepublishOnly": "yarn build",
"release": "standard-version",
"resolve": "ts-node scripts/resolve.ts"
"resolve": "ts-node --files=src/global.d.ts scripts/resolve.ts"
},
"repository": "git@github.com:valora-inc/resolve-kit.git",
"author": "Valora Inc",
Expand Down Expand Up @@ -40,7 +40,8 @@
"dependencies": {
"@celo/base": "^1.5.2",
"@celo/utils": "^1.5.1",
"@nomspace/nomspace": "^1.0.6",
"@ensdomains/ensjs": "^2.0.1",
"eth-ens-namehash": "^2.0.8",
"ethers": "^5.5.4"
},
"files": [
Expand Down
8 changes: 5 additions & 3 deletions scripts/resolve.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
/* eslint no-console: "off" */
import { newKit } from '@celo/contractkit'
import yargs from 'yargs'

import { ResolveGroup, ResolveAddress, ResolveNom } from '../src'

async function main(args: any) {
const kit = newKit('https://forno.celo.org')
const providerUrl = 'https://forno.celo.org'

const resolver = new ResolveGroup([
new ResolveAddress(),
new ResolveNom({ kit, contractAddress: ResolveNom.MainnetContractAddress }),
new ResolveNom({
providerUrl,
ensRegistryAddress: ResolveNom.ENSRegsitryAddress,
}),
])
const resolutions = await resolver.resolve(args.id)

Expand Down
2 changes: 2 additions & 0 deletions src/global.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
declare module '@ensdomains/ensjs'
declare module 'eth-ens-namehash'
60 changes: 35 additions & 25 deletions src/resolve-nom.test.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,30 @@
import { NomKit } from '@nomspace/nomspace'
import { ResolveNom } from './resolve-nom'

describe('resolve-nom', () => {
describe('ResolveNom', () => {
it('does not return resolutions for unmapped nom', async () => {
const mockNomKit = {
resolve: (_: string) => '0x0000000000000000000000000000000000000000',
} as unknown as NomKit
const resolver = new ResolveNom({ nomKit: mockNomKit })
const mockEns = {
name: (_: string) => ({
getAddress: async (_: string) =>
'0x0000000000000000000000000000000000000000',
}),
}
const resolver = new ResolveNom({ ens: mockEns })
const resolutions = await resolver.resolve('foo')

expect(resolutions.resolutions.length).toBe(0)
expect(resolutions.errors.length).toBe(0)
})

it('does not return resolutions for invalid nom', async () => {
const mockNomKit = {
resolve: (_: string) => {
throw new Error('should not happen')
},
} as unknown as NomKit
const resolver = new ResolveNom({ nomKit: mockNomKit })
const mockEns = {
name: (_: string) => ({
getAddress: async () => {
throw new Error('should not happen')
},
}),
}
const resolver = new ResolveNom({ ens: mockEns })
const tooLongId = new Array(33).join('x')
const resolutions = await resolver.resolve(tooLongId)

Expand All @@ -30,10 +34,12 @@ describe('resolve-nom', () => {

it('return resolutions for valid nom', async () => {
const mockAddress = '0x1212121212121212121212121212121212121212'
const mockNomKit = {
resolve: (_: string) => mockAddress,
} as unknown as NomKit
const resolver = new ResolveNom({ nomKit: mockNomKit })
const mockEns = {
name: (_: string) => ({
getAddress: async () => mockAddress,
}),
}
const resolver = new ResolveNom({ ens: mockEns })
const resolutions = await resolver.resolve('foo.nom')

expect(resolutions.resolutions.length).toBe(1)
Expand All @@ -45,23 +51,27 @@ describe('resolve-nom', () => {
})

it('does not return resolutions if domain does not end in ".nom"', async () => {
const mockNomKit = {
resolve: (_: string) => '0x1212121212121212121212121212121212121212',
} as unknown as NomKit
const resolver = new ResolveNom({ nomKit: mockNomKit })
const mockEns = {
name: (_: string) => ({
getAddress: async () => '0x1212121212121212121212121212121212121212',
}),
}
const resolver = new ResolveNom({ ens: mockEns })
const resolutions = await resolver.resolve('foo')

expect(resolutions.resolutions.length).toBe(0)
expect(resolutions.errors.length).toBe(0)
})

it('returns errors', async () => {
const mockNomKit = {
resolve: (_: string) => {
throw new Error('network error or something')
},
} as unknown as NomKit
const resolver = new ResolveNom({ nomKit: mockNomKit })
const mockEns = {
name: (_: string) => ({
getAddress: async () => {
throw new Error('network error or something')
},
}),
}
const resolver = new ResolveNom({ ens: mockEns })
const resolutions = await resolver.resolve('foo.nom')

expect(resolutions.resolutions.length).toBe(0)
Expand Down
78 changes: 40 additions & 38 deletions src/resolve-nom.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,32 @@
import { Address } from '@celo/base/lib/address'
import { ContractKit } from '@celo/contractkit'
import { NomKit } from '@nomspace/nomspace'
import { NameResolver, NameResolutionResults, ResolutionKind } from './types'

import ENS from '@ensdomains/ensjs'
import { normalize } from 'eth-ens-namehash'
import { providers } from 'ethers'

const NullNomResolution = '0x0000000000000000000000000000000000000000'

export class ResolveNom implements NameResolver {
static readonly MainnetContractAddress: Address =
'0xABf8faBbC071F320F222A526A2e1fBE26429344d'
static readonly AlfajoresContractAddress: Address =
'0x36C976Da6A6499Cad683064F849afa69CD4dec2e'
static readonly ENSRegsitryAddress: Address =
'0x3DE51c3960400A0F752d3492652Ae4A0b2A36FB3'

private nomKit: NomKit
private ens: any

constructor({
kit,
contractAddress,
nomKit,
providerUrl,
ensRegistryAddress,
ens,
}: {
kit?: ContractKit
contractAddress?: Address
nomKit?: NomKit
providerUrl?: string
ensRegistryAddress?: Address
ens?: any
}) {
if (nomKit) {
this.nomKit = nomKit
} else if (kit && contractAddress) {
this.nomKit = new NomKit(kit, contractAddress)
if (ens) {
this.ens = ens
} else if (providerUrl && ensRegistryAddress) {
const provider = new providers.JsonRpcProvider(providerUrl)
this.ens = new ENS({ provider, ensAddress: ensRegistryAddress })
} else {
throw new Error('Missing kit and contractAddress')
}
Expand All @@ -38,36 +39,37 @@ export class ResolveNom implements NameResolver {
errors: [],
}
}

const name = id.substring(0, id.length - '.nom'.length)

// Only ids with fewer than 32 bytes are valid noms.
if (Buffer.byteLength(name, 'utf8') < 32) {
try {
const resolution = await this.nomKit.resolve(name)
if (resolution !== NullNomResolution) {
return {
resolutions: [
{
kind: ResolutionKind.Nom,
address: resolution,
name,
},
],
errors: [],
}
}
} catch (error) {
//
// https://docs.nom.space/dapp-developers/integrating-.nom-into-your-dapp
//
const normalName = normalize(name)
const ensName = this.ens.name(`${normalName}.nom`)
try {
const address = await ensName.getAddress()
if (address !== NullNomResolution) {
return {
resolutions: [],
errors: [
resolutions: [
{
kind: ResolutionKind.Nom,
error: error as Error,
address,
name,
},
],
errors: [],
}
}
} catch (error) {
return {
resolutions: [],
errors: [
{
kind: ResolutionKind.Nom,
error: error as Error,
},
],
}
}

return {
Expand Down
Loading

0 comments on commit 5500e28

Please sign in to comment.