Skip to content

Commit

Permalink
add share unlocking mechanism to megavault (#2169)
Browse files Browse the repository at this point in the history
  • Loading branch information
tqin7 authored Aug 29, 2024
1 parent b0ebc7c commit 6d86d0b
Show file tree
Hide file tree
Showing 17 changed files with 1,101 additions and 46 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Rpc } from "../../helpers";
import * as _m0 from "protobufjs/minimal";
import { MsgDepositToMegavault, MsgDepositToMegavaultResponse, MsgUpdateDefaultQuotingParams, MsgUpdateDefaultQuotingParamsResponse, MsgSetVaultParams, MsgSetVaultParamsResponse } from "./tx";
import { MsgDepositToMegavault, MsgDepositToMegavaultResponse, MsgUpdateDefaultQuotingParams, MsgUpdateDefaultQuotingParamsResponse, MsgSetVaultParams, MsgSetVaultParamsResponse, MsgUnlockShares, MsgUnlockSharesResponse } from "./tx";
/** Msg defines the Msg service. */

export interface Msg {
Expand All @@ -12,6 +12,12 @@ export interface Msg {
/** SetVaultParams sets the parameters of a specific vault. */

setVaultParams(request: MsgSetVaultParams): Promise<MsgSetVaultParamsResponse>;
/**
* UnlockShares unlocks an owner's shares that are due to unlock by the block
* height that this transaction is included in.
*/

unlockShares(request: MsgUnlockShares): Promise<MsgUnlockSharesResponse>;
}
export class MsgClientImpl implements Msg {
private readonly rpc: Rpc;
Expand All @@ -21,6 +27,7 @@ export class MsgClientImpl implements Msg {
this.depositToMegavault = this.depositToMegavault.bind(this);
this.updateDefaultQuotingParams = this.updateDefaultQuotingParams.bind(this);
this.setVaultParams = this.setVaultParams.bind(this);
this.unlockShares = this.unlockShares.bind(this);
}

depositToMegavault(request: MsgDepositToMegavault): Promise<MsgDepositToMegavaultResponse> {
Expand All @@ -41,4 +48,10 @@ export class MsgClientImpl implements Msg {
return promise.then(data => MsgSetVaultParamsResponse.decode(new _m0.Reader(data)));
}

unlockShares(request: MsgUnlockShares): Promise<MsgUnlockSharesResponse> {
const data = MsgUnlockShares.encode(request).finish();
const promise = this.rpc.request("dydxprotocol.vault.Msg", "UnlockShares", data);
return promise.then(data => MsgUnlockSharesResponse.decode(new _m0.Reader(data)));
}

}
128 changes: 128 additions & 0 deletions indexer/packages/v4-protos/src/codegen/dydxprotocol/vault/tx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,34 @@ export interface MsgSetVaultParamsResponse {}
/** MsgSetVaultParamsResponse is the Msg/SetVaultParams response type. */

export interface MsgSetVaultParamsResponseSDKType {}
/** MsgUnlockShares is the Msg/UnlockShares request type. */

export interface MsgUnlockShares {
authority: string;
/** Address of the owner to unlock shares of. */

ownerAddress: string;
}
/** MsgUnlockShares is the Msg/UnlockShares request type. */

export interface MsgUnlockSharesSDKType {
authority: string;
/** Address of the owner to unlock shares of. */

owner_address: string;
}
/** MsgUnlockSharesResponse is the Msg/UnlockShares response type. */

export interface MsgUnlockSharesResponse {
/** The number of shares unlocked. */
unlockedShares?: NumShares;
}
/** MsgUnlockSharesResponse is the Msg/UnlockShares response type. */

export interface MsgUnlockSharesResponseSDKType {
/** The number of shares unlocked. */
unlocked_shares?: NumSharesSDKType;
}
/**
* MsgUpdateParams is the Msg/UpdateParams request type.
* Deprecated since v6.x as is replaced by MsgUpdateDefaultQuotingParams.
Expand Down Expand Up @@ -417,6 +445,106 @@ export const MsgSetVaultParamsResponse = {

};

function createBaseMsgUnlockShares(): MsgUnlockShares {
return {
authority: "",
ownerAddress: ""
};
}

export const MsgUnlockShares = {
encode(message: MsgUnlockShares, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer {
if (message.authority !== "") {
writer.uint32(10).string(message.authority);
}

if (message.ownerAddress !== "") {
writer.uint32(18).string(message.ownerAddress);
}

return writer;
},

decode(input: _m0.Reader | Uint8Array, length?: number): MsgUnlockShares {
const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
let end = length === undefined ? reader.len : reader.pos + length;
const message = createBaseMsgUnlockShares();

while (reader.pos < end) {
const tag = reader.uint32();

switch (tag >>> 3) {
case 1:
message.authority = reader.string();
break;

case 2:
message.ownerAddress = reader.string();
break;

default:
reader.skipType(tag & 7);
break;
}
}

return message;
},

fromPartial(object: DeepPartial<MsgUnlockShares>): MsgUnlockShares {
const message = createBaseMsgUnlockShares();
message.authority = object.authority ?? "";
message.ownerAddress = object.ownerAddress ?? "";
return message;
}

};

function createBaseMsgUnlockSharesResponse(): MsgUnlockSharesResponse {
return {
unlockedShares: undefined
};
}

export const MsgUnlockSharesResponse = {
encode(message: MsgUnlockSharesResponse, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer {
if (message.unlockedShares !== undefined) {
NumShares.encode(message.unlockedShares, writer.uint32(10).fork()).ldelim();
}

return writer;
},

decode(input: _m0.Reader | Uint8Array, length?: number): MsgUnlockSharesResponse {
const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
let end = length === undefined ? reader.len : reader.pos + length;
const message = createBaseMsgUnlockSharesResponse();

while (reader.pos < end) {
const tag = reader.uint32();

switch (tag >>> 3) {
case 1:
message.unlockedShares = NumShares.decode(reader, reader.uint32());
break;

default:
reader.skipType(tag & 7);
break;
}
}

return message;
},

fromPartial(object: DeepPartial<MsgUnlockSharesResponse>): MsgUnlockSharesResponse {
const message = createBaseMsgUnlockSharesResponse();
message.unlockedShares = object.unlockedShares !== undefined && object.unlockedShares !== null ? NumShares.fromPartial(object.unlockedShares) : undefined;
return message;
}

};

function createBaseMsgUpdateParams(): MsgUpdateParams {
return {
authority: "",
Expand Down
20 changes: 20 additions & 0 deletions proto/dydxprotocol/vault/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ service Msg {

// SetVaultParams sets the parameters of a specific vault.
rpc SetVaultParams(MsgSetVaultParams) returns (MsgSetVaultParamsResponse);

// UnlockShares unlocks an owner's shares that are due to unlock by the block
// height that this transaction is included in.
rpc UnlockShares(MsgUnlockShares) returns (MsgUnlockSharesResponse);
}

// MsgDepositToMegavault deposits the specified asset from the subaccount to
Expand Down Expand Up @@ -81,6 +85,22 @@ message MsgSetVaultParams {
// MsgSetVaultParamsResponse is the Msg/SetVaultParams response type.
message MsgSetVaultParamsResponse {}

// MsgUnlockShares is the Msg/UnlockShares request type.
message MsgUnlockShares {
// Authority is the address that controls the module.
option (cosmos.msg.v1.signer) = "authority";
string authority = 1 [ (cosmos_proto.scalar) = "cosmos.AddressString" ];

// Address of the owner to unlock shares of.
string owner_address = 2;
}

// MsgUnlockSharesResponse is the Msg/UnlockShares response type.
message MsgUnlockSharesResponse {
// The number of shares unlocked.
NumShares unlocked_shares = 1 [ (gogoproto.nullable) = false ];
}

// MsgUpdateParams is the Msg/UpdateParams request type.
// Deprecated since v6.x as is replaced by MsgUpdateDefaultQuotingParams.
message MsgUpdateParams {
Expand Down
1 change: 1 addition & 0 deletions protocol/app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -1158,6 +1158,7 @@ func New(
appCodec,
keys[vaultmoduletypes.StoreKey],
app.ClobKeeper,
app.DelayMsgKeeper,
app.PerpetualsKeeper,
app.PricesKeeper,
app.SendingKeeper,
Expand Down
2 changes: 2 additions & 0 deletions protocol/app/msgs/all_msgs.go
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,8 @@ var (
"/dydxprotocol.vault.MsgDepositToMegavaultResponse": {},
"/dydxprotocol.vault.MsgSetVaultParams": {},
"/dydxprotocol.vault.MsgSetVaultParamsResponse": {},
"/dydxprotocol.vault.MsgUnlockShares": {},
"/dydxprotocol.vault.MsgUnlockSharesResponse": {},
"/dydxprotocol.vault.MsgUpdateDefaultQuotingParams": {},
"/dydxprotocol.vault.MsgUpdateDefaultQuotingParamsResponse": {},
"/dydxprotocol.vault.MsgUpdateParams": {},
Expand Down
2 changes: 2 additions & 0 deletions protocol/app/msgs/internal_msgs.go
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,8 @@ var (
// vault
"/dydxprotocol.vault.MsgSetVaultParams": &vault.MsgSetVaultParams{},
"/dydxprotocol.vault.MsgSetVaultParamsResponse": nil,
"/dydxprotocol.vault.MsgUnlockShares": &vault.MsgUnlockShares{},
"/dydxprotocol.vault.MsgUnlockSharesResponse": nil,
"/dydxprotocol.vault.MsgUpdateDefaultQuotingParams": &vault.MsgUpdateDefaultQuotingParams{},
"/dydxprotocol.vault.MsgUpdateDefaultQuotingParamsResponse": nil,

Expand Down
2 changes: 2 additions & 0 deletions protocol/app/msgs/internal_msgs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,8 @@ func TestInternalMsgSamples_Gov_Key(t *testing.T) {
// vault
"/dydxprotocol.vault.MsgSetVaultParams",
"/dydxprotocol.vault.MsgSetVaultParamsResponse",
"/dydxprotocol.vault.MsgUnlockShares",
"/dydxprotocol.vault.MsgUnlockSharesResponse",
"/dydxprotocol.vault.MsgUpdateDefaultQuotingParams",
"/dydxprotocol.vault.MsgUpdateDefaultQuotingParamsResponse",

Expand Down
1 change: 1 addition & 0 deletions protocol/lib/ante/internal_msg.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ func IsInternalMsg(msg sdk.Msg) bool {

// vault
*vault.MsgSetVaultParams,
*vault.MsgUnlockShares,
*vault.MsgUpdateDefaultQuotingParams,

// vest
Expand Down
18 changes: 18 additions & 0 deletions protocol/testutil/delaymsg/delaymsg_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import (
"testing"

codectypes "github.com/cosmos/cosmos-sdk/codec/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/dydxprotocol/v4-chain/protocol/testutil/constants"
delaymsgtypes "github.com/dydxprotocol/v4-chain/protocol/x/delaymsg/types"
"github.com/stretchr/testify/require"
)

Expand All @@ -15,3 +17,19 @@ func CreateTestAnyMsg(t testing.TB) *codectypes.Any {
require.NoError(t, err)
return any
}

// FilterDelayedMsgsByType filters a slice of DelayedMessage by a specific sdk.Msg type.
func FilterDelayedMsgsByType[T sdk.Msg](
t testing.TB,
delayedmsgs []*delaymsgtypes.DelayedMessage,
) []*delaymsgtypes.DelayedMessage {
var filtered []*delaymsgtypes.DelayedMessage
for _, delayedmsg := range delayedmsgs {
msg, err := delayedmsg.GetMessage()
require.NoError(t, err)
if _, ok := msg.(T); ok {
filtered = append(filtered, delayedmsg)
}
}
return filtered
}
1 change: 1 addition & 0 deletions protocol/testutil/keeper/vault.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ func createVaultKeeper(
cdc,
storeKey,
&mocks.ClobKeeper{},
&mocks.DelayMsgKeeper{},
&mocks.PerpetualsKeeper{},
&mocks.PricesKeeper{},
&mocks.SendingKeeper{},
Expand Down
3 changes: 3 additions & 0 deletions protocol/x/vault/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ type (
cdc codec.BinaryCodec
storeKey storetypes.StoreKey
clobKeeper types.ClobKeeper
delayMsgKeeper types.DelayMsgKeeper
perpetualsKeeper types.PerpetualsKeeper
pricesKeeper types.PricesKeeper
sendingKeeper types.SendingKeeper
Expand All @@ -28,6 +29,7 @@ func NewKeeper(
cdc codec.BinaryCodec,
storeKey storetypes.StoreKey,
clobKeeper types.ClobKeeper,
delayMsgKeeper types.DelayMsgKeeper,
perpetualsKeeper types.PerpetualsKeeper,
pricesKeeper types.PricesKeeper,
sendingKeeper types.SendingKeeper,
Expand All @@ -38,6 +40,7 @@ func NewKeeper(
cdc: cdc,
storeKey: storeKey,
clobKeeper: clobKeeper,
delayMsgKeeper: delayMsgKeeper,
perpetualsKeeper: perpetualsKeeper,
pricesKeeper: pricesKeeper,
sendingKeeper: sendingKeeper,
Expand Down
42 changes: 42 additions & 0 deletions protocol/x/vault/keeper/msg_server_unlock_shares.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package keeper

import (
"context"
"fmt"

errorsmod "cosmossdk.io/errors"

govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
"github.com/dydxprotocol/v4-chain/protocol/lib"
"github.com/dydxprotocol/v4-chain/protocol/x/vault/types"
)

// UnlockShares unlocks an owner's shares.
func (k msgServer) UnlockShares(
goCtx context.Context,
msg *types.MsgUnlockShares,
) (*types.MsgUnlockSharesResponse, error) {
// Check if authority is valid.
if !k.HasAuthority(msg.Authority) {
return nil, errorsmod.Wrapf(
govtypes.ErrInvalidSigner,
"invalid authority %s",
msg.Authority,
)
}

ctx := lib.UnwrapSDKContext(goCtx, types.ModuleName)

if msg.OwnerAddress == "" {
return nil, fmt.Errorf("owner address cannot be empty")
}

unlockedShares, err := k.Keeper.UnlockShares(ctx, msg.OwnerAddress)
if err != nil {
return nil, err
}

return &types.MsgUnlockSharesResponse{
UnlockedShares: unlockedShares,
}, nil
}
Loading

0 comments on commit 6d86d0b

Please sign in to comment.