Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add settlement events #564

Merged
merged 3 commits into from
Feb 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 57 additions & 2 deletions e2e/tests/virtualgroup_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"math"
"reflect"
"strconv"
"strings"
"testing"
"time"

Expand Down Expand Up @@ -287,7 +288,7 @@ func (s *VirtualGroupTestSuite) TestSettle() {
StorageProvider: user.GetAddr().String(),
GlobalVirtualGroupFamilyId: gvgFamily.Id,
}
s.SendTxBlock(user, &msgSettle)
txResp1 := s.SendTxBlock(user, &msgSettle)

primaryBalanceAfter, err := s.Client.BankQueryClient.Balance(context.Background(), &types2.QueryBalanceRequest{
Denom: s.Config.Denom, Address: primarySp.FundingKey.GetAddr().String(),
Expand All @@ -297,13 +298,18 @@ func (s *VirtualGroupTestSuite) TestSettle() {
s.T().Logf("primaryBalance: %s, after: %s", primaryBalance.String(), primaryBalanceAfter.String())
s.Require().True(primaryBalanceAfter.Balance.Amount.GT(primaryBalance.Balance.Amount))

settleGVGFamilyEvent := filterSettleGVGFamilyEventFromTx(txResp1)
s.Require().True(settleGVGFamilyEvent.Id == gvgFamilyId)
s.Require().True(settleGVGFamilyEvent.SpId == gvgFamily.PrimarySpId)
s.Require().True(settleGVGFamilyEvent.Amount.Equal(primaryBalanceAfter.Balance.Amount.Sub(primaryBalance.Balance.Amount)))

// settle gvg
msgSettle = virtualgroupmoduletypes.MsgSettle{
StorageProvider: user.GetAddr().String(),
GlobalVirtualGroupFamilyId: 0,
GlobalVirtualGroupIds: []uint32{gvgId},
}
s.SendTxBlock(user, &msgSettle)
txResp2 := s.SendTxBlock(user, &msgSettle)

secondaryBalancesAfter := make([]sdkmath.Int, 0, len(secondaryBalances))
for _, addr := range secondarySpAddrs {
Expand All @@ -314,9 +320,12 @@ func (s *VirtualGroupTestSuite) TestSettle() {
secondaryBalancesAfter = append(secondaryBalancesAfter, tempResp.Balance.Amount)
}

settleGVGEvent := filterSettleGVGEventFromTx(txResp2)
s.Require().True(settleGVGEvent.Id == gvgId)
for i := range secondaryBalances {
s.T().Logf("secondaryBalance: %s, after: %s", secondaryBalances[i].String(), secondaryBalancesAfter[i].String())
s.Require().True(secondaryBalancesAfter[i].GT(secondaryBalances[i]))
s.Require().True(settleGVGEvent.Amount.Equal(secondaryBalancesAfter[i].Sub(secondaryBalances[i])))
}
}

Expand Down Expand Up @@ -1316,3 +1325,49 @@ func (s *VirtualGroupTestSuite) TestSPExit_SwapInfo_Expired() {
_, err = s.Client.StorageProvider(context.Background(), &sptypes.QueryStorageProviderRequest{Id: spy.Info.Id})
s.Require().Error(err)
}

func filterSettleGVGEventFromTx(txRes *sdk.TxResponse) virtualgroupmoduletypes.EventSettleGlobalVirtualGroup {
idStr, amountStr := "", ""
for _, event := range txRes.Logs[0].Events {
if event.Type == "greenfield.virtualgroup.EventSettleGlobalVirtualGroup" {
for _, attr := range event.Attributes {
if attr.Key == "id" {
idStr = strings.Trim(attr.Value, `"`)
} else if attr.Key == "amount" {
amountStr = strings.Trim(attr.Value, `"`)
}
}
}
}
id, _ := strconv.ParseInt(idStr, 10, 32)
amount := sdkmath.NewUintFromString(amountStr)
return virtualgroupmoduletypes.EventSettleGlobalVirtualGroup{
Id: uint32(id),
Amount: sdkmath.NewInt(int64(amount.Uint64())),
}
}

func filterSettleGVGFamilyEventFromTx(txRes *sdk.TxResponse) virtualgroupmoduletypes.EventSettleGlobalVirtualGroupFamily {
idStr, spIdStr, amountStr := "", "", ""
for _, event := range txRes.Logs[0].Events {
if event.Type == "greenfield.virtualgroup.EventSettleGlobalVirtualGroupFamily" {
for _, attr := range event.Attributes {
if attr.Key == "id" {
idStr = strings.Trim(attr.Value, `"`)
} else if attr.Key == "sp_id" {
spIdStr = strings.Trim(attr.Value, `"`)
} else if attr.Key == "amount" {
amountStr = strings.Trim(attr.Value, `"`)
}
}
}
}
id, _ := strconv.ParseInt(idStr, 10, 32)
spId, _ := strconv.ParseInt(spIdStr, 10, 32)
amount := sdkmath.NewUintFromString(amountStr)
return virtualgroupmoduletypes.EventSettleGlobalVirtualGroupFamily{
Id: uint32(id),
SpId: uint32(spId),
Amount: sdkmath.NewInt(int64(amount.Uint64())),
}
}
32 changes: 31 additions & 1 deletion proto/greenfield/virtualgroup/events.proto
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ message EventCompleteStorageProviderExit {
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
(gogoproto.nullable) = false
];
// forced_exit whether the exit is a forced exit
// forced_exit whether the exit is a forced exit
bool forced_exit = 5;
}

Expand Down Expand Up @@ -218,3 +218,33 @@ message EventStorageProviderForcedExit {
// The id of the storage provider who wants to exit
uint32 storage_provider_id = 1;
}

message EventSettleGlobalVirtualGroupFamily {
// The id of global virtual group family, which is auto generated by blockchain
uint32 id = 1;
// The id of the primary sp who will receive the fund
uint32 sp_id = 2;
// The funding address of the sp
string sp_funding_address = 3 [(cosmos_proto.scalar) = "cosmos.AddressString"];
// The amount the fund to send to sp
string amount = 4 [
(cosmos_proto.scalar) = "cosmos.Int",
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
(gogoproto.nullable) = false
];
}

message EventSettleGlobalVirtualGroup {
// The id of global virtual group, which is auto generated by blockchain
uint32 id = 1;
// The ids of the secondary sps who will receive the fund
repeated uint32 sp_ids = 2;
// The funding address of the sps
repeated string sp_funding_addresses = 3 [(cosmos_proto.scalar) = "cosmos.AddressString"];
// The amount the fund to send to each sp
string amount = 4 [
(cosmos_proto.scalar) = "cosmos.Int",
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
(gogoproto.nullable) = false
];
}
25 changes: 25 additions & 0 deletions x/virtualgroup/keeper/payment.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,16 @@ func (k Keeper) SettleAndDistributeGVGFamily(ctx sdk.Context, sp *sptypes.Storag
return fmt.Errorf("fail to send coins: %s %s", paymentAddress, sp.FundingAddress)
}

err = ctx.EventManager().EmitTypedEvent(&types.EventSettleGlobalVirtualGroupFamily{
Id: family.Id,
SpId: sp.Id,
SpFundingAddress: sp.FundingAddress,
Amount: totalBalance,
})
if err != nil {
ctx.Logger().Error("fail to send event for settlement", "vfg", family.Id, "err", err)
}

return nil
}

Expand All @@ -38,6 +48,8 @@ func (k Keeper) SettleAndDistributeGVG(ctx sdk.Context, gvg *types.GlobalVirtual
if !amount.IsPositive() {
return nil
}

fundingAddresses := make([]string, 0)
for _, spID := range gvg.SecondarySpIds {
sp, found := k.spKeeper.GetStorageProvider(ctx, spID)
if !found {
Expand All @@ -47,6 +59,19 @@ func (k Keeper) SettleAndDistributeGVG(ctx sdk.Context, gvg *types.GlobalVirtual
if err != nil {
return fmt.Errorf("fail to send coins: %s %s", paymentAddress, sp.FundingAddress)
}

fundingAddresses = append(fundingAddresses, sp.FundingAddress)
}

err = ctx.EventManager().EmitTypedEvent(&types.EventSettleGlobalVirtualGroup{
Id: gvg.Id,
SpIds: gvg.SecondarySpIds,
SpFundingAddresses: fundingAddresses,
Amount: amount,
})
if err != nil {
ctx.Logger().Error("fail to send event for settlement", "gvg", gvg.Id, "err", err)
}

return nil
}
Loading
Loading