Skip to content

Commit

Permalink
Adds more code for the user to copy/paste
Browse files Browse the repository at this point in the history
  • Loading branch information
toschdev committed Nov 6, 2023
1 parent 170c57d commit fda2d65
Showing 1 changed file with 216 additions and 2 deletions.
218 changes: 216 additions & 2 deletions docs/docs/02-guide/06-tokenfactory/01-tokenfactory.md
Original file line number Diff line number Diff line change
Expand Up @@ -220,30 +220,126 @@ In `x/tokenfactory/types/messages_denom.go`:
Implement basic input validation in `x/tokenfactory/types/messages_denom.go`:

- Ensure the ticker length is between 3 and 10 characters.
```go
func (msg *MsgCreateDenom) ValidateBasic() error {
_, err := sdk.AccAddressFromBech32(msg.Owner)
if err != nil {
return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "invalid owner address (%s)", err)
}

tickerLength := len(msg.Ticker)
if tickerLength < 3 {
return sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "Ticker length must be at least 3 chars long")
}
if tickerLength > 10 {
return sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "Ticker length must be 10 chars long maximum")
}
if msg.MaxSupply == 0 {
return sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "Max Supply must be greater than 0")
}

return nil
}
```

- Set `maxSupply` to be greater than 0.

```go
func (msg *MsgUpdateDenom) ValidateBasic() error {
_, err := sdk.AccAddressFromBech32(msg.Owner)
if err != nil {
return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "invalid owner address (%s)", err)
}
if msg.MaxSupply == 0 {
return sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "Max Supply must be greater than 0")
}
return nil
}
```

### Keeper Logic

The keeper is where you define the business logic for manipulating the database and writing to the key-value store.

**In `x/tokenfactory/keeper/msg_server_denom.go`:**

- Update `CreateDenom()` to include logic for creating unique denoms.
- Update `CreateDenom()` to include logic for creating unique denoms. Modify the error message to point to existing denoms. Set `Supply` to `0`.
- Modify `UpdateDenom()` to verify ownership and manage max supply changes.

```go
func (k msgServer) UpdateDenom(goCtx context.Context, msg *types.MsgUpdateDenom) (*types.MsgUpdateDenomResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)

// Check if the value exists
valFound, isFound := k.GetDenom(
ctx,
msg.Denom,
)
if !isFound {
return nil, sdkerrors.Wrap(sdkerrors.ErrKeyNotFound, "index not set")
}

// Checks if the the msg owner is the same as the current owner
if msg.Owner != valFound.Owner {
return nil, sdkerrors.Wrap(sdkerrors.ErrUnauthorized, "incorrect owner")
}

if !valFound.CanChangeMaxSupply && valFound.MaxSupply != msg.MaxSupply {
return nil, sdkerrors.Wrap(sdkerrors.ErrUnauthorized, "cannot change maxsupply")
}
if !valFound.CanChangeMaxSupply && msg.CanChangeMaxSupply {
return nil, sdkerrors.Wrap(sdkerrors.ErrUnauthorized, "Cannot revert change maxsupply flag")
}
var denom = types.Denom{
Owner: msg.Owner,
Denom: msg.Denom,
Description: msg.Description,
Ticker: valFound.Ticker,
Precision: valFound.Precision,
Url: msg.Url,
MaxSupply: msg.MaxSupply,
Supply: valFound.Supply,
CanChangeMaxSupply: msg.CanChangeMaxSupply,
}

k.SetDenom(ctx, denom)

return &types.MsgUpdateDenomResponse{}, nil
}
```

### Expected Keepers

`x/tokenfactory/types/expected_keepers.go` is where you define interactions with other modules. Since your module relies on the `auth` and `bank` modules, specify which of their functions your module can access.

Replace the existing code in `expected_keepers.go` with the updated definitions that interface with `auth` and `bank` modules.

```go
package types

import (
sdk "github.com/cosmos/cosmos-sdk/types"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
)

type AccountKeeper interface {
GetAccount(ctx sdk.Context, addr sdk.AccAddress) authtypes.AccountI
GetModuleAddress(name string) sdk.AccAddress
GetModuleAccount(ctx sdk.Context, moduleName string) authtypes.ModuleAccountI
}

type BankKeeper interface {
SendCoins(ctx sdk.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins) error
MintCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) error
}
```

### Commiting Your Changes

Regular commits are vital for tracking progress and ensuring a stable rollback point if needed. After implementing these changes, use the following commands to commit:

```bash
it add .
git add .
git commit -m "Add token factory create and update logic"
```

Expand Down Expand Up @@ -297,8 +393,126 @@ Found in `x/tokenfactory/keeper/msg_server_update_owner.go`, this function allow
### Keeper Logic

- For `MintAndSendTokens`, add logic to mint new tokens as per the request parameters. This includes checking for maximum supply limits and transferring the minted tokens to the specified recipient.

```go
package keeper

import (
"context"

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

func (k msgServer) MintAndSendTokens(goCtx context.Context, msg *types.MsgMintAndSendTokens) (*types.MsgMintAndSendTokensResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)

// Check if the value exists
valFound, isFound := k.GetDenom(
ctx,
msg.Denom,
)
if !isFound {
return nil, sdkerrors.Wrap(sdkerrors.ErrKeyNotFound, "denom does not exist")
}

// Checks if the the msg owner is the same as the current owner
if msg.Owner != valFound.Owner {
return nil, sdkerrors.Wrap(sdkerrors.ErrUnauthorized, "incorrect owner")
}

if valFound.Supply+msg.Amount > valFound.MaxSupply {
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Cannot mint more than Max Supply")
}
moduleAcct := k.accountKeeper.GetModuleAddress(types.ModuleName)

recipientAddress, err := sdk.AccAddressFromBech32(msg.Recipient)
if err != nil {
return nil, err
}

var mintCoins sdk.Coins

mintCoins = mintCoins.Add(sdk.NewCoin(msg.Denom, sdk.NewInt(int64(msg.Amount))))
if err := k.bankKeeper.MintCoins(ctx, types.ModuleName, mintCoins); err != nil {
return nil, err
}
if err := k.bankKeeper.SendCoins(ctx, moduleAcct, recipientAddress, mintCoins); err != nil {
return nil, err
}

var denom = types.Denom{
Owner: valFound.Owner,
Denom: valFound.Denom,
Description: valFound.Description,
MaxSupply: valFound.MaxSupply,
Supply: valFound.Supply + msg.Amount,
Precision: valFound.Precision,
Ticker: valFound.Ticker,
Url: valFound.Url,
CanChangeMaxSupply: valFound.CanChangeMaxSupply,
}

k.SetDenom(
ctx,
denom,
)
return &types.MsgMintAndSendTokensResponse{}, nil
}
```

- For `UpdateOwner`, implement the logic to update the owner of a denom, ensuring that only the current owner can initiate this change.

```go
package keeper

import (
"context"

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

func (k msgServer) UpdateOwner(goCtx context.Context, msg *types.MsgUpdateOwner) (*types.MsgUpdateOwnerResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)

// Check if the value exists
valFound, isFound := k.GetDenom(
ctx,
msg.Denom,
)
if !isFound {
return nil, sdkerrors.Wrap(sdkerrors.ErrKeyNotFound, "denom does not exist")
}

// Checks if the the msg owner is the same as the current owner
if msg.Owner != valFound.Owner {
return nil, sdkerrors.Wrap(sdkerrors.ErrUnauthorized, "incorrect owner")
}

var denom = types.Denom{
Owner: msg.NewOwner,
Denom: msg.Denom,
Description: valFound.Description,
MaxSupply: valFound.MaxSupply,
Supply: valFound.Supply,
Precision: valFound.Precision,
Ticker: valFound.Ticker,
Url: valFound.Url,
CanChangeMaxSupply: valFound.CanChangeMaxSupply,
}

k.SetDenom(
ctx,
denom,
)

return &types.MsgUpdateOwnerResponse{}, nil
}
```

### Committing Your Changes

After implementing these new functionalities, it's crucial to save your progress. Use the following commands:
Expand Down

0 comments on commit fda2d65

Please sign in to comment.