Skip to content

Commit

Permalink
add comments
Browse files Browse the repository at this point in the history
  • Loading branch information
Julian committed Aug 19, 2020
1 parent 8236260 commit 0286535
Show file tree
Hide file tree
Showing 3 changed files with 141 additions and 23 deletions.
3 changes: 2 additions & 1 deletion asserter/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ package asserter

import "errors"

// Named error types for Asserter errors
var (
//////////////////////////////////
/* ACCOUNT BALANCE QUERY ERRORS */
Expand Down Expand Up @@ -360,7 +361,7 @@ var (
}
)

// IsAssertError takes an error as an argument and returns
// ErrAsserter takes an error as an argument and returns
// whether or not the error is one thrown by the asserter
// along with the specific source of the error
func ErrAsserter(err error) (bool, string) {
Expand Down
98 changes: 76 additions & 22 deletions storage/coin_storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,41 +97,70 @@ func getAndDecodeCoin(

type wallets map[string]map[string]struct{}

func (c *CoinStorage) tryAddingCoin(
// AccountCoin contains an AccountIdentifier and a Coin that it owns
type AccountCoin struct {
Account *types.AccountIdentifier
Coin *types.Coin
}

// AddCoins takes an array of AccountIdentifiers and it's respective Coin
// and saves all of them to the database. It returns an error if the
// transaction fails.
func (c *CoinStorage) AddCoins(
ctx context.Context,
transaction DatabaseTransaction,
operation *types.Operation,
action types.CoinAction,
cache wallets,
accountCoins []*AccountCoin,
) error {
if operation.CoinChange == nil {
return errors.New("coin change cannot be nil")
}
dbTransaction := c.db.NewDatabaseTransaction(ctx, true)
defer dbTransaction.Discard(ctx)

if operation.CoinChange.CoinAction != action {
return nil
cache := wallets{}
for _, accountCoin := range accountCoins {
exists, _, err := getAndDecodeCoin(ctx, dbTransaction, accountCoin.Coin.CoinIdentifier)
if err != nil {
return fmt.Errorf("%w: unable to get coin", err)
}

if exists {
continue
}

err = addCoin(ctx, accountCoin.Account, accountCoin.Coin, dbTransaction, cache)
if err != nil {
return fmt.Errorf("%w: unable to add coin", err)
}
}

coinIdentifier := operation.CoinChange.CoinIdentifier
if err := writeCache(ctx, dbTransaction, cache); err != nil {
return fmt.Errorf("%w: unable to update wallets", err)
}

newCoin := &types.Coin{
CoinIdentifier: coinIdentifier,
Amount: operation.Amount,
if err := dbTransaction.Commit(ctx); err != nil {
return fmt.Errorf("%w: unable to commit last reconciliation update", err)
}

encodedResult, err := encode(newCoin)
return nil
}

func addCoin(
ctx context.Context,
account *types.AccountIdentifier,
coin *types.Coin,
transaction DatabaseTransaction,
cache wallets,
) error {
encodedResult, err := encode(coin)
if err != nil {
return fmt.Errorf("%w: unable to encode coin data", err)
}

if err := transaction.Set(ctx, getCoinKey(coinIdentifier), encodedResult); err != nil {
if err := transaction.Set(ctx, getCoinKey(coin.CoinIdentifier), encodedResult); err != nil {
return fmt.Errorf("%w: unable to store coin", err)
}

addressKey := string(getCoinAccountKey(operation.Account))
addressKey := string(getCoinAccountKey(account))
coins, ok := cache[addressKey]
if !ok {
accountExists, accountCoins, err := getAndDecodeCoins(ctx, transaction, operation.Account)
accountExists, accountCoins, err := getAndDecodeCoins(ctx, transaction, account)
if err != nil {
return fmt.Errorf("%w: unable to query coin account", err)
}
Expand All @@ -142,21 +171,46 @@ func (c *CoinStorage) tryAddingCoin(

coins = accountCoins
}

if _, exists := coins[coinIdentifier.Identifier]; exists {
coinIdentifier := coin.CoinIdentifier.Identifier
if _, exists := coins[coinIdentifier]; exists {
return fmt.Errorf(
"coin %s already exists in account %s",
coinIdentifier,
types.PrettyPrintStruct(operation.Account),
types.PrettyPrintStruct(account),
)
}

coins[coinIdentifier.Identifier] = struct{}{}
coins[coinIdentifier] = struct{}{}
cache[addressKey] = coins

return nil
}

func (c *CoinStorage) tryAddingCoin(
ctx context.Context,
transaction DatabaseTransaction,
operation *types.Operation,
action types.CoinAction,
cache wallets,
) error {
if operation.CoinChange == nil {
return errors.New("coin change cannot be nil")
}

if operation.CoinChange.CoinAction != action {
return nil
}

coinIdentifier := operation.CoinChange.CoinIdentifier

newCoin := &types.Coin{
CoinIdentifier: coinIdentifier,
Amount: operation.Amount,
}

return addCoin(ctx, operation.Account, newCoin, transaction, cache)
}

func encodeAndSetCoins(
ctx context.Context,
transaction DatabaseTransaction,
Expand Down
63 changes: 63 additions & 0 deletions storage/coin_storage_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,30 @@ var (
},
}

coins1 = &types.Coin{
CoinIdentifier: &types.CoinIdentifier{Identifier: "bulkCoin1"},
Amount: &types.Amount{
Value: "10",
Currency: currency,
},
}

coins2 = &types.Coin{
CoinIdentifier: &types.CoinIdentifier{Identifier: "bulkCoin2"},
Amount: &types.Amount{
Value: "20",
Currency: currency,
},
}

coins3 = &types.Coin{
CoinIdentifier: &types.CoinIdentifier{Identifier: "bulkCoin3"},
Amount: &types.Amount{
Value: "30",
Currency: currency,
},
}

successStatus = "success"
failureStatus = "failure"

Expand Down Expand Up @@ -373,6 +397,45 @@ func TestCoinStorage(t *testing.T) {
assert.Equal(t, &types.CoinIdentifier{Identifier: "coin4"}, coinIdentifier)
assert.Equal(t, blockIdentifier, block)
})

t.Run("AddCoins", func(t *testing.T) {
accountCoins := []*AccountCoin{
&AccountCoin{
Account: account,
Coin: coins1,
},
&AccountCoin{
Account: account2,
Coin: coins2,
},
&AccountCoin{
Account: account3,
Coin: coins3,
},
}

account1coins, _, _ := c.GetCoins(ctx, account)
account2coins, _, _ := c.GetCoins(ctx, account2)
account3coins, _, _ := c.GetCoins(ctx, account3)

err := c.AddCoins(ctx, accountCoins)
assert.NoError(t, err)

coinsGot, _, err := c.GetCoins(ctx, account)
account1coins = append(account1coins, coins1)
assert.NoError(t, err)
assert.ElementsMatch(t, coinsGot, account1coins)

coinsGot, _, err = c.GetCoins(ctx, account2)
account2coins = append(account2coins, coins2)
assert.NoError(t, err)
assert.ElementsMatch(t, coinsGot, account2coins)

coinsGot, _, err = c.GetCoins(ctx, account3)
account3coins = append(account3coins, coins3)
assert.NoError(t, err)
assert.ElementsMatch(t, coinsGot, account3coins)
})
}

type MockCoinStorageHelper struct{}
Expand Down

0 comments on commit 0286535

Please sign in to comment.