Skip to content

Commit

Permalink
feat: deposit balance of bank account to payment account
Browse files Browse the repository at this point in the history
  • Loading branch information
yutianwu committed Aug 24, 2023
1 parent 20bbf61 commit 924e9da
Show file tree
Hide file tree
Showing 10 changed files with 163 additions and 13 deletions.
2 changes: 1 addition & 1 deletion app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -527,7 +527,7 @@ func New(
encodingConfig.TxConfig),
auth.NewAppModule(appCodec, app.AccountKeeper, nil, nil),
authzmodule.NewAppModule(appCodec, app.AuthzKeeper, app.AccountKeeper, app.BankKeeper, app.interfaceRegistry),
bank.NewAppModule(appCodec, app.BankKeeper, app.AccountKeeper, nil),
bank.NewAppModule(appCodec, app.BankKeeper, app.AccountKeeper, app.PaymentKeeper, nil),
feegrantmodule.NewAppModule(appCodec, app.AccountKeeper, app.BankKeeper, app.FeeGrantKeeper, app.interfaceRegistry),
gov.NewAppModule(appCodec, &app.GovKeeper, app.AccountKeeper, app.BankKeeper, nil),
slashing.NewAppModule(appCodec, app.SlashingKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper, nil),
Expand Down
22 changes: 21 additions & 1 deletion app/upgrade.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ package app

import (
serverconfig "github.com/cosmos/cosmos-sdk/server/config"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/module"
upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types"
)

func (app *App) RegisterUpgradeHandlers(chainID string, serverCfg *serverconfig.Config) error {
Expand All @@ -12,7 +15,7 @@ func (app *App) RegisterUpgradeHandlers(chainID string, serverCfg *serverconfig.
}

// Register the upgrade handlers here
// app.registerPublicDelegationUpgradeHandler()
app.registerNagquUpgradeHandler()
// app.register...()
// ...
return nil
Expand All @@ -36,3 +39,20 @@ func (app *App) RegisterUpgradeHandlers(chainID string, serverCfg *serverconfig.
// },
// )
// }

func (app *App) registerNagquUpgradeHandler() {
// Register the upgrade handler
app.UpgradeKeeper.SetUpgradeHandler(upgradetypes.Nagqu,
func(ctx sdk.Context, plan upgradetypes.Plan, fromVM module.VersionMap) (module.VersionMap, error) {
app.Logger().Info("upgrade to ", plan.Name)
return fromVM, nil
})

// Register the upgrade initializer
app.UpgradeKeeper.SetUpgradeInitializer(upgradetypes.Nagqu,
func() error {
app.Logger().Info("Init enable public delegation upgrade")
return nil
},
)
}
1 change: 1 addition & 0 deletions deployment/localup/localup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ function generate_genesis() {
sed -i -e "s/src-chain-id = 1/src-chain-id = ${SRC_CHAIN_ID}/g" ${workspace}/.local/validator${i}/config/app.toml
sed -i -e "s/dest-bsc-chain-id = 2/dest-bsc-chain-id = ${DEST_CHAIN_ID}/g" ${workspace}/.local/validator${i}/config/app.toml
sed -i -e "s/snapshot-keep-recent = 2/snapshot-keep-recent = ${SNAPSHOT_KEEP_RECENT}/g" ${workspace}/.local/validator${i}/config/app.toml
echo -e '[[upgrade]]\nname = "Nagqu"\nheight = 1\ninfo = ""' >> ${workspace}/.local/validator${i}/config/app.toml
sed -i -e "s/\"reserve_time\": \"15552000\"/\"reserve_time\": \"60\"/g" ${workspace}/.local/validator${i}/config/genesis.json
sed -i -e "s/\"forced_settle_time\": \"86400\"/\"forced_settle_time\": \"30\"/g" ${workspace}/.local/validator${i}/config/genesis.json
sed -i -e "s/172800s/${DEPOSIT_VOTE_PERIOD}/g" ${workspace}/.local/validator${i}/config/genesis.json
Expand Down
63 changes: 63 additions & 0 deletions e2e/tests/payment_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package tests
import (
"bytes"
"context"
"encoding/binary"
"fmt"
"math"
"reflect"
Expand All @@ -12,6 +13,7 @@ import (

sdkmath "cosmossdk.io/math"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/address"
"github.com/cosmos/cosmos-sdk/types/query"
"github.com/cosmos/cosmos-sdk/types/tx"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
Expand Down Expand Up @@ -375,6 +377,67 @@ func (s *PaymentTestSuite) TestDeposit_ActiveAccount() {
s.Require().Equal(paymentAccountBNBNeeded.MulRaw(3), settledBalance.Add(paymentAccountStreamRecordAfter.StaticBalance.Add(paymentAccountStreamRecordAfter.BufferBalance)))
}

func (s *PaymentTestSuite) TestDeposit_FromBankAccount() {
ctx := context.Background()
user := s.GenAndChargeAccounts(1, 1000000)[0]
userAddr := user.GetAddr().String()
var err error

// derive payment account
paymentAccount := derivePaymentAccount(user.GetAddr(), 0)
// transfer BNB to derived payment account
msgSend := banktypes.NewMsgSend(user.GetAddr(), paymentAccount, sdk.NewCoins(
sdk.NewCoin(s.Config.Denom, sdk.NewInt(1e18)),
))
_ = s.SendTxBlock(user, msgSend)

paymentBalanceBefore, err := s.Client.Balance(ctx, &banktypes.QueryBalanceRequest{
Address: paymentAccount.String(),
Denom: s.Config.Denom,
})
s.Require().NoError(err)
s.Require().Equal(sdk.NewInt(1e18).String(), paymentBalanceBefore.GetBalance().Amount.String())

// create payment account and deposit
msgCreatePaymentAccount := &paymenttypes.MsgCreatePaymentAccount{
Creator: userAddr,
}
_ = s.SendTxBlock(user, msgCreatePaymentAccount)
paymentAccountsReq := &paymenttypes.QueryPaymentAccountsByOwnerRequest{Owner: userAddr}
paymentAccounts, err := s.Client.PaymentQueryClient.PaymentAccountsByOwner(ctx, paymentAccountsReq)
s.Require().NoError(err)
s.T().Logf("paymentAccounts %s", core.YamlString(paymentAccounts))
paymentAddr := paymentAccounts.PaymentAccounts[0]
s.Require().Lenf(paymentAccounts.PaymentAccounts, 1, "paymentAccounts %s", core.YamlString(paymentAccounts))

// transfer BNB to payment account: should not success
msgSend = banktypes.NewMsgSend(user.GetAddr(), sdk.MustAccAddressFromHex(paymentAddr), sdk.NewCoins(
sdk.NewCoin(s.Config.Denom, sdk.NewInt(1e18)),
))
s.SendTxBlockWithExpectErrorString(msgSend, user, "is not allowed to receive funds")

// deposit BNB needed
msgDeposit := &paymenttypes.MsgDeposit{
Creator: user.GetAddr().String(),
To: paymentAddr,
Amount: sdk.NewInt(1e18), // deposit more than needed
}
_ = s.SendTxBlock(user, msgDeposit)

paymentBalanceAfter, err := s.Client.Balance(ctx, &banktypes.QueryBalanceRequest{
Address: paymentAddr,
Denom: s.Config.Denom,
})
s.Require().NoError(err)
s.Require().Equal(sdk.NewInt(0).String(), paymentBalanceAfter.GetBalance().Amount.String())
}

func derivePaymentAccount(owner sdk.AccAddress, index uint64) sdk.AccAddress {
b := make([]byte, 8)
binary.LittleEndian.PutUint64(b, index)
return address.Derive(owner.Bytes(), b)[:sdk.EthAddressLength]
}

func (s *PaymentTestSuite) TestDeposit_ResumeInOneBlock() {
ctx := context.Background()
sp := s.PickStorageProvider()
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ replace (
github.com/cometbft/cometbft => github.com/bnb-chain/greenfield-cometbft v0.0.3-alpha.1
github.com/cometbft/cometbft-db => github.com/bnb-chain/greenfield-cometbft-db v0.8.1-alpha.1
github.com/confio/ics23/go => github.com/cosmos/cosmos-sdk/ics23/go v0.8.0
github.com/cosmos/cosmos-sdk => github.com/bnb-chain/greenfield-cosmos-sdk v0.2.4-alpha.2
github.com/cosmos/cosmos-sdk => github.com/yutianwu/greenfield-cosmos-sdk v0.0.0-20230824025053-97f0d0e407b2
github.com/cosmos/iavl => github.com/bnb-chain/greenfield-iavl v0.20.1
github.com/syndtr/goleveldb => github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7
)
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -163,8 +163,6 @@ github.com/bnb-chain/greenfield-cometbft v0.0.3-alpha.1 h1:nCLXxYdkDIh5bQMxtb14T
github.com/bnb-chain/greenfield-cometbft v0.0.3-alpha.1/go.mod h1:3nGT4Z9fHwgRlBY/rofn0rSarnIcNbuhz/eq0XlLlkg=
github.com/bnb-chain/greenfield-cometbft-db v0.8.1-alpha.1 h1:XcWulGacHVRiSCx90Q8Y//ajOrLNBQWR/KDB89dy3cU=
github.com/bnb-chain/greenfield-cometbft-db v0.8.1-alpha.1/go.mod h1:ey1CiK4bYo1RBNJLRiVbYr5CMdSxci9S/AZRINLtppI=
github.com/bnb-chain/greenfield-cosmos-sdk v0.2.4-alpha.2 h1:mCojTDXd//s34SiHqRolG7saZSG9YHQ9WzPFF8rL4Zo=
github.com/bnb-chain/greenfield-cosmos-sdk v0.2.4-alpha.2/go.mod h1:2jk2ijERIAv8wxQ/IJSmzQKazCnR6YGvICk4O1YrT9M=
github.com/bnb-chain/greenfield-cosmos-sdk/api v0.0.0-20230816082903-b48770f5e210 h1:GHPbV2bC+gmuO6/sG0Tm8oGal3KKSRlyE+zPscDjlA8=
github.com/bnb-chain/greenfield-cosmos-sdk/api v0.0.0-20230816082903-b48770f5e210/go.mod h1:vhsZxXE9tYJeYB5JR4hPhd6Pc/uPf7j1T8IJ7p9FdeM=
github.com/bnb-chain/greenfield-cosmos-sdk/math v0.0.0-20230816082903-b48770f5e210 h1:FLVOn4+OVbsKi2+YJX5kmD27/4dRu4FW7xCXFhzDO5s=
Expand Down Expand Up @@ -1425,6 +1423,8 @@ github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yutianwu/greenfield-cosmos-sdk v0.0.0-20230824025053-97f0d0e407b2 h1:Cbha83MgA1+bNF0DK1A4lSBTwBr5Wu0+1miLDlNhHnw=
github.com/yutianwu/greenfield-cosmos-sdk v0.0.0-20230824025053-97f0d0e407b2/go.mod h1:2jk2ijERIAv8wxQ/IJSmzQKazCnR6YGvICk4O1YrT9M=
github.com/zondax/hid v0.9.1 h1:gQe66rtmyZ8VeGFcOpbuH3r7erYtNEAezCAYu8LdkJo=
github.com/zondax/hid v0.9.1/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM=
github.com/zondax/ledger-go v0.14.1 h1:Pip65OOl4iJ84WTpA4BKChvOufMhhbxED3BaihoZN4c=
Expand Down
10 changes: 8 additions & 2 deletions types/openapiutil/apiconsole.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,21 @@ var index embed.FS

// Handler returns a http handler that servers OpenAPI console for an OpenAPI spec at specURL.
func Handler(title, specURL string) http.HandlerFunc {
t, _ := template.ParseFS(index, "index.tpl")
t, err := template.ParseFS(index, "index.tpl")
if err != nil {
panic(err)
}

return func(w http.ResponseWriter, req *http.Request) {
_ = t.Execute(w, struct {
err := t.Execute(w, struct {
Title string
URL string
}{
title,
specURL,
})
if err != nil {
panic(err)
}
}
}
25 changes: 19 additions & 6 deletions x/payment/keeper/msg_server_deposit.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"

sdk "github.com/cosmos/cosmos-sdk/types"
upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types"

"github.com/bnb-chain/greenfield/x/payment/types"
)
Expand All @@ -14,11 +15,23 @@ func (k msgServer) Deposit(goCtx context.Context, msg *types.MsgDeposit) (*types
// bank transfer
creator := sdk.MustAccAddressFromHex(msg.Creator)
to := sdk.MustAccAddressFromHex(msg.To)
coins := sdk.NewCoins(sdk.NewCoin(k.GetParams(ctx).FeeDenom, msg.Amount))
err := k.bankKeeper.SendCoinsFromAccountToModule(ctx, creator, types.ModuleName, coins)
depositAmount := msg.Amount
coinsToDeposit := sdk.NewCoins(sdk.NewCoin(k.GetParams(ctx).FeeDenom, depositAmount))
err := k.bankKeeper.SendCoinsFromAccountToModule(ctx, creator, types.ModuleName, coinsToDeposit)
if err != nil {
return nil, err
}
if ctx.IsUpgraded(upgradetypes.Nagqu) && k.IsPaymentAccount(ctx, to) {
balanceOfToAccount := k.bankKeeper.GetBalance(ctx, to, k.GetParams(ctx).FeeDenom)
if balanceOfToAccount.IsPositive() {
err := k.bankKeeper.SendCoinsFromAccountToModule(ctx, to, types.ModuleName, sdk.NewCoins(balanceOfToAccount))
if err != nil {
return nil, err
}
depositAmount = depositAmount.Add(balanceOfToAccount.Amount)
}
}

// change payment record
streamRecord, found := k.GetStreamRecord(ctx, to)

Expand All @@ -30,20 +43,20 @@ func (k msgServer) Deposit(goCtx context.Context, msg *types.MsgDeposit) (*types
}
streamRecord.Account = msg.To
streamRecord.CrudTimestamp = ctx.BlockTime().Unix()
streamRecord.StaticBalance = msg.Amount
streamRecord.StaticBalance = depositAmount
k.SetStreamRecord(ctx, streamRecord)
} else {
if streamRecord.Status == types.STREAM_ACCOUNT_STATUS_ACTIVE {
// add static balance
change := types.NewDefaultStreamRecordChangeWithAddr(to).WithStaticBalanceChange(msg.Amount)
change := types.NewDefaultStreamRecordChangeWithAddr(to).WithStaticBalanceChange(depositAmount)
err = k.UpdateStreamRecord(ctx, streamRecord, change)
if err != nil {
return nil, err
}
k.SetStreamRecord(ctx, streamRecord)
} else if streamRecord.Status == types.STREAM_ACCOUNT_STATUS_FROZEN {
// deposit and try resume the account
err = k.TryResumeStreamRecord(ctx, streamRecord, msg.Amount)
err = k.TryResumeStreamRecord(ctx, streamRecord, depositAmount)
if err != nil {
return nil, err
}
Expand All @@ -56,7 +69,7 @@ func (k msgServer) Deposit(goCtx context.Context, msg *types.MsgDeposit) (*types
event := types.EventDeposit{
From: creator.String(),
To: to.String(),
Amount: msg.Amount,
Amount: depositAmount,
}
err = ctx.EventManager().EmitTypedEvents(&event)
if err != nil {
Expand Down
35 changes: 35 additions & 0 deletions x/payment/keeper/msg_server_deposit_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,41 @@ func (s *TestSuite) TestDeposit_ToBankAccount() {
s.Require().True(record.StaticBalance.Int64() == msg.Amount.Int64())
}

func (s *TestSuite) TestDeposit_ToPaymentAccountAccount() {
s.bankKeeper.EXPECT().SendCoinsFromAccountToModule(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).
Return(nil).AnyTimes()
s.accountKeeper.EXPECT().HasAccount(gomock.Any(), gomock.Any()).
Return(true).AnyTimes()

// deposit to self
owner := sample.RandAccAddress()
paymentAddress := s.paymentKeeper.DerivePaymentAccountAddress(owner, 0)
paymentAccount1 := &types.PaymentAccount{
Owner: owner.String(),
Addr: paymentAddress.String(),
Refundable: true,
}

s.ctx = s.ctx.WithBlockHeight(10)

// set
s.paymentKeeper.SetPaymentAccount(s.ctx, paymentAccount1)

msg := types.NewMsgDeposit(owner.String(), paymentAddress.String(), sdkmath.NewInt(1000))
_, err := s.msgServer.Deposit(s.ctx, msg)
s.Require().NoError(err)
record, _ := s.paymentKeeper.GetStreamRecord(s.ctx, owner)
s.Require().True(record.StaticBalance.Int64() == msg.Amount.Int64())

// deposit to other account
to := sample.RandAccAddress()
msg = types.NewMsgDeposit(owner.String(), to.String(), sdkmath.NewInt(1000))
_, err = s.msgServer.Deposit(s.ctx, msg)
s.Require().NoError(err)
record, _ = s.paymentKeeper.GetStreamRecord(s.ctx, to)
s.Require().True(record.StaticBalance.Int64() == msg.Amount.Int64())
}

func (s *TestSuite) TestDeposit_ToActiveStreamRecord() {
s.bankKeeper.EXPECT().SendCoinsFromAccountToModule(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).
Return(nil).AnyTimes()
Expand Down
12 changes: 12 additions & 0 deletions x/payment/keeper/payment_account.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,18 @@ func (k Keeper) GetPaymentAccount(
return val, true
}

// IsPaymentAccount returns is the account address a payment account
func (k Keeper) IsPaymentAccount(
ctx sdk.Context,
addr sdk.AccAddress,
) bool {
store := prefix.NewStore(ctx.KVStore(k.storeKey), types.PaymentAccountKeyPrefix)
b := store.Get(types.PaymentAccountKey(
addr,
))
return b != nil
}

// GetAllPaymentAccount returns all paymentAccount
func (k Keeper) GetAllPaymentAccount(ctx sdk.Context) (list []types.PaymentAccount) {
store := prefix.NewStore(ctx.KVStore(k.storeKey), types.PaymentAccountKeyPrefix)
Expand Down

0 comments on commit 924e9da

Please sign in to comment.