github.com/Aodurkeen/go-ubiq@v2.3.0+incompatible/contracts/ens/ens.go (about)

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