package client import ( "context" "fmt" "time" "github.com/tendermint/tendermint/internal/jsontypes" "github.com/tendermint/tendermint/rpc/coretypes" "github.com/tendermint/tendermint/types" ) // Waiter is informed of current height, decided whether to quit early type Waiter func(delta int64) (abort error) // DefaultWaitStrategy is the standard backoff algorithm, // but you can plug in another one func DefaultWaitStrategy(delta int64) (abort error) { if delta > 10 { return fmt.Errorf("waiting for %d blocks... aborting", delta) } else if delta > 0 { // estimate of wait time.... // wait half a second for the next block (in progress) // plus one second for every full block delay := time.Duration(delta-1)*time.Second + 500*time.Millisecond time.Sleep(delay) } return nil } // Wait for height will poll status at reasonable intervals until // the block at the given height is available. // // If waiter is nil, we use DefaultWaitStrategy, but you can also // provide your own implementation func WaitForHeight(ctx context.Context, c StatusClient, h int64, waiter Waiter) error { if waiter == nil { waiter = DefaultWaitStrategy } delta := int64(1) for delta > 0 { s, err := c.Status(ctx) if err != nil { return err } delta = h - s.SyncInfo.LatestBlockHeight // wait for the time, or abort early if err := waiter(delta); err != nil { return err } } return nil } // WaitForOneEvent waits for the first event matching the given query on c, or // until ctx ends. It reports an error if ctx ends before a matching event is // received. func WaitForOneEvent(ctx context.Context, c EventsClient, query string) (types.EventData, error) { for { rsp, err := c.Events(ctx, &coretypes.RequestEvents{ Filter: &coretypes.EventFilter{Query: query}, MaxItems: 1, WaitTime: 10 * time.Second, // duration doesn't matter, limited by ctx timeout }) if err != nil { return nil, err } else if len(rsp.Items) == 0 { continue // continue polling until ctx expires } var result types.EventData if err := jsontypes.Unmarshal(rsp.Items[0].Data, &result); err != nil { return nil, err } return result, nil } }