Skip to content

Commit

Permalink
add ctors, some helpers
Browse files Browse the repository at this point in the history
  • Loading branch information
leohhhn committed Feb 26, 2024
1 parent 6f4efc6 commit c1ea95d
Show file tree
Hide file tree
Showing 3 changed files with 198 additions and 28 deletions.
3 changes: 3 additions & 0 deletions examples/gno.land/r/demo/tt/tt.gno
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package tt

func Render()
116 changes: 102 additions & 14 deletions gnovm/stdlibs/std/coins.gno
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package std

import "strconv"
import (
"sort"
"strconv"
)

// NOTE: this is selectly copied over from pkgs/std/coin.go
// TODO: import all functionality(?).
Expand All @@ -12,23 +15,62 @@ type Coin struct {
Amount int64 `json:"amount"`
}

func (c Coin) String() string {
return strconv.Itoa(int(c.Amount)) + c.Denom
// NewCoin returns a new coin with a denomination and amount.
func NewCoin(denom string, amount int64) Coin {
validate(amount)
1
return Coin{
Denom: denom,
Amount: amount,
}
}

func (coin Coin) String() string {
return strconv.Itoa(int(coin.Amount)) + coin.Denom
}

func (coin Coin) IsGTE(other Coin) bool {
if coin.Denom != other.Denom {
panic("invalid coin denominations: " + coin.Denom)
}
return coin.Amount >= other.Amount
}

// IsZero returns if this represents no money
func (coin Coin) IsZero() bool {
return coin.Amount == 0
}

func (c Coin) IsGTE(other Coin) bool {
if c.Denom != other.Denom {
panic("invalid coin denominations: " + c.Denom)
// validate returns an error if the Coin has a negative amount
func validate(amount int64) {
if amount < 0 {
panic("negative coin amount when constructing coin")
}
return c.Amount >= other.Amount
}

// Coins is a set of Coin, one per currency
type Coins []Coin

func (cz Coins) String() string {
// NewCoins constructs a new coin set.
func NewCoins(coins ...Coin) Coins {
// remove zeroes
newCoins := removeZeroCoins(Coins(coins))
if len(newCoins) == 0 {
return Coins{}
}

newCoins.Sort()

// detect duplicate Denoms
if dupIndex := findDup(newCoins); dupIndex != -1 {
panic("found duplicate denom when constructing coins set")
}
return newCoins
}

func (coins Coins) String() string {
res := ""
for i, c := range cz {
for i, c := range coins {
if i > 0 {
res += ","
}
Expand All @@ -37,18 +79,18 @@ func (cz Coins) String() string {
return res
}

func (cz Coins) AmountOf(denom string) int64 {
for _, c := range cz {
func (coins Coins) AmountOf(denom string) int64 {
for _, c := range coins {
if c.Denom == denom {
return c.Amount
}
}
return 0
}

func (a Coins) Add(b Coins) Coins {
func (coins Coins) Add(b Coins) Coins {
c := Coins{}
for _, ac := range a {
for _, ac := range coins {
bc := b.AmountOf(ac.Denom)
ac.Amount += bc
c = append(c, ac)
Expand All @@ -62,4 +104,50 @@ func (a Coins) Add(b Coins) Coins {
return c
}

// TODO implement Coin/Coins constructors.
// removeZeroCoins removes all zero coins from the given coin set in-place.
func removeZeroCoins(coins Coins) Coins {
i, l := 0, len(coins)
for i < l {
if coins[i].IsZero() {
// remove coin
coins = append(coins[:i], coins[i+1:]...)
l--
} else {
i++
}
}

return coins[:i]
}

// findDup works on the assumption that coins is sorted
func findDup(coins Coins) int {
if len(coins) <= 1 {
return -1
}

prevDenom := coins[0].Denom
for i := 1; i < len(coins); i++ {
if coins[i].Denom == prevDenom {
return i
}
prevDenom = coins[i].Denom
}

return -1
}

// -----------------------------------------------------------------------------
// Sort interface

func (coins Coins) Len() int { return len(coins) }
func (coins Coins) Less(i, j int) bool { return coins[i].Denom < coins[j].Denom }
func (coins Coins) Swap(i, j int) { coins[i], coins[j] = coins[j], coins[i] }

var _ sort.Interface = Coins{}

// Sort is a helper function to sort the set of coins inplace
func (coins Coins) Sort() Coins {
sort.Sort(coins)
return coins
}
107 changes: 93 additions & 14 deletions gnovm/stdlibs/stdshim/coins.gno
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package std

import "strconv"
import (
"sort"
"strconv"
)

// NOTE: this is selectly copied over from pkgs/std/coin.go
// TODO: import all functionality(?).
Expand All @@ -12,23 +15,53 @@ type Coin struct {
Amount int64 `json:"amount"`
}

func (c Coin) String() string {
return strconv.Itoa(int(c.Amount)) + c.Denom
// NewCoin returns a new coin with a denomination and amount.
func NewCoin(denom string, amount int64) Coin {
return Coin{
Denom: denom,
Amount: amount,
}
}

func (coin Coin) String() string {
return strconv.Itoa(int(coin.Amount)) + coin.Denom
}

func (c Coin) IsGTE(other Coin) bool {
if c.Denom != other.Denom {
panic("invalid coin denominations: " + c.Denom)
func (coin Coin) IsGTE(other Coin) bool {
if coin.Denom != other.Denom {
panic("invalid coin denominations: " + coin.Denom)
}
return c.Amount >= other.Amount
return coin.Amount >= other.Amount
}

// IsZero returns if this represents no money
func (coin Coin) IsZero() bool {
return coin.Amount == 0
}

// Coins is a set of Coin, one per currency
type Coins []Coin

func (cz Coins) String() string {
// NewCoins constructs a new coin set.
func NewCoins(coins ...Coin) Coins {
// remove zeroes
newCoins := removeZeroCoins(Coins(coins))
if len(newCoins) == 0 {
return Coins{}
}

newCoins.Sort()

// detect duplicate Denoms
if dupIndex := findDup(newCoins); dupIndex != -1 {
panic("found duplicate denom when constructing coins set")
}
return newCoins
}

func (coins Coins) String() string {
res := ""
for i, c := range cz {
for i, c := range coins {
if i > 0 {
res += ","
}
Expand All @@ -37,18 +70,18 @@ func (cz Coins) String() string {
return res
}

func (cz Coins) AmountOf(denom string) int64 {
for _, c := range cz {
func (coins Coins) AmountOf(denom string) int64 {
for _, c := range coins {
if c.Denom == denom {
return c.Amount
}
}
return 0
}

func (a Coins) Add(b Coins) Coins {
func (coins Coins) Add(b Coins) Coins {
c := Coins{}
for _, ac := range a {
for _, ac := range coins {
bc := b.AmountOf(ac.Denom)
ac.Amount += bc
c = append(c, ac)
Expand All @@ -62,4 +95,50 @@ func (a Coins) Add(b Coins) Coins {
return c
}

// TODO implement Coin/Coins constructors.
// removeZeroCoins removes all zero coins from the given coin set in-place.
func removeZeroCoins(coins Coins) Coins {
i, l := 0, len(coins)
for i < l {
if coins[i].IsZero() {
// remove coin
coins = append(coins[:i], coins[i+1:]...)
l--
} else {
i++
}
}

return coins[:i]
}

// findDup works on the assumption that coins is sorted
func findDup(coins Coins) int {
if len(coins) <= 1 {
return -1
}

prevDenom := coins[0].Denom
for i := 1; i < len(coins); i++ {
if coins[i].Denom == prevDenom {
return i
}
prevDenom = coins[i].Denom
}

return -1
}

// -----------------------------------------------------------------------------
// Sort interface

func (coins Coins) Len() int { return len(coins) }
func (coins Coins) Less(i, j int) bool { return coins[i].Denom < coins[j].Denom }
func (coins Coins) Swap(i, j int) { coins[i], coins[j] = coins[j], coins[i] }

var _ sort.Interface = Coins{}

// Sort is a helper function to sort the set of coins inplace
func (coins Coins) Sort() Coins {
sort.Sort(coins)
return coins
}

0 comments on commit c1ea95d

Please sign in to comment.