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 take profit price Msg #815

Merged
merged 3 commits into from
Sep 24, 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
13 changes: 11 additions & 2 deletions proto/elys/perpetual/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ service Msg {
rpc AddCollateral (MsgAddCollateral ) returns (MsgAddCollateralResponse );
rpc BrokerAddCollateral (MsgBrokerAddCollateral) returns (MsgAddCollateralResponse );
rpc UpdateStopLoss (MsgUpdateStopLoss ) returns (MsgUpdateStopLossResponse );
rpc ClosePositions (MsgClosePositions ) returns (MsgClosePositionsResponse);
rpc ClosePositions (MsgClosePositions ) returns (MsgClosePositionsResponse );
rpc UpdateTakeProfitPrice(MsgUpdateTakeProfitPrice) returns (MsgUpdateTakeProfitPriceResponse);
}
message MsgOpen {
string creator = 1;
Expand Down Expand Up @@ -126,4 +127,12 @@ message MsgUpdateStopLoss {
string price = 3 [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", (gogoproto.nullable) = false];
}

message MsgUpdateStopLossResponse {}
message MsgUpdateStopLossResponse {}

message MsgUpdateTakeProfitPrice {
string creator = 1;
uint64 id = 2;
string price = 3 [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", (gogoproto.nullable) = false];
}

message MsgUpdateTakeProfitPriceResponse {}
1 change: 1 addition & 0 deletions x/perpetual/client/cli/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
cmd.AddCommand(CmdAddCollateral())
cmd.AddCommand(CmdClosePositions())
cmd.AddCommand(CmdUpdateStopLoss())
cmd.AddCommand(CmdUpdateTakeProfitPrice())

Check warning on line 35 in x/perpetual/client/cli/tx.go

View check run for this annotation

Codecov / codecov/patch

x/perpetual/client/cli/tx.go#L35

Added line #L35 was not covered by tests
// this line is used by starport scaffolding # 1

return cmd
Expand Down
51 changes: 51 additions & 0 deletions x/perpetual/client/cli/tx_update_take_profit_price.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package cli

import (
"errors"
"strconv"

"cosmossdk.io/math"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/client/tx"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/elys-network/elys/x/perpetual/types"
"github.com/spf13/cobra"
)

func CmdUpdateTakeProfitPrice() *cobra.Command {
cmd := &cobra.Command{
Use: "update-take-profit-price [id] [amount]",
Short: "Broadcast message update-take-profit-price",
Args: cobra.ExactArgs(2),
RunE: func(cmd *cobra.Command, args []string) (err error) {
argPrice, err := sdk.NewDecFromStr(args[0])
if err != nil {
return errors.New("invalid take profit amount")

Check warning on line 24 in x/perpetual/client/cli/tx_update_take_profit_price.go

View check run for this annotation

Codecov / codecov/patch

x/perpetual/client/cli/tx_update_take_profit_price.go#L16-L24

Added lines #L16 - L24 were not covered by tests
}
positionId, err := strconv.Atoi(args[1])
if err != nil {
return err

Check warning on line 28 in x/perpetual/client/cli/tx_update_take_profit_price.go

View check run for this annotation

Codecov / codecov/patch

x/perpetual/client/cli/tx_update_take_profit_price.go#L26-L28

Added lines #L26 - L28 were not covered by tests
}

clientCtx, err := client.GetClientTxContext(cmd)
if err != nil {
return err

Check warning on line 33 in x/perpetual/client/cli/tx_update_take_profit_price.go

View check run for this annotation

Codecov / codecov/patch

x/perpetual/client/cli/tx_update_take_profit_price.go#L31-L33

Added lines #L31 - L33 were not covered by tests
}

msg := types.NewMsgUpdateTakeProfitPrice(
clientCtx.GetFromAddress().String(),
uint64(positionId),
math.LegacyDec(argPrice),
)
if err := msg.ValidateBasic(); err != nil {
return err

Check warning on line 42 in x/perpetual/client/cli/tx_update_take_profit_price.go

View check run for this annotation

Codecov / codecov/patch

x/perpetual/client/cli/tx_update_take_profit_price.go#L36-L42

Added lines #L36 - L42 were not covered by tests
}
return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg)

Check warning on line 44 in x/perpetual/client/cli/tx_update_take_profit_price.go

View check run for this annotation

Codecov / codecov/patch

x/perpetual/client/cli/tx_update_take_profit_price.go#L44

Added line #L44 was not covered by tests
},
}

flags.AddTxFlagsToCmd(cmd)

Check warning on line 48 in x/perpetual/client/cli/tx_update_take_profit_price.go

View check run for this annotation

Codecov / codecov/patch

x/perpetual/client/cli/tx_update_take_profit_price.go#L48

Added line #L48 was not covered by tests

return cmd

Check warning on line 50 in x/perpetual/client/cli/tx_update_take_profit_price.go

View check run for this annotation

Codecov / codecov/patch

x/perpetual/client/cli/tx_update_take_profit_price.go#L50

Added line #L50 was not covered by tests
}
70 changes: 70 additions & 0 deletions x/perpetual/keeper/msg_server_update_take_profit_price.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package keeper

import (
"context"
"fmt"
"strconv"

errorsmod "cosmossdk.io/errors"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/elys-network/elys/x/perpetual/types"
assetprofiletypes "github.com/elys-network/elys/x/assetprofile/types"
ptypes "github.com/elys-network/elys/x/parameter/types"
)

func (k msgServer) UpdateTakeProfitPrice(goCtx context.Context, msg *types.MsgUpdateTakeProfitPrice) (*types.MsgUpdateTakeProfitPriceResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)

Check warning on line 16 in x/perpetual/keeper/msg_server_update_take_profit_price.go

View check run for this annotation

Codecov / codecov/patch

x/perpetual/keeper/msg_server_update_take_profit_price.go#L15-L16

Added lines #L15 - L16 were not covered by tests

// Load existing mtp
creator := sdk.MustAccAddressFromBech32(msg.Creator)
mtp, err := k.GetMTP(ctx, creator, msg.Id)
if err != nil {
return nil, err

Check warning on line 22 in x/perpetual/keeper/msg_server_update_take_profit_price.go

View check run for this annotation

Codecov / codecov/patch

x/perpetual/keeper/msg_server_update_take_profit_price.go#L19-L22

Added lines #L19 - L22 were not covered by tests
}

poolId := mtp.AmmPoolId
pool, found := k.GetPool(ctx, poolId)
if !found {
return nil, errorsmod.Wrap(types.ErrPoolDoesNotExist, fmt.Sprintf("poolId: %d", poolId))

Check warning on line 28 in x/perpetual/keeper/msg_server_update_take_profit_price.go

View check run for this annotation

Codecov / codecov/patch

x/perpetual/keeper/msg_server_update_take_profit_price.go#L25-L28

Added lines #L25 - L28 were not covered by tests
}

if !pool.Enabled {
return nil, errorsmod.Wrap(types.ErrPerpetualDisabled, fmt.Sprintf("poolId: %d", poolId))

Check warning on line 32 in x/perpetual/keeper/msg_server_update_take_profit_price.go

View check run for this annotation

Codecov / codecov/patch

x/perpetual/keeper/msg_server_update_take_profit_price.go#L31-L32

Added lines #L31 - L32 were not covered by tests
}

entry, found := k.assetProfileKeeper.GetEntry(ctx, ptypes.BaseCurrency)
if !found {
return nil, errorsmod.Wrapf(assetprofiletypes.ErrAssetProfileNotFound, "asset %s not found", ptypes.BaseCurrency)

Check warning on line 37 in x/perpetual/keeper/msg_server_update_take_profit_price.go

View check run for this annotation

Codecov / codecov/patch

x/perpetual/keeper/msg_server_update_take_profit_price.go#L35-L37

Added lines #L35 - L37 were not covered by tests
}
baseCurrency := entry.Denom

Check warning on line 39 in x/perpetual/keeper/msg_server_update_take_profit_price.go

View check run for this annotation

Codecov / codecov/patch

x/perpetual/keeper/msg_server_update_take_profit_price.go#L39

Added line #L39 was not covered by tests

mtp.TakeProfitPrice = msg.Price
mtp.TakeProfitCustody = types.CalcMTPTakeProfitCustody(&mtp)
mtp.TakeProfitLiabilities, err = k.CalcMTPTakeProfitLiability(ctx, &mtp, baseCurrency)
if err != nil {
return nil, err

Check warning on line 45 in x/perpetual/keeper/msg_server_update_take_profit_price.go

View check run for this annotation

Codecov / codecov/patch

x/perpetual/keeper/msg_server_update_take_profit_price.go#L41-L45

Added lines #L41 - L45 were not covered by tests
}

// All take profit liability has to be in liabilities asset
err = pool.UpdateTakeProfitLiabilities(ctx, mtp.LiabilitiesAsset, mtp.TakeProfitLiabilities, true, mtp.Position)
if err != nil {
return nil, err

Check warning on line 51 in x/perpetual/keeper/msg_server_update_take_profit_price.go

View check run for this annotation

Codecov / codecov/patch

x/perpetual/keeper/msg_server_update_take_profit_price.go#L49-L51

Added lines #L49 - L51 were not covered by tests
}

// All take profit custody has to be in custody asset
err = pool.UpdateTakeProfitCustody(ctx, mtp.CustodyAsset, mtp.TakeProfitCustody, true, mtp.Position)
if err != nil {
return nil, err

Check warning on line 57 in x/perpetual/keeper/msg_server_update_take_profit_price.go

View check run for this annotation

Codecov / codecov/patch

x/perpetual/keeper/msg_server_update_take_profit_price.go#L55-L57

Added lines #L55 - L57 were not covered by tests
}

k.SetMTP(ctx, &mtp)

Check warning on line 60 in x/perpetual/keeper/msg_server_update_take_profit_price.go

View check run for this annotation

Codecov / codecov/patch

x/perpetual/keeper/msg_server_update_take_profit_price.go#L60

Added line #L60 was not covered by tests

event := sdk.NewEvent(types.EventOpen,
sdk.NewAttribute("id", strconv.FormatInt(int64(mtp.Id), 10)),
sdk.NewAttribute("address", mtp.Address),
sdk.NewAttribute("take_profit_price", mtp.TakeProfitPrice.String()),
)
ctx.EventManager().EmitEvent(event)

Check warning on line 67 in x/perpetual/keeper/msg_server_update_take_profit_price.go

View check run for this annotation

Codecov / codecov/patch

x/perpetual/keeper/msg_server_update_take_profit_price.go#L62-L67

Added lines #L62 - L67 were not covered by tests

return &types.MsgUpdateTakeProfitPriceResponse{}, nil

Check warning on line 69 in x/perpetual/keeper/msg_server_update_take_profit_price.go

View check run for this annotation

Codecov / codecov/patch

x/perpetual/keeper/msg_server_update_take_profit_price.go#L69

Added line #L69 was not covered by tests
}
2 changes: 2 additions & 0 deletions x/perpetual/types/codec.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
legacy.RegisterAminoMsg(cdc, &MsgAddCollateral{}, "perpetual/MsgAddCollateral")
legacy.RegisterAminoMsg(cdc, &MsgClosePositions{}, "perpetual/ClosePositions")
legacy.RegisterAminoMsg(cdc, &MsgUpdateStopLoss{}, "perpetual/MsgUpdateStopLoss")
legacy.RegisterAminoMsg(cdc, &MsgUpdateTakeProfitPrice{}, "perpetual/MsgUpdateTakeProfitPrice")
// this line is used by starport scaffolding # 2
}

Expand All @@ -33,6 +34,7 @@
&MsgDewhitelist{},
&MsgAddCollateral{},
&MsgUpdateStopLoss{},
&MsgUpdateTakeProfitPrice{},

Check warning on line 37 in x/perpetual/types/codec.go

View check run for this annotation

Codecov / codecov/patch

x/perpetual/types/codec.go#L37

Added line #L37 was not covered by tests
)
registry.RegisterImplementations((*sdk.Msg)(nil),
&MsgClosePositions{},
Expand Down
53 changes: 53 additions & 0 deletions x/perpetual/types/message_update_take_profit_price.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package types

import (
"fmt"

sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
)

const TypeMsgUpdateTakeProfitPrice= "update_take_profit_price"

var _ sdk.Msg = &MsgUpdateTakeProfitPrice{}

func NewMsgUpdateTakeProfitPrice(creator string, id uint64, price sdk.Dec) *MsgUpdateTakeProfitPrice {
return &MsgUpdateTakeProfitPrice{
Creator: creator,
Id: id,
Price: price,
}
}

func (msg *MsgUpdateTakeProfitPrice) Route() string {
return RouterKey
}

func (msg *MsgUpdateTakeProfitPrice) Type() string {
return TypeMsgUpdateTakeProfitPrice
}

func (msg *MsgUpdateTakeProfitPrice) GetSigners() []sdk.AccAddress {
creator, err := sdk.AccAddressFromBech32(msg.Creator)
if err != nil {
panic(err)
}
return []sdk.AccAddress{creator}
}

func (msg *MsgUpdateTakeProfitPrice) GetSignBytes() []byte {
bz := ModuleCdc.MustMarshalJSON(msg)
return sdk.MustSortJSON(bz)
}

func (msg *MsgUpdateTakeProfitPrice) ValidateBasic() error {
_, err := sdk.AccAddressFromBech32(msg.Creator)
if err != nil {
return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "invalid creator address (%s)", err)
}

if msg.Price.IsNegative() {
return fmt.Errorf("take profit price cannot be negative")
}
return nil
}
67 changes: 67 additions & 0 deletions x/perpetual/types/message_update_take_profit_price_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package types_test

import (
"testing"

sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/elys-network/elys/testutil/sample"
"github.com/elys-network/elys/x/perpetual/types"
"github.com/stretchr/testify/require"
)

func TestMsgUpdatetakeProfitPrice(t *testing.T) {
msg := types.NewMsgUpdateTakeProfitPrice(sample.AccAddress(), 1, sdk.OneDec())
require.Equal(t, msg.Route(), types.RouterKey)
require.Equal(t, msg.Type(), types.TypeMsgUpdateTakeProfitPrice)
require.Equal(t, msg.GetSigners(), []sdk.AccAddress{sdk.MustAccAddressFromBech32(msg.Creator)})
require.Equal(t, msg.GetSignBytes(), sdk.MustSortJSON(types.ModuleCdc.MustMarshalJSON(msg)))
msg.Creator = ""
require.PanicsWithError(t, "empty address string is not allowed", func() { msg.GetSigners() })
tests := []struct {
name string
setter func()
errMsg string
}{
{
name: "success",
setter: func() {
msg.Creator = sample.AccAddress()
},
errMsg: "",
},
{
name: "invalid address",
setter: func() {
msg.Creator = "invalid_address"
},
errMsg: "invalid creator address",
},
{
name: "take profit price is 0",
setter: func() {
msg.Creator = sample.AccAddress()
msg.Price = sdk.ZeroDec()
},
errMsg: "",
},
{
name: "take profit price is < 0",
setter: func() {
msg.Creator = sample.AccAddress()
msg.Price = sdk.OneDec().MulInt64(-1)
},
errMsg: "take profit price cannot be negative",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
tt.setter()
err := msg.ValidateBasic()
if tt.errMsg != "" {
require.ErrorContains(t, err, tt.errMsg)
} else {
require.NoError(t, err)
}
})
}
}
Loading
Loading