Now it is time to define the Msg
for deleting names and add it to the ./x/nameservice/types/msgs.go
file. This code is very similar to SetName
:
// MsgDeleteName defines a DeleteName message
type MsgDeleteName struct {
Name string `json:"name"`
Owner sdk.AccAddress `json:"owner"`
}
// NewMsgDeleteName is a constructor function for MsgDeleteName
func NewMsgDeleteName(name string, owner sdk.AccAddress) MsgDeleteName {
return MsgDeleteName{
Name: name,
Owner: owner,
}
}
// Route should return the name of the module
func (msg MsgDeleteName) Route() string { return RouterKey }
// Type should return the action
func (msg MsgDeleteName) Type() string { return "delete_name" }
// ValidateBasic runs stateless checks on the message
func (msg MsgDeleteName) ValidateBasic() sdk.Error {
if msg.Owner.Empty() {
return sdk.ErrInvalidAddress(msg.Owner.String())
}
if len(msg.Name) == 0 {
return sdk.ErrUnknownRequest("Name cannot be empty")
}
return nil
}
// GetSignBytes encodes the message for signing
func (msg MsgDeleteName) GetSignBytes() []byte {
return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(msg))
}
// GetSigners defines whose signature is required
func (msg MsgDeleteName) GetSigners() []sdk.AccAddress {
return []sdk.AccAddress{msg.Owner}
}
Next, in the ./x/nameservice/handler.go
file, add the MsgDeleteName
handler to the module router:
// NewHandler returns a handler for "nameservice" type messages.
func NewHandler(keeper Keeper) sdk.Handler {
return func(ctx sdk.Context, msg sdk.Msg) sdk.Result {
switch msg := msg.(type) {
case MsgSetName:
return handleMsgSetName(ctx, keeper, msg)
case MsgBuyName:
return handleMsgBuyName(ctx, keeper, msg)
case MsgDeleteName:
return handleMsgDeleteName(ctx, keeper, msg)
default:
errMsg := fmt.Sprintf("Unrecognized nameservice Msg type: %v", msg.Type())
return sdk.ErrUnknownRequest(errMsg).Result()
}
}
}
Finally, define the DeleteName
handler
function which performs the state transitions triggered by the message. Keep in mind that at this point the message has had its ValidateBasic
function run so there has been some input verification. However, ValidateBasic
cannot query application state. Validation logic that is dependent on network state (e.g. account balances) should be performed in the handler
function.
// Handle a message to delete name
func handleMsgDeleteName(ctx sdk.Context, keeper Keeper, msg MsgDeleteName) sdk.Result {
if !keeper.IsNamePresent(ctx, msg.Name) {
return types.ErrNameDoesNotExist(types.DefaultCodespace).Result()
}
if !msg.Owner.Equals(keeper.GetOwner(ctx, msg.Name)) {
return sdk.ErrUnauthorized("Incorrect Owner").Result()
}
keeper.DeleteWhois(ctx, msg.Name)
return sdk.Result{}
}
First check to see if the name currently exists in the store. If not, throw an error and return that to the user. Then check to see if the Msg
sender is actually the owner of the name (keeper.GetOwner
). If so, they can delete the name by calling the function on the Keeper
. If not, throw an error and return that to the user.