github.com/sberex/go-sberex@v1.8.2-0.20181113200658-ed96ac38f7d7/contracts/ens/ens.go (about) 1 // This file is part of the go-sberex library. The go-sberex library is 2 // free software: you can redistribute it and/or modify it under the terms 3 // of the GNU Lesser General Public License as published by the Free 4 // Software Foundation, either version 3 of the License, or (at your option) 5 // any later version. 6 // 7 // The go-sberex library is distributed in the hope that it will be useful, 8 // but WITHOUT ANY WARRANTY; without even the implied warranty of 9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser 10 // General Public License <http://www.gnu.org/licenses/> for more details. 11 12 package ens 13 14 //go:generate abigen --sol contract/ENS.sol --exc contract/AbstractENS.sol:AbstractENS --pkg contract --out contract/ens.go 15 //go:generate abigen --sol contract/FIFSRegistrar.sol --exc contract/AbstractENS.sol:AbstractENS --pkg contract --out contract/fifsregistrar.go 16 //go:generate abigen --sol contract/PublicResolver.sol --exc contract/AbstractENS.sol:AbstractENS --pkg contract --out contract/publicresolver.go 17 18 import ( 19 "strings" 20 21 "github.com/Sberex/go-sberex/accounts/abi/bind" 22 "github.com/Sberex/go-sberex/common" 23 "github.com/Sberex/go-sberex/contracts/ens/contract" 24 "github.com/Sberex/go-sberex/core/types" 25 "github.com/Sberex/go-sberex/crypto" 26 ) 27 28 var ( 29 MainNetAddress = common.HexToAddress("0x314159265dD8dbb310642f98f50C066173C1259b") 30 TestNetAddress = common.HexToAddress("0x112234455c3a32fd11230c42e7bccd4a84e02010") 31 ) 32 33 // swarm domain name registry and resolver 34 type ENS struct { 35 *contract.ENSSession 36 contractBackend bind.ContractBackend 37 } 38 39 // NewENS creates a struct exposing convenient high-level operations for interacting with 40 // the Sberex Name Service. 41 func NewENS(transactOpts *bind.TransactOpts, contractAddr common.Address, contractBackend bind.ContractBackend) (*ENS, error) { 42 ens, err := contract.NewENS(contractAddr, contractBackend) 43 if err != nil { 44 return nil, err 45 } 46 47 return &ENS{ 48 &contract.ENSSession{ 49 Contract: ens, 50 TransactOpts: *transactOpts, 51 }, 52 contractBackend, 53 }, nil 54 } 55 56 // DeployENS deploys an instance of the ENS nameservice, with a 'first-in, first-served' root registrar. 57 func DeployENS(transactOpts *bind.TransactOpts, contractBackend bind.ContractBackend) (common.Address, *ENS, error) { 58 // Deploy the ENS registry. 59 ensAddr, _, _, err := contract.DeployENS(transactOpts, contractBackend) 60 if err != nil { 61 return ensAddr, nil, err 62 } 63 64 ens, err := NewENS(transactOpts, ensAddr, contractBackend) 65 if err != nil { 66 return ensAddr, nil, err 67 } 68 69 // Deploy the registrar. 70 regAddr, _, _, err := contract.DeployFIFSRegistrar(transactOpts, contractBackend, ensAddr, [32]byte{}) 71 if err != nil { 72 return ensAddr, nil, err 73 } 74 // Set the registrar as owner of the ENS root. 75 if _, err = ens.SetOwner([32]byte{}, regAddr); err != nil { 76 return ensAddr, nil, err 77 } 78 79 return ensAddr, ens, nil 80 } 81 82 func ensParentNode(name string) (common.Hash, common.Hash) { 83 parts := strings.SplitN(name, ".", 2) 84 label := crypto.Keccak256Hash([]byte(parts[0])) 85 if len(parts) == 1 { 86 return [32]byte{}, label 87 } else { 88 parentNode, parentLabel := ensParentNode(parts[1]) 89 return crypto.Keccak256Hash(parentNode[:], parentLabel[:]), label 90 } 91 } 92 93 func ensNode(name string) common.Hash { 94 parentNode, parentLabel := ensParentNode(name) 95 return crypto.Keccak256Hash(parentNode[:], parentLabel[:]) 96 } 97 98 func (self *ENS) getResolver(node [32]byte) (*contract.PublicResolverSession, error) { 99 resolverAddr, err := self.Resolver(node) 100 if err != nil { 101 return nil, err 102 } 103 104 resolver, err := contract.NewPublicResolver(resolverAddr, self.contractBackend) 105 if err != nil { 106 return nil, err 107 } 108 109 return &contract.PublicResolverSession{ 110 Contract: resolver, 111 TransactOpts: self.TransactOpts, 112 }, nil 113 } 114 115 func (self *ENS) getRegistrar(node [32]byte) (*contract.FIFSRegistrarSession, error) { 116 registrarAddr, err := self.Owner(node) 117 if err != nil { 118 return nil, err 119 } 120 121 registrar, err := contract.NewFIFSRegistrar(registrarAddr, self.contractBackend) 122 if err != nil { 123 return nil, err 124 } 125 126 return &contract.FIFSRegistrarSession{ 127 Contract: registrar, 128 TransactOpts: self.TransactOpts, 129 }, nil 130 } 131 132 // Resolve is a non-transactional call that returns the content hash associated with a name. 133 func (self *ENS) Resolve(name string) (common.Hash, error) { 134 node := ensNode(name) 135 136 resolver, err := self.getResolver(node) 137 if err != nil { 138 return common.Hash{}, err 139 } 140 141 ret, err := resolver.Content(node) 142 if err != nil { 143 return common.Hash{}, err 144 } 145 146 return common.BytesToHash(ret[:]), nil 147 } 148 149 // Register registers a new domain name for the caller, making them the owner of the new name. 150 // Only works if the registrar for the parent domain implements the FIFS registrar protocol. 151 func (self *ENS) Register(name string) (*types.Transaction, error) { 152 parentNode, label := ensParentNode(name) 153 registrar, err := self.getRegistrar(parentNode) 154 if err != nil { 155 return nil, err 156 } 157 return registrar.Contract.Register(&self.TransactOpts, label, self.TransactOpts.From) 158 } 159 160 // SetContentHash sets the content hash associated with a name. Only works if the caller 161 // owns the name, and the associated resolver implements a `setContent` function. 162 func (self *ENS) SetContentHash(name string, hash common.Hash) (*types.Transaction, error) { 163 node := ensNode(name) 164 165 resolver, err := self.getResolver(node) 166 if err != nil { 167 return nil, err 168 } 169 170 opts := self.TransactOpts 171 opts.GasLimit = 200000 172 return resolver.Contract.SetContent(&opts, node, hash) 173 }