Skip to content

Commit

Permalink
Merge pull request #307 from scorpioborn/feat/sub-main-wager
Browse files Browse the repository at this point in the history
Feat / Subaccount and  Main account consolidated wager
  • Loading branch information
3eyedraga authored Nov 19, 2023
2 parents cfb60c6 + 54800ed commit 26ff3f9
Show file tree
Hide file tree
Showing 21 changed files with 463 additions and 231 deletions.
14 changes: 13 additions & 1 deletion proto/sge/subaccount/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,19 @@ message MsgWithdrawUnlockedBalancesResponse {}

// MsgWager wraps the MsgWager message. We need it in order not to have
// double interface registration conflicts.
message MsgWager { sgenetwork.sge.bet.MsgWager msg = 1; }
message MsgWager {
sgenetwork.sge.bet.MsgWager msg = 1;
// mainacc_deduct_amount is amount to be deducted from main account
string mainacc_deduct_amount = 2 [
(gogoproto.customtype) = "cosmossdk.io/math.Int",
(gogoproto.nullable) = false
];
// subacc_deduct_amount is amount to be deducted from sub account
string subacc_deduct_amount = 3 [
(gogoproto.customtype) = "cosmossdk.io/math.Int",
(gogoproto.nullable) = false
];
}

// MsgWagerResponse wraps the MsgWagerResponse message. We need it in order not
// to have double interface registration conflicts.
Expand Down
2 changes: 1 addition & 1 deletion x/reward/keeper/msg_server_reward_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@ func TestMsgApplySubAccFunds(t *testing.T) {
subAccAddr, found := tApp.SubaccountKeeper.GetSubAccountByOwner(ctx, sdk.MustAccAddressFromBech32(receiverAddr))
require.True(t, found)

balance, found := tApp.SubaccountKeeper.GetBalance(ctx, subAccAddr)
balance, found := tApp.SubaccountKeeper.GetAccountSummary(ctx, subAccAddr)
require.True(t, found)

require.Equal(t, rewardAmount, balance.DepositedAmount.Int64())
Expand Down
2 changes: 1 addition & 1 deletion x/subaccount/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ func InitGenesis(ctx sdk.Context, k keeper.Keeper, genState types.GenesisState)
addr := sdk.MustAccAddressFromBech32(acc.Address)
k.SetSubAccountOwner(ctx, addr, owner)
k.SetLockedBalances(ctx, addr, acc.LockedBalances)
k.SetBalance(ctx, addr, acc.Balance)
k.SetAccountSummary(ctx, addr, acc.Balance)
}
}

Expand Down
47 changes: 35 additions & 12 deletions x/subaccount/keeper/balance.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,16 +70,16 @@ func (k Keeper) GetUnlockedBalance(ctx sdk.Context, subAccountAddress sdk.AccAdd
return unlockedBalance
}

// SetBalance saves the balance of an account.
func (k Keeper) SetBalance(ctx sdk.Context, subAccountAddress sdk.AccAddress, accountSummary types.AccountSummary) {
// SetAccountSummary saves the balance of an account.
func (k Keeper) SetAccountSummary(ctx sdk.Context, subAccountAddress sdk.AccAddress, accountSummary types.AccountSummary) {
store := ctx.KVStore(k.storeKey)

bz := k.cdc.MustMarshal(&accountSummary)
store.Set(types.AccountSummaryKey(subAccountAddress), bz)
}

// GetBalance returns the balance of an account.
func (k Keeper) GetBalance(ctx sdk.Context, subAccountAddress sdk.AccAddress) (types.AccountSummary, bool) {
// GetAccountSummary returns the balance of an account.
func (k Keeper) GetAccountSummary(ctx sdk.Context, subAccountAddress sdk.AccAddress) (types.AccountSummary, bool) {
store := ctx.KVStore(k.storeKey)
bz := store.Get(types.AccountSummaryKey(subAccountAddress))
if bz == nil {
Expand All @@ -96,7 +96,7 @@ func (k Keeper) GetBalance(ctx sdk.Context, subAccountAddress sdk.AccAddress) (t
func (k Keeper) TopUp(ctx sdk.Context, creator, subAccOwnerAddr string,
lockedBalance []types.LockedBalance,
) (string, error) {
moneyToAdd, err := sumBalanceUnlocks(ctx, lockedBalance)
addedBalance, err := sumlockedBalance(ctx, lockedBalance)
if err != nil {
return "", err
}
Expand All @@ -108,25 +108,25 @@ func (k Keeper) TopUp(ctx sdk.Context, creator, subAccOwnerAddr string,
if !exists {
return "", types.ErrSubaccountDoesNotExist
}
balance, exists := k.GetBalance(ctx, subAccAddr)
balance, exists := k.GetAccountSummary(ctx, subAccAddr)
if !exists {
panic("data corruption: subaccount exists but balance does not")
}

balance.DepositedAmount = balance.DepositedAmount.Add(moneyToAdd)
k.SetBalance(ctx, subAccAddr, balance)
balance.DepositedAmount = balance.DepositedAmount.Add(addedBalance)
k.SetAccountSummary(ctx, subAccAddr, balance)
k.SetLockedBalances(ctx, subAccAddr, lockedBalance)

err = k.sendCoinsToSubaccount(ctx, creatorAddr, subAccAddr, moneyToAdd)
err = k.sendCoinsToSubaccount(ctx, creatorAddr, subAccAddr, addedBalance)
if err != nil {
return "", sdkerrors.Wrapf(types.ErrSendCoinError, "%s", err)
}
return subAccAddr.String(), nil
}

// getBalances returns the balance, unlocked balance and bank balance of a subaccount
func (k Keeper) getBalances(sdkContext sdk.Context, subaccountAddr sdk.AccAddress) (types.AccountSummary, sdkmath.Int, sdk.Coin) {
balance, exists := k.GetBalance(sdkContext, subaccountAddr)
// getAccountSummary returns the balance, unlocked balance and bank balance of a subaccount
func (k Keeper) getAccountSummary(sdkContext sdk.Context, subaccountAddr sdk.AccAddress) (types.AccountSummary, sdkmath.Int, sdk.Coin) {
balance, exists := k.GetAccountSummary(sdkContext, subaccountAddr)
if !exists {
panic("data corruption: subaccount exists but balance does not")
}
Expand All @@ -135,3 +135,26 @@ func (k Keeper) getBalances(sdkContext sdk.Context, subaccountAddr sdk.AccAddres

return balance, unlockedBalance, bankBalance
}

// getBalances returns the balance, unlocked balance and bank balance of a subaccount
func (k Keeper) withdraw(ctx sdk.Context, subAccAddr sdk.AccAddress, ownerAddr sdk.AccAddress) error {
summary, unlockedBalance, bankBalance := k.getAccountSummary(ctx, subAccAddr)

withdrawableBalance := summary.WithdrawableBalance(unlockedBalance, bankBalance.Amount)
if withdrawableBalance.IsZero() {
return types.ErrNothingToWithdraw
}

if err := summary.Withdraw(withdrawableBalance); err != nil {
return err
}

k.SetAccountSummary(ctx, subAccAddr, summary)

err := k.bankKeeper.SendCoins(ctx, subAccAddr, ownerAddr, sdk.NewCoins(sdk.NewCoin(params.DefaultBondDenom, withdrawableBalance)))
if err != nil {
return err
}

return nil
}
28 changes: 14 additions & 14 deletions x/subaccount/keeper/hooks.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ func (k Keeper) Hooks() Hooks { return Hooks{k} }

// AfterBettorWin is subaccount module hook for subaccount bettor winning.
func (h Hooks) AfterBettorWin(ctx sdk.Context, bettor sdk.AccAddress, originalAmount, profit sdkmath.Int) {
balance, exists := h.k.GetBalance(ctx, bettor)
balance, exists := h.k.GetAccountSummary(ctx, bettor)
if !exists {
return
}
Expand All @@ -38,12 +38,12 @@ func (h Hooks) AfterBettorWin(ctx sdk.Context, bettor sdk.AccAddress, originalAm
if err != nil {
panic(err)
}
h.k.SetBalance(ctx, bettor, balance)
h.k.SetAccountSummary(ctx, bettor, balance)
}

// AfterBettorLoss is subaccount module hook for subaccount bettor loss.
func (h Hooks) AfterBettorLoss(ctx sdk.Context, bettor sdk.AccAddress, originalAmount sdkmath.Int) {
balance, exists := h.k.GetBalance(ctx, bettor)
balance, exists := h.k.GetAccountSummary(ctx, bettor)
if !exists {
return
}
Expand All @@ -55,12 +55,12 @@ func (h Hooks) AfterBettorLoss(ctx sdk.Context, bettor sdk.AccAddress, originalA
if err != nil {
panic(err)
}
h.k.SetBalance(ctx, bettor, balance)
h.k.SetAccountSummary(ctx, bettor, balance)
}

// AfterBettorRefund is subaccount module hook for subaccount bettor refund.
func (h Hooks) AfterBettorRefund(ctx sdk.Context, bettor sdk.AccAddress, originalAmount, fee sdkmath.Int) {
balance, exists := h.k.GetBalance(ctx, bettor)
balance, exists := h.k.GetAccountSummary(ctx, bettor)
if !exists {
return
}
Expand All @@ -69,13 +69,13 @@ func (h Hooks) AfterBettorRefund(ctx sdk.Context, bettor sdk.AccAddress, origina
if err != nil {
panic(err)
}
h.k.SetBalance(ctx, bettor, balance)
h.k.SetAccountSummary(ctx, bettor, balance)
}

// AfterHouseWin is subaccount module hook for house winning over subbacount.
func (h Hooks) AfterHouseWin(ctx sdk.Context, house sdk.AccAddress, originalAmount, profit sdkmath.Int) {
// update balance
balance, exists := h.k.GetBalance(ctx, house)
balance, exists := h.k.GetAccountSummary(ctx, house)
if !exists {
return
}
Expand All @@ -84,7 +84,7 @@ func (h Hooks) AfterHouseWin(ctx sdk.Context, house sdk.AccAddress, originalAmou
if err != nil {
panic(err)
}
h.k.SetBalance(ctx, house, balance)
h.k.SetAccountSummary(ctx, house, balance)

// send profits
subAccountOwner, exists := h.k.GetSubAccountOwner(ctx, house)
Expand All @@ -99,7 +99,7 @@ func (h Hooks) AfterHouseWin(ctx sdk.Context, house sdk.AccAddress, originalAmou

// AfterHouseLoss is subaccount module hook for house loss for subbacount.
func (h Hooks) AfterHouseLoss(ctx sdk.Context, house sdk.AccAddress, originalAmount, lostAmt sdkmath.Int) {
balance, exists := h.k.GetBalance(ctx, house)
balance, exists := h.k.GetAccountSummary(ctx, house)
if !exists {
return
}
Expand All @@ -113,12 +113,12 @@ func (h Hooks) AfterHouseLoss(ctx sdk.Context, house sdk.AccAddress, originalAmo
panic(err)
}

h.k.SetBalance(ctx, house, balance)
h.k.SetAccountSummary(ctx, house, balance)
}

// AfterHouseRefund is subaccount module hook for house refund in subaccount deposit.
func (h Hooks) AfterHouseRefund(ctx sdk.Context, house sdk.AccAddress, originalAmount sdkmath.Int) {
balance, exists := h.k.GetBalance(ctx, house)
balance, exists := h.k.GetAccountSummary(ctx, house)
if !exists {
return
}
Expand All @@ -128,12 +128,12 @@ func (h Hooks) AfterHouseRefund(ctx sdk.Context, house sdk.AccAddress, originalA
panic(err)
}

h.k.SetBalance(ctx, house, balance)
h.k.SetAccountSummary(ctx, house, balance)
}

// AfterHouseFeeRefund is subaccount module hook for house fee refund in subaccount deposit.
func (h Hooks) AfterHouseFeeRefund(ctx sdk.Context, house sdk.AccAddress, fee sdkmath.Int) {
balance, exists := h.k.GetBalance(ctx, house)
balance, exists := h.k.GetAccountSummary(ctx, house)
if !exists {
return
}
Expand All @@ -143,5 +143,5 @@ func (h Hooks) AfterHouseFeeRefund(ctx sdk.Context, house sdk.AccAddress, fee sd
panic(err)
}

h.k.SetBalance(ctx, house, balance)
h.k.SetAccountSummary(ctx, house, balance)
}
20 changes: 3 additions & 17 deletions x/subaccount/keeper/msg_server_balance.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (

sdk "github.com/cosmos/cosmos-sdk/types"

"github.com/sge-network/sge/app/params"
"github.com/sge-network/sge/x/subaccount/types"
)

Expand All @@ -27,26 +26,13 @@ func (k msgServer) TopUp(goCtx context.Context, msg *types.MsgTopUp) (*types.Msg
func (k msgServer) WithdrawUnlockedBalances(goCtx context.Context, msg *types.MsgWithdrawUnlockedBalances) (*types.MsgWithdrawUnlockedBalancesResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)

creatorAddr := sdk.MustAccAddressFromBech32(msg.Creator)
subAccAddr, exists := k.keeper.GetSubAccountByOwner(ctx, creatorAddr)
ownerAddr := sdk.MustAccAddressFromBech32(msg.Creator)
subAccAddr, exists := k.keeper.GetSubAccountByOwner(ctx, ownerAddr)
if !exists {
return nil, types.ErrSubaccountDoesNotExist
}

balance, unlockedBalance, bankBalance := k.keeper.getBalances(ctx, subAccAddr)

// calculate withdrawable balance, which is the minimum between the available balance, and
// what has been unlocked so far. Also, it cannot be greater than the bank balance.
// Available reports the deposited amount - spent amount - lost amount - withdrawn amount.
withdrawableBalance := sdk.MinInt(sdk.MinInt(balance.Available(), unlockedBalance), bankBalance.Amount)
if withdrawableBalance.IsZero() {
return nil, types.ErrNothingToWithdraw
}

balance.WithdrawnAmount = balance.WithdrawnAmount.Add(withdrawableBalance)
k.keeper.SetBalance(ctx, subAccAddr, balance)

err := k.keeper.bankKeeper.SendCoins(ctx, subAccAddr, creatorAddr, sdk.NewCoins(sdk.NewCoin(params.DefaultBondDenom, withdrawableBalance)))
err := k.keeper.withdraw(ctx, subAccAddr, ownerAddr)
if err != nil {
return nil, err
}
Expand Down
14 changes: 7 additions & 7 deletions x/subaccount/keeper/msg_server_balance_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,10 @@ func TestMsgServer_WithdrawUnlockedBalances(t *testing.T) {
// we force some money to be spent on the subaccount to correctly test
// that if the amount is unlocked but spent, it will not be withdrawable.
subAccountAddress := types.NewAddressFromSubaccount(1)
subaccountBalance, exists := app.SubaccountKeeper.GetBalance(ctx, subAccountAddress)
subaccountBalance, exists := app.SubaccountKeeper.GetAccountSummary(ctx, subAccountAddress)
require.True(t, exists)
require.NoError(t, subaccountBalance.Spend(sdkmath.NewInt(100)))
app.SubaccountKeeper.SetBalance(ctx, subAccountAddr, subaccountBalance)
app.SubaccountKeeper.SetAccountSummary(ctx, subAccountAddr, subaccountBalance)

ctx = ctx.WithBlockTime(lockedTime2.Add(1 * time.Second))
t.Log("Withdraw unlocked balances, with 2 expires")
Expand All @@ -101,10 +101,10 @@ func TestMsgServer_WithdrawUnlockedBalances(t *testing.T) {
require.Equal(t, sdkmath.NewInt(100), balance.Amount)

t.Log("after unspending the money of the subaccount, the owner will be able to get the money back when withdrawing")
subaccountBalance, exists = app.SubaccountKeeper.GetBalance(ctx, subAccountAddress)
subaccountBalance, exists = app.SubaccountKeeper.GetAccountSummary(ctx, subAccountAddress)
require.True(t, exists)
require.NoError(t, subaccountBalance.Unspend(sdkmath.NewInt(100)))
app.SubaccountKeeper.SetBalance(ctx, subAccountAddr, subaccountBalance)
app.SubaccountKeeper.SetAccountSummary(ctx, subAccountAddr, subaccountBalance)
_, err = msgServer.WithdrawUnlockedBalances(sdk.WrapSDKContext(ctx), &types.MsgWithdrawUnlockedBalances{
Creator: subaccountOwner.String(),
})
Expand All @@ -113,7 +113,7 @@ func TestMsgServer_WithdrawUnlockedBalances(t *testing.T) {
// check balances
balance = app.BankKeeper.GetBalance(ctx, subAccountAddr, "usge")
require.Equal(t, sdkmath.NewInt(0), balance.Amount)
subaccountBalance, exists = app.SubaccountKeeper.GetBalance(ctx, subAccountAddress)
subaccountBalance, exists = app.SubaccountKeeper.GetAccountSummary(ctx, subAccountAddress)
require.True(t, exists)
require.Equal(t, sdkmath.NewInt(300), subaccountBalance.WithdrawnAmount)

Expand Down Expand Up @@ -181,7 +181,7 @@ func TestMsgServerTopUp_HappyPath(t *testing.T) {

subAccountAddr := types.NewAddressFromSubaccount(1)

balance, exists := k.GetBalance(ctx, subAccountAddr)
balance, exists := k.GetAccountSummary(ctx, subAccountAddr)
require.True(t, exists)
require.Equal(t, sdkmath.NewInt(0), balance.DepositedAmount)
balances := k.GetLockedBalances(ctx, subAccountAddr)
Expand All @@ -201,7 +201,7 @@ func TestMsgServerTopUp_HappyPath(t *testing.T) {
require.NoError(t, err)

// Check balance
balance, exists = k.GetBalance(ctx, subAccountAddr)
balance, exists = k.GetAccountSummary(ctx, subAccountAddr)
require.True(t, exists)
require.Equal(t, sdkmath.NewInt(123), balance.DepositedAmount)
balances = k.GetLockedBalances(ctx, subAccountAddr)
Expand Down
Loading

0 comments on commit 26ff3f9

Please sign in to comment.