github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/mobile/ethclient.go (about)

     1  
     2  //<developer>
     3  //    <name>linapex 曹一峰</name>
     4  //    <email>linapex@163.com</email>
     5  //    <wx>superexc</wx>
     6  //    <qqgroup>128148617</qqgroup>
     7  //    <url>https://jsq.ink</url>
     8  //    <role>pku engineer</role>
     9  //    <date>2019-03-16 12:09:43</date>
    10  //</624342653747597312>
    11  
    12  
    13  //包含以太坊客户端的包装。
    14  
    15  package geth
    16  
    17  import (
    18  	"math/big"
    19  
    20  	"github.com/ethereum/go-ethereum/core/types"
    21  	"github.com/ethereum/go-ethereum/ethclient"
    22  )
    23  
    24  //以太坊客户端提供对以太坊API的访问。
    25  type EthereumClient struct {
    26  	client *ethclient.Client
    27  }
    28  
    29  //newethereumclient将客户机连接到给定的URL。
    30  func NewEthereumClient(rawurl string) (client *EthereumClient, _ error) {
    31  	rawClient, err := ethclient.Dial(rawurl)
    32  	return &EthereumClient{rawClient}, err
    33  }
    34  
    35  //GetBlockByHash返回给定的完整块。
    36  func (ec *EthereumClient) GetBlockByHash(ctx *Context, hash *Hash) (block *Block, _ error) {
    37  	rawBlock, err := ec.client.BlockByHash(ctx.context, hash.hash)
    38  	return &Block{rawBlock}, err
    39  }
    40  
    41  //GetBlockByNumber返回当前规范链中的块。如果数字小于0,则
    42  //返回最新的已知块。
    43  func (ec *EthereumClient) GetBlockByNumber(ctx *Context, number int64) (block *Block, _ error) {
    44  	if number < 0 {
    45  		rawBlock, err := ec.client.BlockByNumber(ctx.context, nil)
    46  		return &Block{rawBlock}, err
    47  	}
    48  	rawBlock, err := ec.client.BlockByNumber(ctx.context, big.NewInt(number))
    49  	return &Block{rawBlock}, err
    50  }
    51  
    52  //GetHeaderByHash返回具有给定哈希的块头。
    53  func (ec *EthereumClient) GetHeaderByHash(ctx *Context, hash *Hash) (header *Header, _ error) {
    54  	rawHeader, err := ec.client.HeaderByHash(ctx.context, hash.hash)
    55  	return &Header{rawHeader}, err
    56  }
    57  
    58  //GetHeaderByNumber返回当前规范链的块头。如果数字小于0,
    59  //返回最新的已知头。
    60  func (ec *EthereumClient) GetHeaderByNumber(ctx *Context, number int64) (header *Header, _ error) {
    61  	if number < 0 {
    62  		rawHeader, err := ec.client.HeaderByNumber(ctx.context, nil)
    63  		return &Header{rawHeader}, err
    64  	}
    65  	rawHeader, err := ec.client.HeaderByNumber(ctx.context, big.NewInt(number))
    66  	return &Header{rawHeader}, err
    67  }
    68  
    69  //GetTransactionByHash返回具有给定哈希的事务。
    70  func (ec *EthereumClient) GetTransactionByHash(ctx *Context, hash *Hash) (tx *Transaction, _ error) {
    71  //TODO(karalabe):句柄显示
    72  	rawTx, _, err := ec.client.TransactionByHash(ctx.context, hash.hash)
    73  	return &Transaction{rawTx}, err
    74  }
    75  
    76  //GetTransactionSsender返回事务的发件人地址。交易必须
    77  //在给定的块和索引中包含在区块链中。
    78  func (ec *EthereumClient) GetTransactionSender(ctx *Context, tx *Transaction, blockhash *Hash, index int) (sender *Address, _ error) {
    79  	addr, err := ec.client.TransactionSender(ctx.context, tx.tx, blockhash.hash, uint(index))
    80  	return &Address{addr}, err
    81  }
    82  
    83  //GetTransactionCount返回给定块中的事务总数。
    84  func (ec *EthereumClient) GetTransactionCount(ctx *Context, hash *Hash) (count int, _ error) {
    85  	rawCount, err := ec.client.TransactionCount(ctx.context, hash.hash)
    86  	return int(rawCount), err
    87  }
    88  
    89  //GetTransactionInBlock返回给定块中索引处的单个事务。
    90  func (ec *EthereumClient) GetTransactionInBlock(ctx *Context, hash *Hash, index int) (tx *Transaction, _ error) {
    91  	rawTx, err := ec.client.TransactionInBlock(ctx.context, hash.hash, uint(index))
    92  	return &Transaction{rawTx}, err
    93  
    94  }
    95  
    96  //GetTransactionReceipt按事务哈希返回事务的接收。
    97  //请注意,收据不可用于待处理的交易。
    98  func (ec *EthereumClient) GetTransactionReceipt(ctx *Context, hash *Hash) (receipt *Receipt, _ error) {
    99  	rawReceipt, err := ec.client.TransactionReceipt(ctx.context, hash.hash)
   100  	return &Receipt{rawReceipt}, err
   101  }
   102  
   103  //SyncProgress检索同步算法的当前进度。如果有
   104  //当前没有运行同步,它返回零。
   105  func (ec *EthereumClient) SyncProgress(ctx *Context) (progress *SyncProgress, _ error) {
   106  	rawProgress, err := ec.client.SyncProgress(ctx.context)
   107  	if rawProgress == nil {
   108  		return nil, err
   109  	}
   110  	return &SyncProgress{*rawProgress}, err
   111  }
   112  
   113  //NewHeadHandler是一个客户端订阅回调,用于在事件和
   114  //订阅失败。
   115  type NewHeadHandler interface {
   116  	OnNewHead(header *Header)
   117  	OnError(failure string)
   118  }
   119  
   120  //订阅订阅当前区块链头的通知
   121  //在给定的频道上。
   122  func (ec *EthereumClient) SubscribeNewHead(ctx *Context, handler NewHeadHandler, buffer int) (sub *Subscription, _ error) {
   123  //在内部订阅事件
   124  	ch := make(chan *types.Header, buffer)
   125  	rawSub, err := ec.client.SubscribeNewHead(ctx.context, ch)
   126  	if err != nil {
   127  		return nil, err
   128  	}
   129  //启动一个调度器以反馈回拨
   130  	go func() {
   131  		for {
   132  			select {
   133  			case header := <-ch:
   134  				handler.OnNewHead(&Header{header})
   135  
   136  			case err := <-rawSub.Err():
   137  				handler.OnError(err.Error())
   138  				return
   139  			}
   140  		}
   141  	}()
   142  	return &Subscription{rawSub}, nil
   143  }
   144  
   145  //状态访问
   146  
   147  //getbalanceat返回给定帐户的wei余额。
   148  //块编号可以小于0,在这种情况下,余额取自最新的已知块。
   149  func (ec *EthereumClient) GetBalanceAt(ctx *Context, account *Address, number int64) (balance *BigInt, _ error) {
   150  	if number < 0 {
   151  		rawBalance, err := ec.client.BalanceAt(ctx.context, account.address, nil)
   152  		return &BigInt{rawBalance}, err
   153  	}
   154  	rawBalance, err := ec.client.BalanceAt(ctx.context, account.address, big.NewInt(number))
   155  	return &BigInt{rawBalance}, err
   156  }
   157  
   158  //GetStorageAt返回给定帐户的合同存储中密钥的值。
   159  //块编号可以小于0,在这种情况下,该值取自最新的已知块。
   160  func (ec *EthereumClient) GetStorageAt(ctx *Context, account *Address, key *Hash, number int64) (storage []byte, _ error) {
   161  	if number < 0 {
   162  		return ec.client.StorageAt(ctx.context, account.address, key.hash, nil)
   163  	}
   164  	return ec.client.StorageAt(ctx.context, account.address, key.hash, big.NewInt(number))
   165  }
   166  
   167  //getcodeat返回给定帐户的合同代码。
   168  //块编号可以小于0,在这种情况下,代码取自最新的已知块。
   169  func (ec *EthereumClient) GetCodeAt(ctx *Context, account *Address, number int64) (code []byte, _ error) {
   170  	if number < 0 {
   171  		return ec.client.CodeAt(ctx.context, account.address, nil)
   172  	}
   173  	return ec.client.CodeAt(ctx.context, account.address, big.NewInt(number))
   174  }
   175  
   176  //getnonceat返回给定帐户的nonce帐户。
   177  //块号可以小于0,在这种情况下,nonce是从最新的已知块中获取的。
   178  func (ec *EthereumClient) GetNonceAt(ctx *Context, account *Address, number int64) (nonce int64, _ error) {
   179  	if number < 0 {
   180  		rawNonce, err := ec.client.NonceAt(ctx.context, account.address, nil)
   181  		return int64(rawNonce), err
   182  	}
   183  	rawNonce, err := ec.client.NonceAt(ctx.context, account.address, big.NewInt(number))
   184  	return int64(rawNonce), err
   185  }
   186  
   187  //过滤器
   188  
   189  //filterlogs执行筛选器查询。
   190  func (ec *EthereumClient) FilterLogs(ctx *Context, query *FilterQuery) (logs *Logs, _ error) {
   191  	rawLogs, err := ec.client.FilterLogs(ctx.context, query.query)
   192  	if err != nil {
   193  		return nil, err
   194  	}
   195  //由于vm.logs为[]*vm.log,临时黑客
   196  	res := make([]*types.Log, len(rawLogs))
   197  	for i := range rawLogs {
   198  		res[i] = &rawLogs[i]
   199  	}
   200  	return &Logs{res}, nil
   201  }
   202  
   203  //filterlogshandler是一个客户端订阅回调,用于在事件和
   204  //订阅失败。
   205  type FilterLogsHandler interface {
   206  	OnFilterLogs(log *Log)
   207  	OnError(failure string)
   208  }
   209  
   210  //subscribeFilterLogs订阅流式筛选查询的结果。
   211  func (ec *EthereumClient) SubscribeFilterLogs(ctx *Context, query *FilterQuery, handler FilterLogsHandler, buffer int) (sub *Subscription, _ error) {
   212  //在内部订阅事件
   213  	ch := make(chan types.Log, buffer)
   214  	rawSub, err := ec.client.SubscribeFilterLogs(ctx.context, query.query, ch)
   215  	if err != nil {
   216  		return nil, err
   217  	}
   218  //启动一个调度器以反馈回拨
   219  	go func() {
   220  		for {
   221  			select {
   222  			case log := <-ch:
   223  				handler.OnFilterLogs(&Log{&log})
   224  
   225  			case err := <-rawSub.Err():
   226  				handler.OnError(err.Error())
   227  				return
   228  			}
   229  		}
   230  	}()
   231  	return &Subscription{rawSub}, nil
   232  }
   233  
   234  //预备状态
   235  
   236  //getPendingBalanceAt返回处于挂起状态的给定帐户的wei余额。
   237  func (ec *EthereumClient) GetPendingBalanceAt(ctx *Context, account *Address) (balance *BigInt, _ error) {
   238  	rawBalance, err := ec.client.PendingBalanceAt(ctx.context, account.address)
   239  	return &BigInt{rawBalance}, err
   240  }
   241  
   242  //GetPendingStorageAt返回处于挂起状态的给定帐户的合同存储中键的值。
   243  func (ec *EthereumClient) GetPendingStorageAt(ctx *Context, account *Address, key *Hash) (storage []byte, _ error) {
   244  	return ec.client.PendingStorageAt(ctx.context, account.address, key.hash)
   245  }
   246  
   247  //GetPendingCodeAt返回处于挂起状态的给定帐户的合同代码。
   248  func (ec *EthereumClient) GetPendingCodeAt(ctx *Context, account *Address) (code []byte, _ error) {
   249  	return ec.client.PendingCodeAt(ctx.context, account.address)
   250  }
   251  
   252  //GetPendingOnCate返回处于挂起状态的给定帐户的帐户nonce。
   253  //这是应该用于下一个事务的nonce。
   254  func (ec *EthereumClient) GetPendingNonceAt(ctx *Context, account *Address) (nonce int64, _ error) {
   255  	rawNonce, err := ec.client.PendingNonceAt(ctx.context, account.address)
   256  	return int64(rawNonce), err
   257  }
   258  
   259  //GetPendingtTransactionCount返回处于挂起状态的事务总数。
   260  func (ec *EthereumClient) GetPendingTransactionCount(ctx *Context) (count int, _ error) {
   261  	rawCount, err := ec.client.PendingTransactionCount(ctx.context)
   262  	return int(rawCount), err
   263  }
   264  
   265  //合同呼叫
   266  
   267  //CallContract执行消息调用事务,该事务直接在VM中执行
   268  //但从未开发到区块链中。
   269  //
   270  //BlockNumber选择运行调用的块高度。它可以小于0,其中
   271  //如果代码取自最新的已知块。注意这个状态从很老
   272  //块可能不可用。
   273  func (ec *EthereumClient) CallContract(ctx *Context, msg *CallMsg, number int64) (output []byte, _ error) {
   274  	if number < 0 {
   275  		return ec.client.CallContract(ctx.context, msg.msg, nil)
   276  	}
   277  	return ec.client.CallContract(ctx.context, msg.msg, big.NewInt(number))
   278  }
   279  
   280  //PendingCallContract使用EVM执行消息调用事务。
   281  //合同调用所看到的状态是挂起状态。
   282  func (ec *EthereumClient) PendingCallContract(ctx *Context, msg *CallMsg) (output []byte, _ error) {
   283  	return ec.client.PendingCallContract(ctx.context, msg.msg)
   284  }
   285  
   286  //SuggestGasprice检索当前建议的天然气价格,以便及时
   287  //交易的执行。
   288  func (ec *EthereumClient) SuggestGasPrice(ctx *Context) (price *BigInt, _ error) {
   289  	rawPrice, err := ec.client.SuggestGasPrice(ctx.context)
   290  	return &BigInt{rawPrice}, err
   291  }
   292  
   293  //EstimateGas试图根据
   294  //后端区块链的当前挂起状态。不能保证这是
   295  //矿工可能增加或移除的其他交易的实际气体限制要求,
   296  //但它应为设定合理违约提供依据。
   297  func (ec *EthereumClient) EstimateGas(ctx *Context, msg *CallMsg) (gas int64, _ error) {
   298  	rawGas, err := ec.client.EstimateGas(ctx.context, msg.msg)
   299  	return int64(rawGas), err
   300  }
   301  
   302  //sendTransaction将签名的事务注入挂起池以执行。
   303  //
   304  //如果事务是合同创建,请使用TransactionReceipt方法获取
   305  //挖掘交易记录后的合同地址。
   306  func (ec *EthereumClient) SendTransaction(ctx *Context, tx *Transaction) error {
   307  	return ec.client.SendTransaction(ctx.context, tx.tx)
   308  }
   309