github.com/vipernet-xyz/tendermint-core@v0.32.0/rpc/client/helpers.go (about) 1 package client 2 3 import ( 4 "context" 5 "time" 6 7 "github.com/pkg/errors" 8 9 "github.com/tendermint/tendermint/types" 10 ) 11 12 // Waiter is informed of current height, decided whether to quit early 13 type Waiter func(delta int64) (abort error) 14 15 // DefaultWaitStrategy is the standard backoff algorithm, 16 // but you can plug in another one 17 func DefaultWaitStrategy(delta int64) (abort error) { 18 if delta > 10 { 19 return errors.Errorf("waiting for %d blocks... aborting", delta) 20 } else if delta > 0 { 21 // estimate of wait time.... 22 // wait half a second for the next block (in progress) 23 // plus one second for every full block 24 delay := time.Duration(delta-1)*time.Second + 500*time.Millisecond 25 time.Sleep(delay) 26 } 27 return nil 28 } 29 30 // Wait for height will poll status at reasonable intervals until 31 // the block at the given height is available. 32 // 33 // If waiter is nil, we use DefaultWaitStrategy, but you can also 34 // provide your own implementation 35 func WaitForHeight(c StatusClient, h int64, waiter Waiter) error { 36 if waiter == nil { 37 waiter = DefaultWaitStrategy 38 } 39 delta := int64(1) 40 for delta > 0 { 41 s, err := c.Status() 42 if err != nil { 43 return err 44 } 45 delta = h - s.SyncInfo.LatestBlockHeight 46 // wait for the time, or abort early 47 if err := waiter(delta); err != nil { 48 return err 49 } 50 } 51 return nil 52 } 53 54 // WaitForOneEvent subscribes to a websocket event for the given 55 // event time and returns upon receiving it one time, or 56 // when the timeout duration has expired. 57 // 58 // This handles subscribing and unsubscribing under the hood 59 func WaitForOneEvent(c EventsClient, evtTyp string, timeout time.Duration) (types.TMEventData, error) { 60 const subscriber = "helpers" 61 ctx, cancel := context.WithTimeout(context.Background(), timeout) 62 defer cancel() 63 64 // register for the next event of this type 65 eventCh, err := c.Subscribe(ctx, subscriber, types.QueryForEvent(evtTyp).String()) 66 if err != nil { 67 return nil, errors.Wrap(err, "failed to subscribe") 68 } 69 // make sure to unregister after the test is over 70 defer c.UnsubscribeAll(ctx, subscriber) 71 72 select { 73 case event := <-eventCh: 74 return event.Data.(types.TMEventData), nil 75 case <-ctx.Done(): 76 return nil, errors.New("timed out waiting for event") 77 } 78 }