func (s *Service) ProposerDutiesForSlotRange(ctx context.Context,
	startSlot phase0.Slot,
	endSlot phase0.Slot,
) (
	[]*chaindb.ProposerDuty,
	error,
) {
	tx := s.tx(ctx)
	if tx == nil {
		ctx, cancel, err := s.BeginTx(ctx)
		if err != nil {
			return nil, errors.Wrap(err, "failed to begin transaction")
		}
		tx = s.tx(ctx)
		defer cancel()
	}
	rows, err := tx.Query(ctx, `
      SELECT f_slot
            ,f_validator_index
      FROM t_proposer_duties
      WHERE f_slot >= $1
        AND f_slot < $2
      ORDER BY f_slot`,
		startSlot,
		endSlot,
	)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	proposerDuties := make([]*chaindb.ProposerDuty, 0)
	for rows.Next() {
		proposerDuty := &chaindb.ProposerDuty{}
		err := rows.Scan(
			&proposerDuty.Slot,
			&proposerDuty.ValidatorIndex,
		)
		if err != nil {
			return nil, errors.Wrap(err, "failed to scan row")
		}
		proposerDuties = append(proposerDuties, proposerDuty)
	}
	return proposerDuties, nil
}
ProposerDutiesForSlotRange fetches all proposer duties for a slot range.
package postgresql
import (
	"context"
	"github.com/attestantio/go-eth2-client/spec/phase0"
	"github.com/pkg/errors"
	"github.com/wealdtech/chaind/services/chaindb"
)
func (s *Service) SetProposerDuty(ctx context.Context, proposerDuty *chaindb.ProposerDuty) error {
	tx := s.tx(ctx)
	if tx == nil {
		return ErrNoTransaction
	}
	_, err := tx.Exec(ctx, `
      INSERT INTO t_proposer_duties(f_slot
                                   ,f_validator_index)
      VALUES($1,$2)
      ON CONFLICT (f_slot) DO
      UPDATE
      SET f_validator_index = excluded.f_validator_index
		 `,
		proposerDuty.Slot,
		proposerDuty.ValidatorIndex,
	)
	return err
}