Path: blob/main/docs/versioned_docs/version-v0.25/guide/03-blog/00-build-blog.md
1007 views
---
---
Build a blog
In this tutorial, you create a blockchain with a module that lets you write to and read data from the blockchain. This module implements create and read functionalities for a blog-like application. The end user will be able to submit new blog posts and show a list of blog posts on the blockchain.
The purpose of this tutorial is to guide you through the implementation of a complete feedback loop: submitting data and reading this data back from the blockchain.
By completing this tutorial, you will learn about:
Scaffolding a Cosmos SDK message
Defining new types in protocol buffer files
Implementing keeper methods to write data to the store
Reading data from the store and return it as a result of a query
Using the blockchain's CLI to broadcast transactions and query the blockchain
Note: All the functions in this chapter can be scaffolded with a single command but instead you will learn how to add each functionality individually.
Prerequisites
This series of blog tutorials is based on a specific version of Ignite CLI, so to install Ignite CLI v0.22.2 use the following command:
Create your blog chain
First, create a new blockchain.
Open a terminal and navigate to a directory where you have permissions to create files. To create your Cosmos SDK blockchain, run this command:
The blog
directory is created with the default directory structure.
The new blockchain is scaffolded with the --address-prefix blog
flag to use "blog" instead of the default "cosmos" address prefix.
High-level transaction review
So far, you have learned how to modify proto files to define a new API endpoint and modify a keeper query function to return static data back to the user. Of course, a keeper can do more than return a string of data. Its purpose is to manage access to the state of the blockchain.
You can think of the state as being a collection of key-value stores. Each module is responsible for its own store. Changes to the store are triggered by transactions that are signed and broadcasted by users. Each transaction contains Cosmos SDK messages (not to be confused with proto message
). When a transaction is processed, each message gets routed to its module. A module has message handlers that process messages. Processing a message can trigger changes in the state.
Create message types
A Cosmos SDK message contains information that can trigger changes in the state of a blockchain.
First, change into the blog
directory:
To create a message type and its handler, use the message
command:
The message
command accepts message name (createPost
) and a list of fields (title
and body
) as arguments.
The message
command has created and modified several files:
As always, start with a proto file. Inside the proto/blog/tx.proto
file, the MsgCreatePost
message has been created. Edit the file to add the line that defines the id
for message MsgCreatePostResponse
:
Review the message code
Review the Cosmos SDK message type with proto message
. The MsgCreatePost
has three fields: creator, title, and body. Since the purpose of the MsgCreatePost
message is to create new posts in the store, the only thing the message needs to return is an ID of a created post. The CreatePost
rpc was already added to the Msg
service:
Define messages logic
In the newly scaffolded x/blog/keeper/msg_server_create_post.go
file, you can see a placeholder implementation of the CreatePost
function. Right now it does nothing and returns an empty response. For your blog chain, you want the contents of the message (title and body) to be written to the state as a new post.
You need to do two things:
Create a variable of type
Post
with title and body from the messageAppend this
Post
to the store
Define Post type and AppendPost keeper method
Define the Post
type and the AppendPost
keeper method.
When you define the Post
type in a proto file, Ignite CLI (with the help of protoc
) takes care of generating the required Go files.
Create the proto/blog/post.proto
file and define the Post
message:
The contents of the post.proto
file are standard. The file defines:
A package name
blog.blog
that is used to identify messagesThe Go package
go_package = "blog/x/blog/types"
where new files are generatedThe message
message Post
Continue developing your blog chain.
Define keeper methods
The next step is to define the AppendPost
keeper method.
Create the x/blog/keeper/post.go
file and start thinking about the logic of the function and what you want to call the prefixes. The file will be empty for now.
To implement
AppendPost
you must first understand how the key store works. You can think of a store as a key-value database where keys are lexicographically ordered. You can loop through keys and useGet
andSet
to retrieve and set values based on keys. To distinguish between different types of data that a module can keep in its store, you can use prefixes likeproduct/
orpost/
.To keep a list of posts in what is essentially a key-value store, you need to keep track of the index of the posts you insert. Since both post values and post count (index) values are kept in the store, you can use different prefixes:
Post/value/
andPost/count/
.
Then, add these prefixes to the x/blog/types/keys.go
file in the const
and add a comment that describes the keys:
Your blog is now updated to take these actions when a Post
message is sent to the AppendPost
function:
Get the number of posts in the store (count)
Add a post by using the count as an ID
Increment the count
Return the count
Write data to the store
In the x/blog/keeper/post.go
file, draft the AppendPost
function. You can add these comments to help you visualize what you do next:
First, implement GetPostCount
:
Now that GetPostCount
returns the correct number of posts in the store, implement SetPostCount
:
Now that you have implemented functions for getting the number of posts and setting the post count, at the top of the same x/blog/keeper/post.go
file, implement the logic behind the AppendPost
function:
By following these steps, you have implemented all of the code required to create new posts and store them on-chain. Now, when a transaction that contains a message of type MsgCreatePost
is broadcast, the message is routed to your blog module.
k.CreatePost
callsAppendPost
AppendPost
gets the number of posts from the store, adds a post using the count as an ID, increments the count, and returns the ID
Now that you have added the functionality to create posts and broadcast them to our chain, you can add querying.
Display posts
To display posts, scaffold a query:
Two components are responsible for querying data:
An rpc inside
service Query
in a proto file that defines data types and specifies the HTTP API endpointA keeper method that performs the querying from the key-value store
First, review the services and messages in proto/blog/query.proto
. The Posts
rpc accepts an empty request and returns an object with two fields: title and body. Now you can make changes so it can return a list of posts. The list of posts can be long, so add pagination. When pagination is added, the request and response include a page number so you can request a particular page when you know what page has been returned.
To define the types in proto files, make the following updates in proto/blog/query.proto
:
Add the
import
:
Add pagination to the post request:
Add pagination to the post response:
To implement post querying logic in the x/blog/keeper/grpc_query_posts.go
file, delete the contents of that file and replace it with:
Add gRPC to the module handler
In the x/blog/module.go
file:
Add
"context"
to the imports, don't save the file yet.
Update the
RegisterGRPCGatewayRoutes
function to register the query handler client:
Now that you've modified the file with the two updates, now it's safe to save the file.
Use the CLI to create a post
Now that you have implemented logic for creating and querying posts, you can interact with your blog chain using the command line. The blog chain binary is blogd
.
First, start the chain on your development machine by running the following command in the blog
directory:
The binary is built by the ignite chain serve
command bit it can also be built by running:
To create a post at the command line:
The transaction is output to the terminal. You are prompted to confirm the transaction:
Type y
to sign and broadcast the transaction.
Congratulations, you built a chain binary and used the blogd
binary CLI to create a blog post.
Use the CLI to query posts
To query the list of all on-chain posts:
The result:
Conclusion
Congratulations. You have built a blog blockchain!
You have successfully completed these steps:
Write blog posts to your chain
Read from blog posts
Scaffold a Cosmos SDK message
Define new types in protocol buffer files
Write keeper methods to write data to the store
Register query handlers
Read data from the store and return it as a result a query
Use the CLI to broadcast transactions