Skip to content

Commit 0d45ffb

Browse files
testinginprodAgentSmithMatrixNibiruHeisenbergmatthiasmatt
authored
add: expose open position (#435)
* add: expose open position * add: open position cmd * add: open position cmd * fix: register msg server * chore: lint * fix imports * fix the imports * fix: OpenPosition cmd and make it more readable * make proto to include integers * fix tests * add open position requests * fix linter Co-authored-by: Agent Smith <agentsmith@matrixsystems.co> Co-authored-by: AgentSmithMatrix <98403347+AgentSmithMatrix@users.noreply.github.com> Co-authored-by: Walter White <101130700+MatrixHeisenberg@users.noreply.github.com> Co-authored-by: Mat-Cosmos <97468149+matthiasmatt@users.noreply.github.com>
1 parent b81d938 commit 0d45ffb

File tree

9 files changed

+752
-60
lines changed

9 files changed

+752
-60
lines changed

proto/perp/v1/tx.proto

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ package nibiru.perp.v1;
55
import "google/api/annotations.proto";
66
import "cosmos/base/v1beta1/coin.proto";
77
import "gogoproto/gogo.proto";
8+
import "perp/v1/state.proto";
89

910
option go_package="github.com/NibiruChain/nibiru/x/perp/types";
1011

@@ -18,6 +19,9 @@ service Msg {
1819
rpc AddMargin(MsgAddMargin) returns (MsgAddMarginResponse) {
1920
option (google.api.http).post = "/nibiru/perp/add_margin";
2021
}
22+
23+
rpc OpenPosition(MsgOpenPosition) returns (MsgOpenPositionResponse) {}
24+
2125
}
2226

2327
/* MsgRemoveMargin: Msg to remove margin. */
@@ -44,4 +48,23 @@ message MsgAddMargin {
4448

4549
message MsgAddMarginResponse {
4650
// MarginOut: tokens transferred back to the trader
51+
}
52+
53+
message MsgOpenPosition {
54+
string sender = 1;
55+
string token_pair = 2;
56+
nibiru.perp.v1.Side side = 3;
57+
string quote_asset_amount = 4 [
58+
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
59+
(gogoproto.nullable) = false];
60+
string leverage = 5 [
61+
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec",
62+
(gogoproto.nullable) = false];
63+
string base_asset_amount_limit = 6 [
64+
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
65+
(gogoproto.nullable) = false];
66+
}
67+
68+
message MsgOpenPositionResponse {
69+
4770
}

x/perp/client/cli/cli.go

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import (
55
"fmt"
66
"strings"
77

8+
"github.com/NibiruChain/nibiru/x/common"
9+
810
"github.com/spf13/cobra"
911

1012
"github.com/cosmos/cosmos-sdk/client"
@@ -84,11 +86,76 @@ func GetTxCmd() *cobra.Command {
8486
txCmd.AddCommand(
8587
RemoveMarginCmd(),
8688
AddMarginCmd(),
89+
OpenPositionCmd(),
8790
)
8891

8992
return txCmd
9093
}
9194

95+
func OpenPositionCmd() *cobra.Command {
96+
cmd := &cobra.Command{
97+
Use: "open-position [buy/sell] [pair] [leverage] [amount/sdk.Dec] [base asset amount limit/sdk.Dec]",
98+
Short: "Opens a position",
99+
Args: cobra.ExactArgs(5),
100+
RunE: func(cmd *cobra.Command, args []string) error {
101+
clientCtx, err := client.GetClientTxContext(cmd)
102+
if err != nil {
103+
return err
104+
}
105+
106+
txf := tx.NewFactoryCLI(clientCtx, cmd.Flags()).WithTxConfig(clientCtx.TxConfig).WithAccountRetriever(clientCtx.AccountRetriever)
107+
108+
var side types.Side
109+
switch args[0] {
110+
case "buy":
111+
side = types.Side_BUY
112+
case "sell":
113+
side = types.Side_SELL
114+
default:
115+
return fmt.Errorf("invalid side: %s", args[0])
116+
}
117+
118+
_, err = common.NewTokenPairFromStr(args[1])
119+
if err != nil {
120+
return err
121+
}
122+
123+
leverage, err := sdk.NewDecFromStr(args[2])
124+
if err != nil {
125+
return err
126+
}
127+
128+
amount, ok := sdk.NewIntFromString(args[3])
129+
if !ok {
130+
return fmt.Errorf("invalid quote amount: %s", args[3])
131+
}
132+
133+
baseAssetAmountLimit, ok := sdk.NewIntFromString(args[4])
134+
if !ok {
135+
return fmt.Errorf("invalid base amount limit: %s", args[3])
136+
}
137+
138+
msg := &types.MsgOpenPosition{
139+
Sender: clientCtx.GetFromAddress().String(),
140+
TokenPair: args[1],
141+
Side: side,
142+
QuoteAssetAmount: amount,
143+
Leverage: leverage,
144+
BaseAssetAmountLimit: baseAssetAmountLimit,
145+
}
146+
147+
if err := msg.ValidateBasic(); err != nil {
148+
return err
149+
}
150+
151+
return tx.GenerateOrBroadcastTxWithFactory(clientCtx, txf, msg)
152+
},
153+
}
154+
155+
flags.AddTxFlagsToCmd(cmd)
156+
return cmd
157+
}
158+
92159
/*
93160
RemoveMarginCmd is a CLI command that removes margin from a position,
94161
realizing any outstanding funding payments and decreasing the margin ratio.

x/perp/keeper/clearing_house.go

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,12 @@ import (
55
"fmt"
66
"time"
77

8-
"github.com/NibiruChain/nibiru/x/common"
9-
"github.com/NibiruChain/nibiru/x/perp/events"
10-
pooltypes "github.com/NibiruChain/nibiru/x/vpool/types"
11-
128
sdk "github.com/cosmos/cosmos-sdk/types"
139

10+
"github.com/NibiruChain/nibiru/x/common"
11+
"github.com/NibiruChain/nibiru/x/perp/events"
1412
"github.com/NibiruChain/nibiru/x/perp/types"
13+
pooltypes "github.com/NibiruChain/nibiru/x/vpool/types"
1514
)
1615

1716
// TODO test: OpenPosition | https://github.com/NibiruChain/nibiru/issues/299
@@ -45,7 +44,7 @@ func (k Keeper) OpenPosition(
4544
var positionResp *types.PositionResp
4645
sameSideLong := position.Size_.IsPositive() && side == types.Side_BUY
4746
sameSideShort := position.Size_.IsNegative() && side == types.Side_SELL
48-
var openSideMatchesPosition bool = (sameSideLong || sameSideShort)
47+
var openSideMatchesPosition = sameSideLong || sameSideShort
4948
switch {
5049
case isNewPosition || openSideMatchesPosition:
5150
// increase position case

x/perp/keeper/msg_server.go

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,45 +3,48 @@ package keeper
33
import (
44
"context"
55

6+
sdk "github.com/cosmos/cosmos-sdk/types"
7+
8+
"github.com/NibiruChain/nibiru/x/common"
69
"github.com/NibiruChain/nibiru/x/perp/types"
710
)
811

912
type msgServer struct {
10-
Keeper
13+
k Keeper
1114
}
1215

1316
// NewMsgServerImpl returns an implementation of the MsgServer interface
1417
// for the provided Keeper.
1518
func NewMsgServerImpl(keeper Keeper) types.MsgServer {
16-
return &msgServer{Keeper: keeper}
19+
return &msgServer{k: keeper}
1720
}
1821

1922
var _ types.MsgServer = msgServer{}
2023

21-
/*
22-
Args:
23-
goCtx
24-
25-
Returns
26-
MsgRemoveMarginResponse:
27-
error:
28-
*/
29-
func (k msgServer) MsgRemoveMargin(goCtx context.Context, msg *types.MsgRemoveMargin,
30-
) (*types.MsgRemoveMarginResponse, error) {
31-
removeMarginResponse, err := k.RemoveMargin(goCtx, msg)
24+
func (k msgServer) RemoveMargin(ctx context.Context, margin *types.MsgRemoveMargin) (*types.MsgRemoveMarginResponse, error) {
25+
return k.k.RemoveMargin(ctx, margin)
26+
}
27+
28+
func (k msgServer) AddMargin(ctx context.Context, margin *types.MsgAddMargin) (*types.MsgAddMarginResponse, error) {
29+
return k.k.AddMargin(ctx, margin)
30+
}
31+
32+
func (k msgServer) OpenPosition(ctx context.Context, req *types.MsgOpenPosition) (*types.MsgOpenPositionResponse, error) {
33+
pair, err := common.NewTokenPairFromStr(req.TokenPair)
3234
if err != nil {
33-
return nil, err
35+
panic(err) // must not happen
3436
}
3537

36-
return removeMarginResponse, nil
37-
}
38+
addr, err := sdk.AccAddressFromBech32(req.Sender)
39+
if err != nil {
40+
panic(err) // must not happen
41+
}
3842

39-
func (k msgServer) MsgAddMargin(goCtx context.Context, msg *types.MsgAddMargin,
40-
) (*types.MsgAddMarginResponse, error) {
41-
removeMarginResponse, err := k.AddMargin(goCtx, msg)
43+
sdkCtx := sdk.UnwrapSDKContext(ctx)
44+
err = k.k.OpenPosition(sdkCtx, pair, req.Side, addr, req.QuoteAssetAmount, req.Leverage, req.BaseAssetAmountLimit.ToDec())
4245
if err != nil {
4346
return nil, err
4447
}
4548

46-
return removeMarginResponse, nil
49+
return &types.MsgOpenPositionResponse{}, nil
4750
}

x/perp/module.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ func (am AppModule) LegacyQuerierHandler(legacyQuerierCdc *codec.LegacyAmino) sd
180180
// module-specific GRPC queries.
181181
func (am AppModule) RegisterServices(cfg module.Configurator) {
182182
types.RegisterQueryServer(cfg.QueryServer(), am.keeper)
183-
types.RegisterMsgServer(cfg.MsgServer(), am.keeper)
183+
types.RegisterMsgServer(cfg.MsgServer(), keeper.NewMsgServerImpl(am.keeper))
184184
}
185185

186186
// RegisterInvariants registers the capability module's invariants.

x/perp/types/codec.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ func RegisterInterfaces(registry cdctypes.InterfaceRegistry) {
1818
/* implementations */
1919
&MsgRemoveMargin{},
2020
&MsgAddMargin{},
21+
&MsgOpenPosition{},
2122
)
2223

2324
msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc)

x/perp/types/msgs.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
11
package types
22

33
import (
4+
"fmt"
5+
46
sdk "github.com/cosmos/cosmos-sdk/types"
7+
8+
"github.com/NibiruChain/nibiru/x/common"
59
)
610

711
var _ sdk.Msg = &MsgRemoveMargin{}
812
var _ sdk.Msg = &MsgAddMargin{}
13+
var _ sdk.Msg = &MsgOpenPosition{}
914

1015
// MsgRemoveMargin
1116

@@ -42,3 +47,35 @@ func (m MsgAddMargin) GetSigners() []sdk.AccAddress {
4247
sender, _ := sdk.AccAddressFromBech32(m.Sender)
4348
return []sdk.AccAddress{sender}
4449
}
50+
51+
func (m *MsgOpenPosition) ValidateBasic() error {
52+
if m.Side != Side_SELL && m.Side != Side_BUY {
53+
return fmt.Errorf("invalid side")
54+
}
55+
if _, err := common.NewTokenPairFromStr(m.TokenPair); err != nil {
56+
return err
57+
}
58+
if _, err := sdk.AccAddressFromBech32(m.Sender); err != nil {
59+
return err
60+
}
61+
if !m.Leverage.GT(sdk.ZeroDec()) {
62+
return fmt.Errorf("leverage must always be greater than zero")
63+
}
64+
if !m.BaseAssetAmountLimit.GT(sdk.ZeroInt()) {
65+
return fmt.Errorf("base asset amount limit must always be greater than zero")
66+
}
67+
if m.QuoteAssetAmount.GT(sdk.ZeroInt()) {
68+
return fmt.Errorf("quote asset amount must be always greater than zero")
69+
}
70+
71+
return nil
72+
}
73+
74+
func (m *MsgOpenPosition) GetSigners() []sdk.AccAddress {
75+
addr, err := sdk.AccAddressFromBech32(m.Sender)
76+
if err != nil {
77+
panic(err)
78+
}
79+
80+
return []sdk.AccAddress{addr}
81+
}

0 commit comments

Comments
 (0)