github.com/zhiqiangxu/go-ethereum@v1.9.16-0.20210824055606-be91cfdebc48/rpc/client_example_test.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 rpc_test
    18  
    19  import (
    20  	"context"
    21  	"fmt"
    22  	"time"
    23  
    24  	"github.com/zhiqiangxu/go-ethereum/common/hexutil"
    25  	"github.com/zhiqiangxu/go-ethereum/rpc"
    26  )
    27  
    28  // In this example, our client wishes to track the latest 'block number'
    29  // known to the server. The server supports two methods:
    30  //
    31  // eth_getBlockByNumber("latest", {})
    32  //    returns the latest block object.
    33  //
    34  // eth_subscribe("newHeads")
    35  //    creates a subscription which fires block objects when new blocks arrive.
    36  
    37  type Block struct {
    38  	Number *hexutil.Big
    39  }
    40  
    41  func ExampleClientSubscription() {
    42  	// Connect the client.
    43  	client, _ := rpc.Dial("ws://127.0.0.1:8545")
    44  	subch := make(chan Block)
    45  
    46  	// Ensure that subch receives the latest block.
    47  	go func() {
    48  		for i := 0; ; i++ {
    49  			if i > 0 {
    50  				time.Sleep(2 * time.Second)
    51  			}
    52  			subscribeBlocks(client, subch)
    53  		}
    54  	}()
    55  
    56  	// Print events from the subscription as they arrive.
    57  	for block := range subch {
    58  		fmt.Println("latest block:", block.Number)
    59  	}
    60  }
    61  
    62  // subscribeBlocks runs in its own goroutine and maintains
    63  // a subscription for new blocks.
    64  func subscribeBlocks(client *rpc.Client, subch chan Block) {
    65  	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
    66  	defer cancel()
    67  
    68  	// Subscribe to new blocks.
    69  	sub, err := client.EthSubscribe(ctx, subch, "newHeads")
    70  	if err != nil {
    71  		fmt.Println("subscribe error:", err)
    72  		return
    73  	}
    74  
    75  	// The connection is established now.
    76  	// Update the channel with the current block.
    77  	var lastBlock Block
    78  	err = client.CallContext(ctx, &lastBlock, "eth_getBlockByNumber", "latest", false)
    79  	if err != nil {
    80  		fmt.Println("can't get latest block:", err)
    81  		return
    82  	}
    83  	subch <- lastBlock
    84  
    85  	// The subscription will deliver events to the channel. Wait for the
    86  	// subscription to end for any reason, then loop around to re-establish
    87  	// the connection.
    88  	fmt.Println("connection lost: ", <-sub.Err())
    89  }