github.com/noirx94/tendermintmp@v0.0.1/rpc/client/helpers.go (about) 1 package client 2 3 import ( 4 "context" 5 "errors" 6 "fmt" 7 "time" 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 fmt.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(context.Background()) 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 52 return nil 53 } 54 55 // WaitForOneEvent subscribes to a websocket event for the given 56 // event time and returns upon receiving it one time, or 57 // when the timeout duration has expired. 58 // 59 // This handles subscribing and unsubscribing under the hood 60 func WaitForOneEvent(c EventsClient, evtTyp string, timeout time.Duration) (types.TMEventData, error) { 61 const subscriber = "helpers" 62 ctx, cancel := context.WithTimeout(context.Background(), timeout) 63 defer cancel() 64 65 // register for the next event of this type 66 eventCh, err := c.Subscribe(ctx, subscriber, types.QueryForEvent(evtTyp).String()) 67 if err != nil { 68 return nil, fmt.Errorf("failed to subscribe: %w", err) 69 } 70 // make sure to unregister after the test is over 71 defer func() { 72 if deferErr := c.UnsubscribeAll(ctx, subscriber); deferErr != nil { 73 panic(err) 74 } 75 }() 76 77 select { 78 case event := <-eventCh: 79 return event.Data.(types.TMEventData), nil 80 case <-ctx.Done(): 81 return nil, errors.New("timed out waiting for event") 82 } 83 }