Skip to content

Commit

Permalink
chore: emit tokens as json marshalled strings. (#6495)
Browse files Browse the repository at this point in the history
* chore: emit tokens as json marshalled strings.

* chore: emit denom as json, add generic func to marshal em.

* chore: return a string, since we always cast to one.
  • Loading branch information
DimitrisJim authored Jun 5, 2024
1 parent 9e9376a commit ead6127
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 137 deletions.
31 changes: 26 additions & 5 deletions modules/apps/transfer/internal/events/events.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package events

import (
"encoding/json"
"fmt"

sdk "github.com/cosmos/cosmos-sdk/types"
Expand All @@ -11,12 +12,14 @@ import (

// EmitTransferEvent emits a ibc transfer event on successful transfers.
func EmitTransferEvent(ctx sdk.Context, sender, receiver string, tokens types.Tokens, memo string) {
jsonTokens := mustMarshalType[types.Tokens](tokens)

ctx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
types.EventTypeTransfer,
sdk.NewAttribute(types.AttributeKeySender, sender),
sdk.NewAttribute(types.AttributeKeyReceiver, receiver),
sdk.NewAttribute(types.AttributeKeyTokens, tokens.String()),
sdk.NewAttribute(types.AttributeKeyTokens, jsonTokens),
sdk.NewAttribute(types.AttributeKeyMemo, memo),
),
sdk.NewEvent(
Expand All @@ -28,10 +31,12 @@ func EmitTransferEvent(ctx sdk.Context, sender, receiver string, tokens types.To

// EmitOnRecvPacketEvent emits a fungible token packet event in the OnRecvPacket callback
func EmitOnRecvPacketEvent(ctx sdk.Context, packetData types.FungibleTokenPacketDataV2, ack channeltypes.Acknowledgement, ackErr error) {
jsonTokens := mustMarshalType[types.Tokens](types.Tokens(packetData.Tokens))

eventAttributes := []sdk.Attribute{
sdk.NewAttribute(types.AttributeKeySender, packetData.Sender),
sdk.NewAttribute(types.AttributeKeyReceiver, packetData.Receiver),
sdk.NewAttribute(types.AttributeKeyTokens, types.Tokens(packetData.Tokens).String()),
sdk.NewAttribute(types.AttributeKeyTokens, jsonTokens),
sdk.NewAttribute(types.AttributeKeyMemo, packetData.Memo),
sdk.NewAttribute(types.AttributeKeyAckSuccess, fmt.Sprintf("%t", ack.Success())),
}
Expand All @@ -54,12 +59,14 @@ func EmitOnRecvPacketEvent(ctx sdk.Context, packetData types.FungibleTokenPacket

// EmitOnAcknowledgementPacketEvent emits a fungible token packet event in the OnAcknowledgementPacket callback
func EmitOnAcknowledgementPacketEvent(ctx sdk.Context, packetData types.FungibleTokenPacketDataV2, ack channeltypes.Acknowledgement) {
jsonTokens := mustMarshalType[types.Tokens](types.Tokens(packetData.Tokens))

ctx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
types.EventTypePacket,
sdk.NewAttribute(sdk.AttributeKeySender, packetData.Sender),
sdk.NewAttribute(types.AttributeKeyReceiver, packetData.Receiver),
sdk.NewAttribute(types.AttributeKeyTokens, types.Tokens(packetData.Tokens).String()),
sdk.NewAttribute(types.AttributeKeyTokens, jsonTokens),
sdk.NewAttribute(types.AttributeKeyMemo, packetData.Memo),
sdk.NewAttribute(types.AttributeKeyAck, ack.String()),
),
Expand Down Expand Up @@ -89,11 +96,13 @@ func EmitOnAcknowledgementPacketEvent(ctx sdk.Context, packetData types.Fungible

// EmitOnTimeoutPacketEvent emits a fungible token packet event in the OnTimeoutPacket callback
func EmitOnTimeoutEvent(ctx sdk.Context, packetData types.FungibleTokenPacketDataV2) {
jsonTokens := mustMarshalType[types.Tokens](types.Tokens(packetData.Tokens))

ctx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
types.EventTypeTimeout,
sdk.NewAttribute(types.AttributeKeyReceiver, packetData.Sender),
sdk.NewAttribute(types.AttributeKeyRefundTokens, types.Tokens(packetData.Tokens).String()),
sdk.NewAttribute(types.AttributeKeyRefundTokens, jsonTokens),
sdk.NewAttribute(types.AttributeKeyMemo, packetData.Memo),
),
sdk.NewEvent(
Expand All @@ -105,11 +114,23 @@ func EmitOnTimeoutEvent(ctx sdk.Context, packetData types.FungibleTokenPacketDat

// EmitDenomEvent emits a denomination event in the OnRecv callback.
func EmitDenomEvent(ctx sdk.Context, token types.Token) {
jsonDenom := mustMarshalType[types.Denom](token.Denom)

ctx.EventManager().EmitEvent(
sdk.NewEvent(
types.EventTypeDenom,
sdk.NewAttribute(types.AttributeKeyDenomHash, token.Denom.Hash().String()),
sdk.NewAttribute(types.AttributeKeyDenomHash, jsonDenom),
sdk.NewAttribute(types.AttributeKeyDenom, token.Denom.String()),
),
)
}

// mustMarshalType json marshals the given type and panics on failure.
func mustMarshalType[T any](v T) string {
bz, err := json.Marshal(v)
if err != nil {
panic(err)
}

return string(bz)
}
21 changes: 14 additions & 7 deletions modules/apps/transfer/keeper/msg_server_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package keeper_test

import (
"encoding/json"
"errors"
"strings"

Expand Down Expand Up @@ -204,26 +205,32 @@ func (suite *KeeperTestSuite) TestMsgTransfer() {
tc.malleate()

ctx := suite.chainA.GetContext()
res, err := suite.chainA.GetSimApp().TransferKeeper.Transfer(ctx, msg)

// Verify events
events := ctx.EventManager().Events().ToABCIEvents()

var tokens []types.Token
token1, _ := suite.chainA.GetSimApp().TransferKeeper.TokenFromCoin(ctx, coin1)
token1, err := suite.chainA.GetSimApp().TransferKeeper.TokenFromCoin(ctx, coin1)
suite.Require().NoError(err)
tokens = append(tokens, token1)

var expEvents []abci.Event
if tc.multiDenom {
token2, _ := suite.chainA.GetSimApp().TransferKeeper.TokenFromCoin(ctx, coin2)
token2, err := suite.chainA.GetSimApp().TransferKeeper.TokenFromCoin(ctx, coin2)
suite.Require().NoError(err)
tokens = append(tokens, token2)
}

jsonTokens, err := json.Marshal(types.Tokens(tokens))
suite.Require().NoError(err)

res, err := suite.chainA.GetSimApp().TransferKeeper.Transfer(ctx, msg)

// Verify events
events := ctx.EventManager().Events().ToABCIEvents()

expEvents = sdk.Events{
sdk.NewEvent(types.EventTypeTransfer,
sdk.NewAttribute(types.AttributeKeySender, msg.Sender),
sdk.NewAttribute(types.AttributeKeyReceiver, msg.Receiver),
sdk.NewAttribute(types.AttributeKeyTokens, types.Tokens(tokens).String()),
sdk.NewAttribute(types.AttributeKeyTokens, string(jsonTokens)),
sdk.NewAttribute(types.AttributeKeyMemo, msg.Memo),
),
sdk.NewEvent(
Expand Down
27 changes: 3 additions & 24 deletions modules/apps/transfer/types/token.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
package types

import (
"strings"

errorsmod "cosmossdk.io/errors"
sdkmath "cosmossdk.io/math"
)

// Tokens is a slice of Tokens
type Tokens []Token

// Validate validates a token denomination and amount.
func (t Token) Validate() error {
if err := t.Denom.Validate(); err != nil {
Expand All @@ -24,25 +25,3 @@ func (t Token) Validate() error {

return nil
}

// Tokens is a set of Token
type Tokens []Token

// String prints out the tokens array as a string.
// If the array is empty, an empty string is returned
func (tokens Tokens) String() string {
if len(tokens) == 0 {
return ""
} else if len(tokens) == 1 {
return tokens[0].String()
}

var out strings.Builder
for _, token := range tokens[:len(tokens)-1] {
out.WriteString(token.String()) // nolint:revive // no error returned by WriteString
out.WriteByte(',') //nolint:revive // no error returned by WriteByte

}
out.WriteString(tokens[len(tokens)-1].String()) //nolint:revive
return out.String()
}
101 changes: 0 additions & 101 deletions modules/apps/transfer/types/token_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,104 +149,3 @@ func TestValidate(t *testing.T) {
})
}
}

func TestTokens_String(t *testing.T) {
cases := []struct {
name string
input Tokens
expected string
}{
{
"empty tokens",
Tokens{},
"",
},
{
"single token, no trace",
Tokens{
Token{
Denom: Denom{
Base: "tree",
Trace: []Trace{},
},
Amount: "1",
},
},
`denom:<base:"tree" > amount:"1" `,
},
{
"single token with trace",
Tokens{
Token{
Denom: Denom{
Base: "tree",
Trace: []Trace{
NewTrace("portid", "channelid"),
},
},
Amount: "1",
},
},
`denom:<base:"tree" trace:<port_id:"portid" channel_id:"channelid" > > amount:"1" `,
},
{
"multiple tokens, no trace",
Tokens{
Token{
Denom: Denom{
Base: "tree",
},
Amount: "1",
},
Token{
Denom: Denom{
Base: "gas",
},
Amount: "2",
},
Token{
Denom: Denom{
Base: "mineral",
},
Amount: "3",
},
},
`denom:<base:"tree" > amount:"1" ,denom:<base:"gas" > amount:"2" ,denom:<base:"mineral" > amount:"3" `,
},
{
"multiple tokens, trace and no trace",
Tokens{
Token{
Denom: Denom{
Base: "tree",
},
Amount: "1",
},
Token{
Denom: Denom{
Base: "gas",
Trace: []Trace{
NewTrace("portid", "channelid"),
},
},
Amount: "2",
},
Token{
Denom: Denom{
Base: "mineral",
Trace: []Trace{
NewTrace("portid", "channelid"),
NewTrace("transfer", "channel-52"),
},
},
Amount: "3",
},
},
`denom:<base:"tree" > amount:"1" ,denom:<base:"gas" trace:<port_id:"portid" channel_id:"channelid" > > amount:"2" ,denom:<base:"mineral" trace:<port_id:"portid" channel_id:"channelid" > trace:<port_id:"transfer" channel_id:"channel-52" > > amount:"3" `,
},
}

for _, tt := range cases {
require.Equal(t, tt.expected, tt.input.String())
}
}

0 comments on commit ead6127

Please sign in to comment.