Skip to content

Commit

Permalink
add withdraw fee payer funds
Browse files Browse the repository at this point in the history
  • Loading branch information
satawatnack committed Dec 12, 2024
1 parent e8afa0a commit 3bf764d
Show file tree
Hide file tree
Showing 9 changed files with 2,021 additions and 334 deletions.
1,585 changes: 1,343 additions & 242 deletions api/band/tunnel/v1beta1/tx.pulsar.go

Large diffs are not rendered by default.

39 changes: 39 additions & 0 deletions api/band/tunnel/v1beta1/tx_grpc.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

23 changes: 23 additions & 0 deletions proto/band/tunnel/v1beta1/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ service Msg {
// UpdateSignalsAndInterval is a RPC method to update a signals and interval of the tunnel.
rpc UpdateSignalsAndInterval(MsgUpdateSignalsAndInterval) returns (MsgUpdateSignalsAndIntervalResponse);

// WithdrawFeePayerFunds is a RPC method to withdraw fee payer funds to creator.
rpc WithdrawFeePayerFunds(MsgWithdrawFeePayerFunds) returns (MsgWithdrawFeePayerFundsResponse);

// Activate is a RPC method to activate a tunnel.
rpc Activate(MsgActivate) returns (MsgActivateResponse);

Expand Down Expand Up @@ -105,6 +108,26 @@ message MsgUpdateSignalsAndInterval {
// MsgUpdateSignalsAndIntervalResponse is the response type for the Msg/UpdateSignalsAndInterval RPC method.
message MsgUpdateSignalsAndIntervalResponse {}

// MsgWithdrawFeePayerFunds is the transaction message to withdraw fee payer funds to creator.
message MsgWithdrawFeePayerFunds {
option (cosmos.msg.v1.signer) = "fee_payer";
option (amino.name) = "tunnel/MsgWithdrawFeePayerCoins";

// tunnel_id is the ID of the tunnel to withdraw fee payer coins.
uint64 tunnel_id = 1 [(gogoproto.customname) = "TunnelID"];
// coins is the coins to withdraw.
repeated cosmos.base.v1beta1.Coin amount = 2 [
(gogoproto.nullable) = false,
(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins",
(amino.dont_omitempty) = true
];
// creator is the address of the creator.
string creator = 3 [(cosmos_proto.scalar) = "cosmos.AddressString"];
}

// MsgWithdrawFeePayerFundsResponse is the response type for the Msg/WithdrawFeePayerFunds RPC method.
message MsgWithdrawFeePayerFundsResponse {}

// Activate is the transaction message to activate a tunnel.
message MsgActivate {
option (cosmos.msg.v1.signer) = "creator";
Expand Down
32 changes: 32 additions & 0 deletions x/tunnel/client/cli/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ func GetTxCmd() *cobra.Command {
GetTxCmdCreateTunnel(),
GetTxCmdUpdateRoute(),
GetTxCmdUpdateSignalsAndInterval(),
GetTxCmdWithdrawFeePayerFunds(),
GetTxCmdActivate(),
GetTxCmdDeactivate(),
GetTxCmdTriggerTunnel(),
Expand Down Expand Up @@ -246,6 +247,37 @@ func GetTxCmdUpdateSignalsAndInterval() *cobra.Command {
return cmd
}

func GetTxCmdWithdrawFeePayerFunds() *cobra.Command {
cmd := &cobra.Command{
Use: "withdraw-fee-payer-funds [tunnel-id] [amount]",
Short: "Withdraw fee payer funds from a tunnel to the creator",
Args: cobra.ExactArgs(2),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientTxContext(cmd)
if err != nil {
return err
}

id, err := strconv.ParseUint(args[0], 10, 64)
if err != nil {
return err
}

amount, err := sdk.ParseCoinsNormalized(args[1])
if err != nil {
return err
}

msg := types.NewMsgWithdrawFeePayerFunds(id, amount, clientCtx.GetFromAddress().String())
return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg)
},
}

flags.AddTxFlagsToCmd(cmd)

return cmd
}

func GetTxCmdActivate() *cobra.Command {
cmd := &cobra.Command{
Use: "activate [tunnel-id]",
Expand Down
29 changes: 29 additions & 0 deletions x/tunnel/keeper/msg_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,35 @@ func (k msgServer) UpdateSignalsAndInterval(
return &types.MsgUpdateSignalsAndIntervalResponse{}, nil
}

// WithdrawFeePayerFunds withdraws the fee payer's funds from the tunnel to the creator.
func (k msgServer) WithdrawFeePayerFunds(
goCtx context.Context,
msg *types.MsgWithdrawFeePayerFunds,
) (*types.MsgWithdrawFeePayerFundsResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)

tunnel, err := k.Keeper.GetTunnel(ctx, msg.TunnelID)
if err != nil {
return nil, err
}

if msg.Creator != tunnel.Creator {
return nil, types.ErrInvalidTunnelCreator.Wrapf("creator %s, tunnelID %d", msg.Creator, msg.TunnelID)
}

// send coins from the fee payer to the creator
if err := k.Keeper.bankKeeper.SendCoins(
ctx,
sdk.AccAddress(tunnel.FeePayer),
sdk.AccAddress(tunnel.Creator),
msg.Amount,
); err != nil {
return nil, err
}

return &types.MsgWithdrawFeePayerFundsResponse{}, nil
}

// Activate activates a tunnel.
func (k msgServer) Activate(
goCtx context.Context,
Expand Down
22 changes: 14 additions & 8 deletions x/tunnel/testutil/expected_keepers_mocks.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion x/tunnel/types/expected_keepers.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ type AccountKeeper interface {
}

type BankKeeper interface {
SendCoins(ctx context.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins) error
GetAllBalances(ctx context.Context, addr sdk.AccAddress) sdk.Coins
SpendableCoins(ctx context.Context, addr sdk.AccAddress) sdk.Coins

SendCoinsFromModuleToAccount(
ctx context.Context,
senderModule string,
Expand Down
30 changes: 27 additions & 3 deletions x/tunnel/types/msgs.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ import (
)

var (
_, _, _, _, _, _, _, _, _ sdk.Msg = &MsgCreateTunnel{}, &MsgUpdateRoute{}, &MsgUpdateSignalsAndInterval{}, &MsgActivate{}, &MsgDeactivate{}, &MsgTriggerTunnel{}, &MsgDepositToTunnel{}, &MsgWithdrawFromTunnel{}, &MsgUpdateParams{}
_, _, _, _, _, _, _, _, _ sdk.HasValidateBasic = &MsgCreateTunnel{}, &MsgUpdateRoute{}, &MsgUpdateSignalsAndInterval{}, &MsgActivate{}, &MsgDeactivate{}, &MsgTriggerTunnel{}, &MsgDepositToTunnel{}, &MsgWithdrawFromTunnel{}, &MsgUpdateParams{}
_, _ types.UnpackInterfacesMessage = &MsgCreateTunnel{}, &MsgUpdateRoute{}
_, _, _, _, _, _, _, _, _, _ sdk.Msg = &MsgCreateTunnel{}, &MsgUpdateRoute{}, &MsgUpdateSignalsAndInterval{}, &MsgWithdrawFeePayerFunds{}, &MsgActivate{}, &MsgDeactivate{}, &MsgTriggerTunnel{}, &MsgDepositToTunnel{}, &MsgWithdrawFromTunnel{}, &MsgUpdateParams{}
_, _, _, _, _, _, _, _, _ sdk.HasValidateBasic = &MsgCreateTunnel{}, &MsgUpdateRoute{}, &MsgUpdateSignalsAndInterval{}, &MsgActivate{}, &MsgDeactivate{}, &MsgTriggerTunnel{}, &MsgDepositToTunnel{}, &MsgWithdrawFromTunnel{}, &MsgUpdateParams{}
_, _ types.UnpackInterfacesMessage = &MsgCreateTunnel{}, &MsgUpdateRoute{}
)

// NewMsgCreateTunnel creates a new MsgCreateTunnel instance.
Expand Down Expand Up @@ -228,6 +228,30 @@ func (m MsgUpdateSignalsAndInterval) ValidateBasic() error {
return nil
}

// NewMsgWithdrawFeePayerFunds creates a new MsgWithdrawFeePayerFunds instance.
func NewMsgWithdrawFeePayerFunds(tunnelID uint64, amount sdk.Coins, creator string) *MsgWithdrawFeePayerFunds {
return &MsgWithdrawFeePayerFunds{
TunnelID: tunnelID,
Amount: amount,
Creator: creator,
}
}

// ValidateBasic does a sanity check on the provided data
func (m MsgWithdrawFeePayerFunds) ValidateBasic() error {
// creator address must be valid
if _, err := sdk.AccAddressFromBech32(m.Creator); err != nil {
return sdkerrors.ErrInvalidAddress.Wrapf("invalid address: %s", err)
}

// amount must be valid
if !m.Amount.IsValid() {
return sdkerrors.ErrInvalidCoins.Wrapf("invalid funds: %s", m.Amount)
}

return nil
}

// NewMsgActivate creates a new MsgActivate instance.
func NewMsgActivate(
tunnelID uint64,
Expand Down
Loading

0 comments on commit 3bf764d

Please sign in to comment.