Skip to content

Commit

Permalink
Merge branch 'release/v2.2.x' into ryan/732-cli-create-basket
Browse files Browse the repository at this point in the history
  • Loading branch information
ryanchristo authored Feb 11, 2022
2 parents 09641d6 + 452ec03 commit dfe986b
Show file tree
Hide file tree
Showing 22 changed files with 1,131 additions and 252 deletions.
20 changes: 20 additions & 0 deletions types/math/dec.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,13 @@ func NewDecFromInt64(x int64) Dec {
return res
}

// NewDecFinite returns a decimal with a value of coeff * 10^exp.
func NewDecFinite(coeff int64, exp int32) Dec {
var res Dec
res.dec.SetFinite(coeff, exp)
return res
}

// Add returns a new Dec with value `x+y` without mutating any argument and error if
// there is an overflow.
func (x Dec) Add(y Dec) (Dec, error) {
Expand All @@ -114,6 +121,19 @@ func (x Dec) Quo(y Dec) (Dec, error) {
return z, errors.Wrap(err, "decimal quotient error")
}

// MulExact returns a new dec with value x * y. The product must not round or an error will be returned.
func (x Dec) MulExact(y Dec) (Dec, error) {
var z Dec
condition, err := dec128Context.Mul(&z.dec, &x.dec, &y.dec)
if err != nil {
return z, err
}
if condition.Rounded() {
return z, errors.Wrap(err, "exact decimal product error")
}
return z, nil
}

// QuoInteger returns a new integral Dec with value `x/y` (formatted as decimal128, with 34 digit precision)
// without mutating any argument and error if there is an overflow.
func (x Dec) QuoInteger(y Dec) (Dec, error) {
Expand Down
5 changes: 5 additions & 0 deletions x/ecocredit/basket/keys.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package basket

import "github.com/regen-network/regen-ledger/x/ecocredit"

const BasketSubModuleName = ecocredit.ModuleName + "-basket"
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package server
package ecocredit

import (
"testing"
Expand All @@ -11,7 +11,7 @@ import (
var addr = sdk.AccAddress(ed25519.GenPrivKey().PubKey().Address())

func TestKeys(t *testing.T) {
batchDenom := batchDenomT("testing-denom")
batchDenom := BatchDenomT("testing-denom")

// tradable-balance-key
key := TradableBalanceKey(addr, batchDenom)
Expand Down
158 changes: 158 additions & 0 deletions x/ecocredit/keys.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,166 @@
package ecocredit

import (
"fmt"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/address"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/regen-network/regen-ledger/types/math"
)

const (
// ModuleName is the module name constant used in many places
ModuleName = "ecocredit"

DefaultParamspace = ModuleName

TradableBalancePrefix byte = 0x0
TradableSupplyPrefix byte = 0x1
RetiredBalancePrefix byte = 0x2
RetiredSupplyPrefix byte = 0x3
CreditTypeSeqTablePrefix byte = 0x4
ClassInfoTablePrefix byte = 0x5
BatchInfoTablePrefix byte = 0x6
ORMPrefix byte = 0x7
)

// BatchDenomT is used to prevent errors when forming keys as accounts and denoms are
// both represented as strings
type BatchDenomT string

// - 0x0 <accAddrLen (1 Byte)><accAddr_Bytes><denom_Bytes>: TradableBalance
// - 0x1 <denom_Bytes>: TradableSupply
// - 0x2 <accAddrLen (1 Byte)><accAddr_Bytes><denom_Bytes>: RetiredBalance
// - 0x3 <denom_Bytes>: RetiredSupply

// TradableBalanceKey creates the index key for recipient address and batch-denom
func TradableBalanceKey(acc sdk.AccAddress, denom BatchDenomT) []byte {
key := []byte{TradableBalancePrefix}
key = append(key, address.MustLengthPrefix(acc)...)
return append(key, denom...)
}

// ParseBalanceKey parses the recipient address and batch-denom from tradable or retired balance key.
// Balance keys take the following form: <storage prefix 1 byte><addr length 1 byte><addr><batchDenom>
func ParseBalanceKey(key []byte) (sdk.AccAddress, BatchDenomT) {
addrLen := key[1]
addr := sdk.AccAddress(key[2 : 2+addrLen])
return addr, BatchDenomT(key[2+addrLen:])
}

// TradableSupplyKey creates the tradable supply key for a given batch-denom
func TradableSupplyKey(batchDenom BatchDenomT) []byte {
key := []byte{TradableSupplyPrefix}
return append(key, batchDenom...)
}

// ParseSupplyKey parses the batch-denom from tradable or retired supply key
func ParseSupplyKey(key []byte) BatchDenomT {
return BatchDenomT(key[1:])
}

// RetiredBalanceKey creates the index key for recipient address and batch-denom
func RetiredBalanceKey(acc sdk.AccAddress, batchDenom BatchDenomT) []byte {
key := []byte{RetiredBalancePrefix}
key = append(key, address.MustLengthPrefix(acc)...)
return append(key, batchDenom...)
}

// RetiredSupplyKey creates the retired supply key for a given batch-denom
func RetiredSupplyKey(batchDenom BatchDenomT) []byte {
key := []byte{RetiredSupplyPrefix}
return append(key, batchDenom...)
}

// GetDecimal retrieves a decimal by `key` from the given `store`
func GetDecimal(store sdk.KVStore, key []byte) (math.Dec, error) {
bz := store.Get(key)
if bz == nil {
return math.NewDecFromInt64(0), nil
}

value, err := math.NewDecFromString(string(bz))
if err != nil {
return math.Dec{}, sdkerrors.Wrap(err, fmt.Sprintf("can't unmarshal %s as decimal", bz))
}

return value, nil
}

// SetDecimal stores a decimal by `key` in the given `store`
func SetDecimal(store sdk.KVStore, key []byte, value math.Dec) {
// always remove all trailing zeros for canonical representation
value, _ = value.Reduce()

if value.IsZero() {
store.Delete(key)
} else {
// use floating notation here always for canonical representation
store.Set(key, []byte(value.String()))
}
}

// AddAndSetDecimal retrieves a decimal from the given key, adds it to x, and saves it.
func AddAndSetDecimal(store sdk.KVStore, key []byte, x math.Dec) error {
value, err := GetDecimal(store, key)
if err != nil {
return err
}

value, err = value.Add(x)
if err != nil {
return err
}

SetDecimal(store, key, value)
return nil
}

// SubAndSetDecimal retrieves a decimal from the given key, subtracts x from it, and saves it.
func SubAndSetDecimal(store sdk.KVStore, key []byte, x math.Dec) error {
value, err := GetDecimal(store, key)
if err != nil {
return err
}

if value.Cmp(x) == -1 {
return ErrInsufficientFunds
}

value, err = math.SafeSubBalance(value, x)
if err != nil {
return err
}

SetDecimal(store, key, value)
return nil
}

// IterateSupplies iterates over supplies and calls the specified callback function `cb`
func IterateSupplies(store sdk.KVStore, storeKey byte, cb func(denom, supply string) (bool, error)) error {
iter := sdk.KVStorePrefixIterator(store, []byte{storeKey})
defer iter.Close()
for ; iter.Valid(); iter.Next() {
stop, err := cb(string(ParseSupplyKey(iter.Key())), string(iter.Value()))
if err != nil {
return err
}
if stop {
break
}
}

return nil
}

// IterateBalances iterates over balances and calls the specified callback function `cb`
func IterateBalances(store sdk.KVStore, storeKey byte, cb func(address, denom, balance string) bool) {
iter := sdk.KVStorePrefixIterator(store, []byte{storeKey})
defer iter.Close()
for ; iter.Valid(); iter.Next() {
addr, denom := ParseBalanceKey(iter.Key())
if cb(addr.String(), string(denom), string(iter.Value())) {
break
}
}
}
5 changes: 3 additions & 2 deletions x/ecocredit/server/basket/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,19 @@ type Keeper struct {
stateStore basketv1.StateStore
bankKeeper BankKeeper
ecocreditKeeper EcocreditKeeper
storeKey sdk.StoreKey
}

var _ baskettypes.MsgServer = Keeper{}
var _ baskettypes.QueryServer = Keeper{}

// NewKeeper returns a new keeper instance.
func NewKeeper(db ormdb.ModuleDB, ecocreditKeeper EcocreditKeeper, bankKeeper BankKeeper) Keeper {
func NewKeeper(db ormdb.ModuleDB, ecocreditKeeper EcocreditKeeper, bankKeeper BankKeeper, storeKey sdk.StoreKey) Keeper {
basketStore, err := basketv1.NewStateStore(db)
if err != nil {
panic(err)
}
return Keeper{bankKeeper: bankKeeper, ecocreditKeeper: ecocreditKeeper, stateStore: basketStore}
return Keeper{bankKeeper: bankKeeper, ecocreditKeeper: ecocreditKeeper, stateStore: basketStore, storeKey: storeKey}
}

// EcocreditKeeper abstracts over methods that the main eco-credit keeper
Expand Down
4 changes: 3 additions & 1 deletion x/ecocredit/server/basket/keeper_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package basket_test

import (
sdk "github.com/cosmos/cosmos-sdk/types"
"testing"

"github.com/cosmos/cosmos-sdk/orm/model/ormdb"
Expand All @@ -19,6 +20,7 @@ func TestKeeperExample(t *testing.T) {

bankKeeper := mocks.NewMockBankKeeper(ctrl)
ecocreditKeeper := mocks.NewMockEcocreditKeeper(ctrl)
k := basket.NewKeeper(db, ecocreditKeeper, bankKeeper)
sk := sdk.NewKVStoreKey("test")
k := basket.NewKeeper(db, ecocreditKeeper, bankKeeper, sk)
require.NotNil(t, k)
}
Loading

0 comments on commit dfe986b

Please sign in to comment.