func NewAPIErrTxTimedOut(err error, txType, txID, txTimeout string) APIError {
	message := fmt.Sprintf("timed out waiting for %s tx (ID:%s) to be mined in %s: %v", txType, txID, txTimeout, err)
	return NewAPIErr(
		ProtocolFatalError,
		ErrTxTimedOut,
		errors.WithMessage(err, message),
		ErrInfoTxTimedOut{
			TxType:    txType,
			TxID:      txID,
			TxTimeout: txTimeout,
		},
	)
}
NewAPIErrTxTimedOut returns an ErrTxTimedOut API Error with the given
error message.
package perun
import (
	"fmt"
	"io"
	"github.com/pkg/errors"
)
type apiError struct {
	category ErrorCategory
	code     ErrorCode
	err      error
	addInfo  interface{}
}
func (e apiError) Category() ErrorCategory { return e.category }
func (e apiError) Code() ErrorCode { return e.code }
func (e apiError) Message() string { return e.err.Error() }
func (e apiError) AddInfo() interface{} {
	return e.addInfo
}
func (e apiError) Error() string {
	return fmt.Sprintf("%s %d:%v", e.Category(), e.Code(), e.Message())
}
func (e apiError) Format(s fmt.State, verb rune) {
	switch verb {
	case 'v':
		if s.Flag('+') {
			fmt.Fprintf(s, "%s %d:%+v", e.Category(), e.Code(), e.err)
			return
		}
		fallthrough
	case 's':
		io.WriteString(s, e.Error())
	case 'q':
		fmt.Fprintf(s, "%q", e.Error())
	}
}
func (e apiError) Cause() error { return e.err }
func (e apiError) Unwrap() error { return e.err }
func NewAPIErr(category ErrorCategory, code ErrorCode, err error, addInfo interface{}) APIError {
	return apiError{
		category: category,
		code:     code,
		err:      err,
		addInfo:  addInfo,
	}
}
func NewAPIErrPeerRequestTimedOut(err error, peerAlias, timeout string) APIError {
	message := fmt.Sprintf("timed out waiting for response from %s for %s", peerAlias, timeout)
	return NewAPIErr(
		ParticipantError,
		ErrPeerRequestTimedOut,
		errors.WithMessage(err, message),
		ErrInfoPeerRequestTimedOut{
			PeerAlias: peerAlias,
			Timeout:   timeout,
		},
	)
}
func NewAPIErrPeerRejected(err error, peerAlias, reason string) APIError {
	message := fmt.Sprintf("peer %s rejected with reason %s", peerAlias, reason)
	return NewAPIErr(
		ParticipantError,
		ErrPeerRejected,
		errors.WithMessage(err, message),
		ErrInfoPeerRejected{
			PeerAlias: peerAlias,
			Reason:    reason,
		},
	)
}
func NewAPIErrPeerNotFunded(err error, peerAlias string) APIError {
	message := fmt.Sprintf("peer %s did not fund within expected time", peerAlias)
	return NewAPIErr(
		ParticipantError,
		ErrPeerNotFunded,
		errors.WithMessage(err, message),
		ErrInfoPeerNotFunded{
			PeerAlias: peerAlias,
		},
	)
}
func NewAPIErrUserResponseTimedOut(expiry, receivedAt int64) APIError {
	message := fmt.Sprintf("response received (at %v) after timeout expired (at %v)", receivedAt, expiry)
	return NewAPIErr(
		ParticipantError,
		ErrUserResponseTimedOut,
		errors.New(message),
		ErrInfoUserResponseTimedOut{
			Expiry:     expiry,
			ReceivedAt: receivedAt,
		},
	)
}
type ResourceType string
func NewAPIErrResourceNotFound(resourceType ResourceType, resourceID string) APIError {
	message := fmt.Sprintf("cannot find %s with ID: %s", resourceType, resourceID)
	return NewAPIErr(
		ClientError,
		ErrResourceNotFound,
		errors.New(message),
		ErrInfoResourceNotFound{
			Type: string(resourceType),
			ID:   resourceID,
		},
	)
}
func NewAPIErrResourceExists(resourceType ResourceType, resourceID string) APIError {
	message := fmt.Sprintf("%s with ID: %s already exists", resourceType, resourceID)
	return NewAPIErr(
		ClientError,
		ErrResourceExists,
		errors.New(message),
		ErrInfoResourceExists{
			Type: string(resourceType),
			ID:   resourceID,
		},
	)
}
type ArgumentName string
func NewAPIErrInvalidArgument(err error, name ArgumentName, value string) APIError {
	message := fmt.Sprintf("invalid value for %s: %s", name, value)
	return NewAPIErr(
		ClientError,
		ErrInvalidArgument,
		errors.WithMessage(err, message),
		ErrInfoInvalidArgument{
			Name:  string(name),
			Value: value,
		},
	)
}
func NewAPIErrFailedPreCondition(err error) APIError {
	return newAPIErrFailedPreCondition(err, nil)
}
func NewAPIErrFailedPreConditionUnclosedChs(err error, chs []ChInfo) APIError {
	return newAPIErrFailedPreCondition(err,
		ErrInfoFailedPreCondUnclosedChs{
			ChInfos: chs,
		})
}
func newAPIErrFailedPreCondition(err error, addInfo interface{}) APIError {
	message := "failed pre-condition"
	return NewAPIErr(
		ClientError,
		ErrFailedPreCondition,
		errors.WithMessage(err, message),
		addInfo,
	)
}
func NewAPIErrInvalidConfig(err error, name, value string) APIError {
	message := fmt.Sprintf("invalid value for %s: %s", name, value)
	return NewAPIErr(
		ClientError,
		ErrInvalidConfig,
		errors.WithMessage(err, message),
		ErrInfoInvalidConfig{
			Name:  name,
			Value: value,
		},
	)
}
func NewAPIErrInvalidContracts(contractErrInfos ...ContractErrInfo) APIError {
	contractsErrInfosMsg := ""
	for _, c := range contractErrInfos {
		contractsErrInfosMsg += fmt.Sprintf("(%s at address %s: %v) ", c.Name, c.Address, c.Error)
	}
	message := "invalid contracts: " + contractsErrInfosMsg
	return NewAPIErr(
		ClientError,
		ErrInvalidContracts,
		errors.New(message),
		ErrInfoInvalidContracts{
			ContractErrInfos: contractErrInfos,
		},
	)
}