Skip to content

Commit

Permalink
Basic registry functions
Browse files Browse the repository at this point in the history
  • Loading branch information
jefflau committed Sep 18, 2020
1 parent b4b9f1f commit 292b637
Show file tree
Hide file tree
Showing 12 changed files with 3,462 additions and 422 deletions.
Binary file modified .DS_Store
Binary file not shown.
8 changes: 5 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
"@babel/plugin-transform-spread": "^7.2.2",
"@babel/polyfill": "^7.4.4",
"@babel/preset-env": "^7.4.4",
"@ensdomains/mock": "^1.0.13",
"@ensdomains/mock": "^2.0.22",
"babel-eslint": "^9.0.0",
"babel-jest": "^23.6.0",
"babel-jest-assertions": "^0.1.0",
Expand All @@ -42,13 +42,15 @@
"esm": "^3.2.22",
"ganache-cli": "^6.4.3",
"ganache-core": "^2.11.3",
"jest": "^24.8.0"
"jest": "^24.8.0",
"web3": "^1.2.11"
},
"dependencies": {
"@babel/runtime": "^7.4.4",
"@ensdomains/ens": "^0.3.5",
"@ensdomains/ens": "0.4.3",
"@ensdomains/resolver": "^0.1.6",
"eth-ens-namehash": "^2.0.8",
"ethers": "^5.0.13",
"js-sha3": "^0.8.0"
}
}
Binary file modified src/.DS_Store
Binary file not shown.
465 changes: 257 additions & 208 deletions src/__tests__/ens.test.js

Large diffs are not rendered by default.

93 changes: 77 additions & 16 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { ethers } from 'ethers'
import { namehash } from './utils/namehash'
import { abi as ensContract } from '@ensdomains/ens/build/contracts/ENS.json'
import { abi as resolverContract } from '@ensdomains/resolver/build/contracts/Resolver.json'

import { emptyAddress, namehash, labelhash } from './utils'

let registries = {
1: '0x314159265dd8dbb310642f98f50c066173c1259b',
3: '0x112234455c3a32fd11230c42e7bccd4a84e02010',
Expand All @@ -16,60 +17,120 @@ async function getNetworkId() {
return web3.eth.net.getId()
}

async function getResolverContract({ address, provider }) {
function getResolverContract({ address, provider }) {
return new ethers.Contract(address, resolverContract, provider)
}

async function getENSContract({ address, provider }) {
function getENSContract({ address, provider }) {
console.log(address, provider, ensContract)
return new ethers.Contract(address, ensContract, provider)
}

class Resolver {
constructor(address, ENS) {
//TODO
constructor({ address, ens }) {
this.address = address
this.ens = ens
}
}

class Name {
constructor(options) {
const { name, ens, provider } = options
const { name, ens, provider, signer, namehash: nh } = options
if (options.namehash) {
this.namehash = nh
}
this.ens = ens
this.ensWithSigner = this.ens.connect(signer)
this.name = name
this.namehash = namehash(name)
this.signer = signer
}

getAddr() {
async getAddr() {
return
}

getOwner() {
return this.ens.owner(namehash(name))
async getOwner() {
return this.ens.owner(this.namehash)
}

async getResolver() {
return this.ens.resolver(this.namehash)
}

async getTTL(name) {
return this.ens.ttl(this.namehash)
}

async setResolver(address) {
if (!address) throw new Error('No resolver address provided!')
return this.ensWithSigner.setResolver(this.namehash, address)
}

async setOwner(address) {
if (!address) throw new Error('No newOwner address provided!')
return this.ensWithSigner.setOwner(this.namehash, address)
}

async setSubnodeOwner(label, newOwner) {
const lh = labelhash(label)
return this.ensWithSigner.setSubnodeOwner(this.namehash, lh, newOwner)
}

async setSubnodeRecord(label, newOwner, resolver, ttl = 0) {
const lh = labelhash(label)
return this.ensWithSigner.setSubnodeRecord(
this.namehash,
lh,
newOwner,
resolver,
ttl
)
}

async createSubdomain(label) {
const resolverPromise = this.getResolver()
const ownerPromise = this.getOwner()
const [resolver, owner] = await Promise.all([resolverPromise, ownerPromise])
return this.setSubnodeRecord(label, owner, resolver)
}

async deleteSubdomain(label) {
return this.setSubnodeRecord(label, emptyAddress, emptyAddress)
}
}

export default class ENS {
constructor(options) {
const { networkId, provider, ensAddress } = options
this.provider = new ethers.providers.Web3Provider(provider)
const ethersProvider = new ethers.providers.Web3Provider(provider)
this.provider = ethersProvider
this.signer = ethersProvider.getSigner()
this.ens = getENSContract({
address: ensAddress ? ensAddress : registries[networkId],
provider: this.provider,
provider: ethersProvider,
})
}

getName(name) {
name(name) {
return new Name({
name,
ens: this.ens,
provider: this.provider,
signer: this.signer,
})
}
getResolver(address) {
return new Resolver(address)
resolver(address) {
return new Resolver({ ens: this.ens, provider: this.provider })
}

getReverseRecord() {}
setReverseRecord() {}
getReverseRecord() {
//TODO
}
setReverseRecord() {
//TODO
}
}

export { namehash }
export { namehash, labelhash, getENSContract }
103 changes: 103 additions & 0 deletions src/utils/contents.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import contentHash from 'content-hash'
import { ethers } from 'ethers'
import bs58 from 'bs58'
const supportedCodecs = ['ipns-ns', 'ipfs-ns', 'swarm-ns', 'onion', 'onion3']

const utils = ethers.utils

export function decodeContenthash(encoded) {
let decoded, protocolType, error
if (encoded.error) {
return { protocolType: null, decoded: encoded.error }
}
if (encoded) {
try {
decoded = contentHash.decode(encoded)
const codec = contentHash.getCodec(encoded)
if (codec === 'ipfs-ns') {
protocolType = 'ipfs'
} else if (codec === 'ipns-ns') {
decoded = bs58.decode(decoded).slice(2).toString()
protocolType = 'ipns'
} else if (codec === 'swarm-ns') {
protocolType = 'bzz'
} else if (codec === 'onion') {
protocolType = 'onion'
} else if (codec === 'onion3') {
protocolType = 'onion3'
} else {
decoded = encoded
}
} catch (e) {
error = e.message
}
}
return { protocolType, decoded, error }
}

export function validateContent(encoded) {
return (
contentHash.isHashOfType(encoded, contentHash.Types.ipfs) ||
contentHash.isHashOfType(encoded, contentHash.Types.swarm)
)
}

export function isValidContenthash(encoded) {
try {
const codec = contentHash.getCodec(encoded)
return utils.isHexString(encoded) && supportedCodecs.includes(codec)
} catch (e) {
console.log(e)
}
}

export function encodeContenthash(text) {
let content, contentType
let encoded = false
if (!!text) {
let matched =
text.match(/^(ipfs|ipns|bzz|onion|onion3):\/\/(.*)/) ||
text.match(/\/(ipfs)\/(.*)/) ||
text.match(/\/(ipns)\/(.*)/)
if (matched) {
contentType = matched[1]
content = matched[2]
}
try {
if (contentType === 'ipfs') {
if (content.length >= 4) {
encoded = '0x' + contentHash.encode('ipfs-ns', content)
}
} else if (contentType === 'ipns') {
let bs58content = bs58.encode(
Buffer.concat([
Buffer.from([0, content.length]),
Buffer.from(content),
])
)
encoded = '0x' + contentHash.encode('ipns-ns', bs58content)
} else if (contentType === 'bzz') {
if (content.length >= 4) {
encoded = '0x' + contentHash.fromSwarm(content)
}
} else if (contentType === 'onion') {
if (content.length == 16) {
encoded = '0x' + contentHash.encode('onion', content)
}
} else if (contentType === 'onion3') {
if (content.length == 56) {
encoded = '0x' + contentHash.encode('onion3', content)
}
} else {
console.warn('Unsupported protocol or invalid value', {
contentType,
text,
})
}
} catch (err) {
console.warn('Error encoding content hash', { text, encoded })
//throw 'Error encoding content hash'
}
}
return encoded
}

0 comments on commit 292b637

Please sign in to comment.