Skip to content

Commit

Permalink
fix(docs): some typos + new nameservice challenge
Browse files Browse the repository at this point in the history
  • Loading branch information
Reecepbcups committed Sep 12, 2024
1 parent 288f5f3 commit 34c143e
Show file tree
Hide file tree
Showing 12 changed files with 245 additions and 71 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ Find `query.proto` and add the following
// ResolveName allows a user to resolve the name of an account.
rpc ResolveName(QueryResolveNameRequest) returns (QueryResolveNameResponse) {
option (google.api.http).get = "/nameservice/v1/names/{wallet}";
option (google.api.http).get = "/nameservice/v1/name/{wallet}";
}
}
Expand All @@ -72,7 +72,6 @@ proto/nameservice/v1/query.proto
These .proto file templates will be converted into Golang source code for you to use. Build the Go source code using the command:

```bash
// highlight-next-line
make proto-gen
```

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ You now need to set the data structure in the keeper to store the wallet to name

type Keeper struct {
...
// highlight-next-line
NameMapping collections.Map[string, string]
}

Expand All @@ -23,7 +24,7 @@ func NewKeeper() Keeper {

k := Keeper{
...

// highlight-next-line
NameMapping: collections.NewMap(sb, collections.NewPrefix(1), "name_mapping", collections.StringKey, collections.StringValue),
}

Expand All @@ -40,18 +41,21 @@ Update the msg_server logic to set the name upon request from a user.

```go title="x/nameservice/keeper/msg_server.go"
func (ms msgServer) SetServiceName(ctx context.Context, msg *types.MsgSetServiceName) (*types.MsgSetServiceNameResponse, error) {
// highlight-start
if err := ms.k.NameMapping.Set(ctx, msg.Sender, msg.Name); err != nil {
return nil, err
}

return &types.MsgSetServiceNameResponse{}, nil
// highlight-end
}
```

and also for the query_server to retrieve the name.

```go title="x/nameservice/keeper/query_server.go"
func (k Querier) ResolveName(goCtx context.Context, req *types.QueryResolveNameRequest) (*types.QueryResolveNameResponse, error) {
// highlight-start
v, err := k.Keeper.NameMapping.Get(goCtx, req.Wallet)
if err != nil {
return nil, err
Expand All @@ -60,6 +64,7 @@ func (k Querier) ResolveName(goCtx context.Context, req *types.QueryResolveNameR
return &types.QueryResolveNameResponse{
Name: v,
}, nil
// highlight-end
}
```

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ Update the autocli to allow someone to get the name of a wallet account.
Query: &autocliv1.ServiceCommandDescriptor{
Service: modulev1.Query_ServiceDesc.ServiceName,
RpcCommandOptions: []*autocliv1.RpcCommandOptions{
// highlight-start
{
RpcMethod: "ResolveName",
Use: "resolve [wallet]",
Expand All @@ -25,6 +26,7 @@ Update the autocli to allow someone to get the name of a wallet account.
{ProtoField: "wallet"},
},
},
// highlight-end
{
RpcMethod: "Params",
Use: "params",
Expand All @@ -34,7 +36,12 @@ Update the autocli to allow someone to get the name of a wallet account.
},
```

![AutoCLI Query](https://github.com/rollchains/spawn/assets/31943163/fefe8c7d-88b5-42d5-afd9-cb33cd22df16)
<details>
<summary>AutoCLI Query</summary>

![AutoCLI Query](https://github.com/rollchains/spawn/assets/31943163/fefe8c7d-88b5-42d5-afd9-cb33cd22df16)
</details>



### Transaction
Expand All @@ -45,6 +52,7 @@ Also add interaction in `x/nameservice/autocli.go` to set the name of a wallet a
Tx: &autocliv1.ServiceCommandDescriptor{
Service: modulev1.Msg_ServiceDesc.ServiceName,
RpcCommandOptions: []*autocliv1.RpcCommandOptions{
// highlight-start
{
RpcMethod: "SetServiceName",
Use: "set [name]",
Expand All @@ -53,6 +61,7 @@ Also add interaction in `x/nameservice/autocli.go` to set the name of a wallet a
{ProtoField: "name"},
},
},
// highlight-end
{
// NOTE: this is already included in the current source
RpcMethod: "UpdateParams",
Expand All @@ -62,4 +71,10 @@ Also add interaction in `x/nameservice/autocli.go` to set the name of a wallet a
},
```

![AutoCLI Tx](https://github.com/rollchains/spawn/assets/31943163/e945c898-415c-4d22-8bb3-b8af34a44cee)
<details>
<summary>AutoCLI Tx</summary>

![AutoCLI Tx](https://github.com/rollchains/spawn/assets/31943163/e945c898-415c-4d22-8bb3-b8af34a44cee)
</details>


Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
---
title: "Name Service"
sidebar_label: "Bonus"
sidebar_position: 6
slug: /build/name-service-bonus
---

# Extra Challenges

## Challenge 1: Limit Input

It seems the nameservice will let you set any name length you want. Add a validation check in `SetServiceName` to ensure the name is less than 32 characters long.

<details>
<summary>Hint #1</summary>
<p>The `SetServiceName` in the msg_server.go looks like an interesting place to start. It should return an error if the name is too long.</p>
</details>

<details>
<summary>Solution</summary>

If a user attempts to submit a name longer than 32 characters, it will return an error that is not allowed.
```go title="x/nameservice/keeper/msg_server.go"
// SetServiceName implements types.MsgServer.
func (ms msgServer) SetServiceName(ctx context.Context, msg *types.MsgSetServiceName) (*types.MsgSetServiceNameResponse, error) {
if len(msg.Name) > 32 {
return nil, fmt.Errorf("name cannot be longer than 32 characters")
}

if err := ms.k.NameMapping.Set(ctx, msg.Sender, msg.Name); err != nil {
return nil, err
}

return &types.MsgSetServiceNameResponse{}, nil
}
```
</details>


## Challenge 2: Resolve Wallet From Name

Currently the nameservice only allows you to resolve a name given a wallet. If someone has a name they should be able to resolve the wallet address. Add a new query to the `query_server` and autocli client to resolve a wallet address from a name.

> This challenge is signinicantly harder and will some previous Go programming knowledge with iterators. You can also just copy the solutions.
<details>
<summary>Hint #1</summary>
<p>Create a new query.proto for ResolveWallet that takes in a name string</p>
</details>

<details>
<summary>Solution #1</summary>

```protobuf title="proto/nameservice/v1/query.proto"
// Query provides defines the gRPC querier service.
service Query {
// Params queries all parameters of the module.
rpc Params(QueryParamsRequest) returns (QueryParamsResponse) {
option (google.api.http).get = "/nameservice/v1/params";
}
// ResolveName allows a user to resolve the name of an account.
rpc ResolveName(QueryResolveNameRequest) returns (QueryResolveNameResponse) {
option (google.api.http).get = "/nameservice/v1/name/{wallet}";
}
// highlight-start
// ResolveWallet allows a user to resolve the wallet of a name.
rpc ResolveWallet(QueryResolveWalletRequest) returns (QueryResolveWalletResponse) {
option (google.api.http).get = "/nameservice/v1/wallet/{name}";
}
// highlight-end
}
// highlight-start
message QueryResolveWalletRequest {
string name = 1;
}
message QueryResolveWalletResponse {
string wallet = 1;
}
// highlight-end
```

```bash
make proto-gen
```

</details>

<details>
<summary>Hint #2</summary>
<p>Iterate through the `k.Keeper.NameMapping`, check the Value(). if it matches the name we requested, return that wallet (Key)</p>
</details>

<details>
<summary>Solution #2</summary>

```go title="x/nameservice/keeper/query_server.go"
// ResolveWallet implements types.QueryServer.
func (k Querier) ResolveWallet(goCtx context.Context, req *types.QueryResolveWalletRequest) (*types.QueryResolveWalletResponse, error) {
// highlight-start
// create a way to iterate over all the name mappings.
iter, err := k.Keeper.NameMapping.Iterate(goCtx, nil)
if err != nil {
return nil, err
}
defer iter.Close()

for ; iter.Valid(); iter.Next() {
// get the value (name)
v, err := iter.Value()
if err != nil {
return nil, err
}

// if current name matches the requested name,
// return the wallet address for the name
if v == req.Name {
walletAddr, err := iter.Key()
if err != nil {
return nil, err
}

return &types.QueryResolveWalletResponse{
Wallet: walletAddr,
}, nil
}
}

return nil, fmt.Errorf("wallet not found for name %s", req.Name)
// highlight-end
}


```
This is not the most efficient way to do this. If you would like, create a new WalletMapping collection that maps name->sender when `SetServiceName` is called. This way you can resolve the wallet from the name in O(1) time (i.e. instant) instead of looping through all possible wallets.

</details>


<details>
<summary>Hint #3</summary>
<p>Add the AutoCLI method to `ResolveWallet` with the `ProtoField` "name" to match the .proto file</p>
</details>


<details>
<summary>Solution #3</summary>

```go title="x/nameservice/autocli.go"
func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions {
return &autocliv1.ModuleOptions{
Query: &autocliv1.ServiceCommandDescriptor{
Service: modulev1.Query_ServiceDesc.ServiceName,
RpcCommandOptions: []*autocliv1.RpcCommandOptions{
{
RpcMethod: "ResolveName",
Use: "resolve [wallet]",
Short: "Resolve the name of a wallet address",
PositionalArgs: []*autocliv1.PositionalArgDescriptor{
{ProtoField: "wallet"},
},
},
// highlight-start
{
RpcMethod: "ResolveWallet",
Use: "wallet [name]",
Short: "Resolve the wallet address from a given name",
PositionalArgs: []*autocliv1.PositionalArgDescriptor{
{ProtoField: "name"},
},
},
// highlight-end
{
RpcMethod: "Params",
Use: "params",
Short: "Query the current module parameters",
},
},
},
...
```
Then `make install` and re-run the testnet to verify `rolld q nameservice wallet <name>` returns the expected wallet address.
</details>
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,9 @@ You just crafted your first blockchain, module, and custom logic with Spawn. You
* Running a local testnet
* Interacting with the network

# What's Next?
## What's Next?

Extend the NameService to include IBC support with the [ibc-module](../03-demos/02-ibc-module.md) tutorial.



<!-- TODO: What's next? (further interaction, Go,TS,Python, public testnet with github, frontend, explorer, cosmwasm) -->
<!-- TODO: query via rest api -->
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"label": "Your First Application",
"position": 2,
"link": null
}

This file was deleted.

This file was deleted.

Loading

0 comments on commit 34c143e

Please sign in to comment.