mirror of
				https://github.com/0glabs/0g-chain.git
				synced 2025-11-04 02:07:52 +00:00 
			
		
		
		
	feat: clean up pricefeed code
This commit is contained in:
		
							parent
							
								
									fd39cea7a5
								
							
						
					
					
						commit
						a6031172a1
					
				@ -1,8 +1,8 @@
 | 
			
		||||
// nolint
 | 
			
		||||
// autogenerated code using github.com/rigelrozanski/multitool
 | 
			
		||||
// aliases generated for the following subdirectories:
 | 
			
		||||
// ALIASGEN: github.com/kava-labs/kava/x/pricefeed/types/
 | 
			
		||||
// ALIASGEN: github.com/kava-labs/kava/x/pricefeed/keeper/
 | 
			
		||||
// ALIASGEN: github.com/kava-labs/kava/x/pricefeed/keeper
 | 
			
		||||
// ALIASGEN: github.com/kava-labs/kava/x/pricefeed/types
 | 
			
		||||
package pricefeed
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
@ -31,48 +31,54 @@ const (
 | 
			
		||||
	RouterKey                     = types.RouterKey
 | 
			
		||||
	QuerierRoute                  = types.QuerierRoute
 | 
			
		||||
	DefaultParamspace             = types.DefaultParamspace
 | 
			
		||||
	RawPriceFeedPrefix            = types.RawPriceFeedPrefix
 | 
			
		||||
	CurrentPricePrefix            = types.CurrentPricePrefix
 | 
			
		||||
	MarketPrefix                  = types.MarketPrefix
 | 
			
		||||
	OraclePrefix                  = types.OraclePrefix
 | 
			
		||||
	TypeMsgPostPrice              = types.TypeMsgPostPrice
 | 
			
		||||
	QueryPrice                    = types.QueryPrice
 | 
			
		||||
	QueryRawPrices                = types.QueryRawPrices
 | 
			
		||||
	QueryGetParams                = types.QueryGetParams
 | 
			
		||||
	QueryMarkets                  = types.QueryMarkets
 | 
			
		||||
	QueryOracles                  = types.QueryOracles
 | 
			
		||||
	QueryRawPrices                = types.QueryRawPrices
 | 
			
		||||
	QueryPrice                    = types.QueryPrice
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	// functions aliases
 | 
			
		||||
	RegisterCodec       = types.RegisterCodec
 | 
			
		||||
	ErrEmptyInput       = types.ErrEmptyInput
 | 
			
		||||
	ErrExpired          = types.ErrExpired
 | 
			
		||||
	ErrNoValidPrice     = types.ErrNoValidPrice
 | 
			
		||||
	ErrInvalidMarket    = types.ErrInvalidMarket
 | 
			
		||||
	ErrInvalidOracle    = types.ErrInvalidOracle
 | 
			
		||||
	NewGenesisState     = types.NewGenesisState
 | 
			
		||||
	DefaultGenesisState = types.DefaultGenesisState
 | 
			
		||||
	NewMsgPostPrice     = types.NewMsgPostPrice
 | 
			
		||||
	NewParams           = types.NewParams
 | 
			
		||||
	DefaultParams       = types.DefaultParams
 | 
			
		||||
	ParamKeyTable       = types.ParamKeyTable
 | 
			
		||||
	NewKeeper           = keeper.NewKeeper
 | 
			
		||||
	NewQuerier          = keeper.NewQuerier
 | 
			
		||||
	NewKeeper                  = keeper.NewKeeper
 | 
			
		||||
	NewQuerier                 = keeper.NewQuerier
 | 
			
		||||
	RegisterCodec              = types.RegisterCodec
 | 
			
		||||
	ErrEmptyInput              = types.ErrEmptyInput
 | 
			
		||||
	ErrExpired                 = types.ErrExpired
 | 
			
		||||
	ErrNoValidPrice            = types.ErrNoValidPrice
 | 
			
		||||
	ErrInvalidMarket           = types.ErrInvalidMarket
 | 
			
		||||
	ErrInvalidOracle           = types.ErrInvalidOracle
 | 
			
		||||
	NewGenesisState            = types.NewGenesisState
 | 
			
		||||
	DefaultGenesisState        = types.DefaultGenesisState
 | 
			
		||||
	CurrentPriceKey            = types.CurrentPriceKey
 | 
			
		||||
	RawPriceKey                = types.RawPriceKey
 | 
			
		||||
	NewCurrentPrice            = types.NewCurrentPrice
 | 
			
		||||
	NewPostedPrice             = types.NewPostedPrice
 | 
			
		||||
	NewMsgPostPrice            = types.NewMsgPostPrice
 | 
			
		||||
	NewParams                  = types.NewParams
 | 
			
		||||
	DefaultParams              = types.DefaultParams
 | 
			
		||||
	ParamKeyTable              = types.ParamKeyTable
 | 
			
		||||
	NewQueryWithMarketIDParams = types.NewQueryWithMarketIDParams
 | 
			
		||||
 | 
			
		||||
	// variable aliases
 | 
			
		||||
	ModuleCdc      = types.ModuleCdc
 | 
			
		||||
	KeyMarkets     = types.KeyMarkets
 | 
			
		||||
	DefaultMarkets = types.DefaultMarkets
 | 
			
		||||
	ModuleCdc          = types.ModuleCdc
 | 
			
		||||
	CurrentPricePrefix = types.CurrentPricePrefix
 | 
			
		||||
	RawPriceFeedPrefix = types.RawPriceFeedPrefix
 | 
			
		||||
	KeyMarkets         = types.KeyMarkets
 | 
			
		||||
	DefaultMarkets     = types.DefaultMarkets
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type (
 | 
			
		||||
	Keeper                  = keeper.Keeper
 | 
			
		||||
	GenesisState            = types.GenesisState
 | 
			
		||||
	Market                  = types.Market
 | 
			
		||||
	Markets                 = types.Markets
 | 
			
		||||
	CurrentPrice            = types.CurrentPrice
 | 
			
		||||
	PostedPrice             = types.PostedPrice
 | 
			
		||||
	PostedPrices            = types.PostedPrices
 | 
			
		||||
	SortDecs                = types.SortDecs
 | 
			
		||||
	MsgPostPrice            = types.MsgPostPrice
 | 
			
		||||
	Params                  = types.Params
 | 
			
		||||
	QueryWithMarketIDParams = types.QueryWithMarketIDParams
 | 
			
		||||
	Keeper                  = keeper.Keeper
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
@ -58,13 +58,9 @@ func (k Keeper) SetPrice(
 | 
			
		||||
		}
 | 
			
		||||
		// set the price for that particular oracle
 | 
			
		||||
		if found {
 | 
			
		||||
			prices[index] = types.PostedPrice{
 | 
			
		||||
				MarketID: marketID, OracleAddress: oracle,
 | 
			
		||||
				Price: price, Expiry: expiry}
 | 
			
		||||
			prices[index] = types.NewPostedPrice(marketID, oracle, price, expiry)
 | 
			
		||||
		} else {
 | 
			
		||||
			prices = append(prices, types.PostedPrice{
 | 
			
		||||
				MarketID: marketID, OracleAddress: oracle,
 | 
			
		||||
				Price: price, Expiry: expiry})
 | 
			
		||||
			prices = append(prices, types.NewPostedPrice(marketID, oracle, price, expiry))
 | 
			
		||||
			index = len(prices) - 1
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@ -79,7 +75,7 @@ func (k Keeper) SetPrice(
 | 
			
		||||
			),
 | 
			
		||||
		)
 | 
			
		||||
		store.Set(
 | 
			
		||||
			[]byte(types.RawPriceFeedPrefix+marketID), k.cdc.MustMarshalBinaryBare(prices),
 | 
			
		||||
			types.RawPriceKey(marketID), k.cdc.MustMarshalBinaryBare(prices),
 | 
			
		||||
		)
 | 
			
		||||
		return prices[index], nil
 | 
			
		||||
	}
 | 
			
		||||
@ -101,20 +97,17 @@ func (k Keeper) SetCurrentPrices(ctx sdk.Context, marketID string) sdk.Error {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	prices := k.GetRawPrices(ctx, marketID)
 | 
			
		||||
	var notExpiredPrices []types.CurrentPrice
 | 
			
		||||
	var notExpiredPrices types.CurrentPrices
 | 
			
		||||
	// filter out expired prices
 | 
			
		||||
	for _, v := range prices {
 | 
			
		||||
		if v.Expiry.After(ctx.BlockTime()) {
 | 
			
		||||
			notExpiredPrices = append(notExpiredPrices, types.CurrentPrice{
 | 
			
		||||
				MarketID: v.MarketID,
 | 
			
		||||
				Price:    v.Price,
 | 
			
		||||
			})
 | 
			
		||||
			notExpiredPrices = append(notExpiredPrices, types.NewCurrentPrice(v.MarketID, v.Price))
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if len(notExpiredPrices) == 0 {
 | 
			
		||||
		store := ctx.KVStore(k.key)
 | 
			
		||||
		store.Set(
 | 
			
		||||
			[]byte(types.CurrentPricePrefix+marketID), k.cdc.MustMarshalBinaryBare(types.CurrentPrice{}),
 | 
			
		||||
			types.CurrentPriceKey(marketID), k.cdc.MustMarshalBinaryBare(types.CurrentPrice{}),
 | 
			
		||||
		)
 | 
			
		||||
		return types.ErrNoValidPrice(k.codespace)
 | 
			
		||||
	}
 | 
			
		||||
@ -135,20 +128,17 @@ func (k Keeper) SetCurrentPrices(ctx sdk.Context, marketID string) sdk.Error {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	store := ctx.KVStore(k.key)
 | 
			
		||||
	currentPrice := types.CurrentPrice{
 | 
			
		||||
		MarketID: marketID,
 | 
			
		||||
		Price:    medianPrice,
 | 
			
		||||
	}
 | 
			
		||||
	currentPrice := types.NewCurrentPrice(marketID, medianPrice)
 | 
			
		||||
 | 
			
		||||
	store.Set(
 | 
			
		||||
		[]byte(types.CurrentPricePrefix+marketID), k.cdc.MustMarshalBinaryBare(currentPrice),
 | 
			
		||||
		types.CurrentPriceKey(marketID), k.cdc.MustMarshalBinaryBare(currentPrice),
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CalculateMedianPrice calculates the median prices for the input prices.
 | 
			
		||||
func (k Keeper) CalculateMedianPrice(ctx sdk.Context, prices []types.CurrentPrice) sdk.Dec {
 | 
			
		||||
func (k Keeper) CalculateMedianPrice(ctx sdk.Context, prices types.CurrentPrices) sdk.Dec {
 | 
			
		||||
	l := len(prices)
 | 
			
		||||
 | 
			
		||||
	if l == 1 {
 | 
			
		||||
@ -169,7 +159,7 @@ func (k Keeper) CalculateMedianPrice(ctx sdk.Context, prices []types.CurrentPric
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (k Keeper) calculateMeanPrice(ctx sdk.Context, prices []types.CurrentPrice) sdk.Dec {
 | 
			
		||||
func (k Keeper) calculateMeanPrice(ctx sdk.Context, prices types.CurrentPrices) sdk.Dec {
 | 
			
		||||
	sum := prices[0].Price.Add(prices[1].Price)
 | 
			
		||||
	mean := sum.Quo(sdk.NewDec(2))
 | 
			
		||||
	return mean
 | 
			
		||||
@ -178,7 +168,7 @@ func (k Keeper) calculateMeanPrice(ctx sdk.Context, prices []types.CurrentPrice)
 | 
			
		||||
// GetCurrentPrice fetches the current median price of all oracles for a specific market
 | 
			
		||||
func (k Keeper) GetCurrentPrice(ctx sdk.Context, marketID string) (types.CurrentPrice, sdk.Error) {
 | 
			
		||||
	store := ctx.KVStore(k.key)
 | 
			
		||||
	bz := store.Get([]byte(types.CurrentPricePrefix + marketID))
 | 
			
		||||
	bz := store.Get(types.CurrentPriceKey(marketID))
 | 
			
		||||
 | 
			
		||||
	if bz == nil {
 | 
			
		||||
		return types.CurrentPrice{}, types.ErrNoValidPrice(k.codespace)
 | 
			
		||||
@ -192,10 +182,10 @@ func (k Keeper) GetCurrentPrice(ctx sdk.Context, marketID string) (types.Current
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetRawPrices fetches the set of all prices posted by oracles for an asset
 | 
			
		||||
func (k Keeper) GetRawPrices(ctx sdk.Context, marketID string) []types.PostedPrice {
 | 
			
		||||
func (k Keeper) GetRawPrices(ctx sdk.Context, marketID string) types.PostedPrices {
 | 
			
		||||
	store := ctx.KVStore(k.key)
 | 
			
		||||
	bz := store.Get([]byte(types.RawPriceFeedPrefix + marketID))
 | 
			
		||||
	var prices []types.PostedPrice
 | 
			
		||||
	bz := store.Get(types.RawPriceKey(marketID))
 | 
			
		||||
	var prices types.PostedPrices
 | 
			
		||||
	k.cdc.MustUnmarshalBinaryBare(bz, &prices)
 | 
			
		||||
	return prices
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,12 +1,31 @@
 | 
			
		||||
package simulation
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"fmt"
 | 
			
		||||
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/codec"
 | 
			
		||||
	cmn "github.com/tendermint/tendermint/libs/common"
 | 
			
		||||
 | 
			
		||||
	"github.com/kava-labs/kava/x/pricefeed/types"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// DecodeStore unmarshals the KVPair's Value to the corresponding pricefeed type
 | 
			
		||||
func DecodeStore(cdc *codec.Codec, kvA, kvB cmn.KVPair) string {
 | 
			
		||||
	// TODO implement this
 | 
			
		||||
	return ""
 | 
			
		||||
	switch {
 | 
			
		||||
	case bytes.Contains(kvA.Key[:1], []byte(types.CurrentPricePrefix)):
 | 
			
		||||
		var priceA, priceB types.CurrentPrice
 | 
			
		||||
		cdc.MustUnmarshalBinaryBare(kvA.Value, &priceA)
 | 
			
		||||
		cdc.MustUnmarshalBinaryBare(kvB.Value, &priceB)
 | 
			
		||||
		return fmt.Sprintf("%s\n%s", priceA, priceB)
 | 
			
		||||
 | 
			
		||||
	case bytes.Contains(kvA.Key[:1], []byte(types.RawPriceFeedPrefix)):
 | 
			
		||||
		var postedPriceA, postedPriceB types.PostedPrices
 | 
			
		||||
		cdc.MustUnmarshalBinaryBare(kvA.Value, &postedPriceA)
 | 
			
		||||
		cdc.MustUnmarshalBinaryBare(kvB.Value, &postedPriceB)
 | 
			
		||||
		return fmt.Sprintf("%s\n%s", postedPriceA, postedPriceB)
 | 
			
		||||
 | 
			
		||||
	default:
 | 
			
		||||
		panic(fmt.Sprintf("invalid %s key prefix %X", types.ModuleName, kvA.Key[:1]))
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										63
									
								
								x/pricefeed/simulation/decoder_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								x/pricefeed/simulation/decoder_test.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,63 @@
 | 
			
		||||
package simulation_test
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"testing"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/codec"
 | 
			
		||||
	sdk "github.com/cosmos/cosmos-sdk/types"
 | 
			
		||||
	"github.com/kava-labs/kava/app"
 | 
			
		||||
	"github.com/kava-labs/kava/x/pricefeed/simulation"
 | 
			
		||||
	"github.com/kava-labs/kava/x/pricefeed/types"
 | 
			
		||||
	"github.com/stretchr/testify/suite"
 | 
			
		||||
	cmn "github.com/tendermint/tendermint/libs/common"
 | 
			
		||||
	tmtime "github.com/tendermint/tendermint/types/time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type decoderTest struct {
 | 
			
		||||
	name        string
 | 
			
		||||
	expectedLog string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type DecoderTestSuite struct {
 | 
			
		||||
	suite.Suite
 | 
			
		||||
 | 
			
		||||
	tests []decoderTest
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func makeTestCodec() (cdc *codec.Codec) {
 | 
			
		||||
	cdc = codec.New()
 | 
			
		||||
	sdk.RegisterCodec(cdc)
 | 
			
		||||
	codec.RegisterCrypto(cdc)
 | 
			
		||||
	types.RegisterCodec(cdc)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (suite *DecoderTestSuite) TestDecodeStore() {
 | 
			
		||||
	cdc := makeTestCodec()
 | 
			
		||||
	price := types.NewCurrentPrice("bnb:usd", sdk.MustNewDecFromStr("12.0"))
 | 
			
		||||
	_, addrs := app.GeneratePrivKeyAddressPairs(1)
 | 
			
		||||
	rawPrices := types.PostedPrices{
 | 
			
		||||
		types.NewPostedPrice("bnb:usd", addrs[0], sdk.MustNewDecFromStr("12.0"), tmtime.Now().Add(time.Hour*2)),
 | 
			
		||||
	}
 | 
			
		||||
	kvPairs := cmn.KVPairs{
 | 
			
		||||
		cmn.KVPair{Key: types.CurrentPriceKey("bnb:usd"), Value: cdc.MustMarshalBinaryBare(price)},
 | 
			
		||||
		cmn.KVPair{Key: types.RawPriceKey("bnb:usd"), Value: cdc.MustMarshalBinaryBare(rawPrices)},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	decoderTests := []decoderTest{
 | 
			
		||||
		decoderTest{"current price", fmt.Sprintf("%s\n%s", price, price)},
 | 
			
		||||
		decoderTest{"raw prices", fmt.Sprintf("%s\n%s", rawPrices, rawPrices)},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for i, t := range decoderTests {
 | 
			
		||||
		suite.Run(t.name, func() {
 | 
			
		||||
			suite.Equal(t.expectedLog, simulation.DecodeStore(cdc, kvPairs[i], kvPairs[i]))
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestDecoderTestSuite(t *testing.T) {
 | 
			
		||||
	suite.Run(t, new(DecoderTestSuite))
 | 
			
		||||
}
 | 
			
		||||
@ -15,16 +15,22 @@ const (
 | 
			
		||||
 | 
			
		||||
	// DefaultParamspace default namestore
 | 
			
		||||
	DefaultParamspace = ModuleName
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	// CurrentPricePrefix prefix for the current price of an asset
 | 
			
		||||
	CurrentPricePrefix = []byte{0x00}
 | 
			
		||||
 | 
			
		||||
	// RawPriceFeedPrefix prefix for the raw pricefeed of an asset
 | 
			
		||||
	RawPriceFeedPrefix = StoreKey + ":raw:"
 | 
			
		||||
 | 
			
		||||
	// CurrentPricePrefix prefix for the current price of an asset
 | 
			
		||||
	CurrentPricePrefix = StoreKey + ":currentprice:"
 | 
			
		||||
 | 
			
		||||
	// MarketPrefix Prefix for the assets in the pricefeed system
 | 
			
		||||
	MarketPrefix = StoreKey + ":markets"
 | 
			
		||||
 | 
			
		||||
	// OraclePrefix store prefix for the oracle accounts
 | 
			
		||||
	OraclePrefix = StoreKey + ":oracles"
 | 
			
		||||
	RawPriceFeedPrefix = []byte{0x01}
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// CurrentPriceKey returns the prefix for the current price
 | 
			
		||||
func CurrentPriceKey(marketID string) []byte {
 | 
			
		||||
	return append(CurrentPricePrefix, []byte(marketID)...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RawPriceKey returns the prefix for the raw price
 | 
			
		||||
func RawPriceKey(marketID string) []byte {
 | 
			
		||||
	return append(RawPriceFeedPrefix, []byte(marketID)...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -46,6 +46,14 @@ type CurrentPrice struct {
 | 
			
		||||
	Price    sdk.Dec `json:"price" yaml:"price"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewCurrentPrice returns an instance of CurrentPrice
 | 
			
		||||
func NewCurrentPrice(marketID string, price sdk.Dec) CurrentPrice {
 | 
			
		||||
	return CurrentPrice{MarketID: marketID, Price: price}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CurrentPrices type for an array of CurrentPrice
 | 
			
		||||
type CurrentPrices []CurrentPrice
 | 
			
		||||
 | 
			
		||||
// PostedPrice price for market posted by a specific oracle
 | 
			
		||||
type PostedPrice struct {
 | 
			
		||||
	MarketID      string         `json:"market_id" yaml:"market_id"`
 | 
			
		||||
@ -54,6 +62,19 @@ type PostedPrice struct {
 | 
			
		||||
	Expiry        time.Time      `json:"expiry" yaml:"expiry"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewPostedPrice returns a new PostedPrice
 | 
			
		||||
func NewPostedPrice(marketID string, oracle sdk.AccAddress, price sdk.Dec, expiry time.Time) PostedPrice {
 | 
			
		||||
	return PostedPrice{
 | 
			
		||||
		MarketID:      marketID,
 | 
			
		||||
		OracleAddress: oracle,
 | 
			
		||||
		Price:         price,
 | 
			
		||||
		Expiry:        expiry,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// PostedPrices type for an array of PostedPrice
 | 
			
		||||
type PostedPrices []PostedPrice
 | 
			
		||||
 | 
			
		||||
// implement fmt.Stringer
 | 
			
		||||
func (cp CurrentPrice) String() string {
 | 
			
		||||
	return strings.TrimSpace(fmt.Sprintf(`Market ID: %s
 | 
			
		||||
@ -68,6 +89,15 @@ Price: %s
 | 
			
		||||
Expiry: %s`, pp.MarketID, pp.OracleAddress, pp.Price, pp.Expiry))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// String implements fmt.Stringer
 | 
			
		||||
func (ps PostedPrices) String() string {
 | 
			
		||||
	out := "Posted Prices:\n"
 | 
			
		||||
	for _, p := range ps {
 | 
			
		||||
		out += fmt.Sprintf("%s\n", p.String())
 | 
			
		||||
	}
 | 
			
		||||
	return strings.TrimSpace(out)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SortDecs provides the interface needed to sort sdk.Dec slices
 | 
			
		||||
type SortDecs []sdk.Dec
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user