func NewReverseAuction(buyer sdk.AccAddress, bid sdk.Coin, initialLot sdk.Coin, endTime endTime) (ReverseAuction, bankOutput) {
	auction := ReverseAuction{BaseAuction{
		Initiator:  buyer,
		Lot:        initialLot,
		Bidder:     buyer,  
		Bid:        bid,    
		EndTime:    endTime,
		MaxEndTime: endTime,
	}}
	output := bankOutput{buyer, initialLot}
	return auction, output
}
NewReverseAuction creates a new reverse auction
package auction
import (
	"fmt"
	"strconv"
	sdk "github.com/cosmos/cosmos-sdk/types"
)
const (
	MaxAuctionDuration endTime = 2 * 24 * 3600 / 5  
	BidDuration endTime = 3 * 3600 / 5  
)
type Auction interface {
	GetID() ID
	SetID(ID)
	PlaceBid(currentBlockHeight endTime, bidder sdk.AccAddress, lot sdk.Coin, bid sdk.Coin) ([]bankOutput, []bankInput, sdk.Error)
	GetEndTime() endTime  
	GetPayout() bankInput
	String() string
}
type BaseAuction struct {
	ID         ID
	Initiator  sdk.AccAddress  
	Lot        sdk.Coin        
	Bidder     sdk.AccAddress  
	Bid        sdk.Coin        
	EndTime    endTime         
	MaxEndTime endTime         
}
type ID uint64
func NewIDFromString(s string) (ID, error) {
	n, err := strconv.ParseUint(s, 10, 64)  
	if err != nil {
		return 0, err
	}
	return ID(n), nil
}
type endTime int64  
type bankInput struct {
	Address sdk.AccAddress
	Coin    sdk.Coin
}
type bankOutput struct {
	Address sdk.AccAddress
	Coin    sdk.Coin
}
func (a BaseAuction) GetID() ID { return a.ID }
func (a *BaseAuction) SetID(id ID) { a.ID = id }
func (a BaseAuction) GetEndTime() endTime { return a.EndTime }
func (a BaseAuction) GetPayout() bankInput {
	return bankInput{a.Bidder, a.Lot}
}
func (e endTime) String() string {
	return string(e)
}
func (a BaseAuction) String() string {
	return fmt.Sprintf(`Auction %d:
  Initiator:              %s
  Lot:               			%s
  Bidder:            		  %s
  Bid:        						%s
  End Time:   						%s
  Max End Time:      			%s`,
		a.GetID(), a.Initiator, a.Lot,
		a.Bidder, a.Bid, a.GetEndTime().String(),
		a.MaxEndTime.String(),
	)
}
type ForwardAuction struct {
	BaseAuction
}
func NewForwardAuction(seller sdk.AccAddress, lot sdk.Coin, initialBid sdk.Coin, endTime endTime) (ForwardAuction, bankOutput) {
	auction := ForwardAuction{BaseAuction{
		Initiator:  seller,
		Lot:        lot,
		Bidder:     seller,      
		Bid:        initialBid,  
		EndTime:    endTime,
		MaxEndTime: endTime,
	}}
	output := bankOutput{seller, lot}
	return auction, output
}
func (a *ForwardAuction) PlaceBid(currentBlockHeight endTime, bidder sdk.AccAddress, lot sdk.Coin, bid sdk.Coin) ([]bankOutput, []bankInput, sdk.Error) {
	if currentBlockHeight > a.EndTime {
		return []bankOutput{}, []bankInput{}, sdk.ErrInternal("auction has closed")
	}
	if !a.Bid.IsLT(bid) {  
		return []bankOutput{}, []bankInput{}, sdk.ErrInternal("bid not greater than last bid")
	}
	outputs := []bankOutput{{bidder, bid}}                                   
	inputs := []bankInput{{a.Bidder, a.Bid}, {a.Initiator, bid.Sub(a.Bid)}}  
	a.Bidder = bidder
	a.Bid = bid
	a.EndTime = endTime(min(int64(currentBlockHeight+BidDuration), int64(a.MaxEndTime)))  
	return outputs, inputs, nil
}
type ReverseAuction struct {
	BaseAuction
}