1"use strict";(globalThis.webpackChunkmy_website=globalThis.webpackChunkmy_website||[]).push([[3813],{15680(e,t,n){n.d(t,{xA:()=>d,yg:()=>c});var o=n(96540);function i(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function a(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);t&&(o=o.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,o)}return n}function s(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?a(Object(n),!0).forEach((function(t){i(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):a(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function r(e,t){if(null==e)return{};var n,o,i=function(e,t){if(null==e)return{};var n,o,i={},a=Object.keys(e);for(o=0;o<a.length;o++)n=a[o],t.indexOf(n)>=0||(i[n]=e[n]);return i}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(o=0;o<a.length;o++)n=a[o],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}var p=o.createContext({}),l=function(e){var t=o.useContext(p),n=t;return e&&(n="function"==typeof e?e(t):s(s({},t),e)),n},d=function(e){var t=l(e.components);return o.createElement(p.Provider,{value:t},e.children)},g={inlineCode:"code",wrapper:function(e){var t=e.children;return o.createElement(o.Fragment,{},t)}},h=o.forwardRef((function(e,t){var n=e.components,i=e.mdxType,a=e.originalType,p=e.parentName,d=r(e,["components","mdxType","originalType","parentName"]),h=l(n),c=i,y=h["".concat(p,".").concat(c)]||h[c]||g[c]||a;return n?o.createElement(y,s(s({ref:t},d),{},{components:n})):o.createElement(y,s({ref:t},d))}));function c(e,t){var n=arguments,i=t&&t.mdxType;if("string"==typeof e||i){var a=n.length,s=new Array(a);s[0]=h;var r={};for(var p in t)hasOwnProperty.call(t,p)&&(r[p]=t[p]);r.originalType=e,r.mdxType="string"==typeof e?e:i,s[1]=r;for(var l=2;l<a;l++)s[l]=n[l];return o.createElement.apply(null,s)}return o.createElement.apply(null,n)}h.displayName="MDXCreateElement"},5(e,t,n){n.r(t),n.d(t,{assets:()=>p,contentTitle:()=>s,default:()=>g,frontMatter:()=>a,metadata:()=>r,toc:()=>l});var o=n(58168),i=(n(96540),n(15680));const a={},s="Creating posts",r={unversionedId:"guide/blog/create",id:"version-v0.27/guide/blog/create",title:"Creating posts",description:'In this chapter, we will be focusing on the process of handling a "create post"',source:"@site/versioned_docs/version-v0.27/02-guide/04-blog/03-create.md",sourceDirName:"02-guide/04-blog",slug:"/guide/blog/create",permalink:"/v0.27/guide/blog/create",draft:!1,tags:[],version:"v0.27",sidebarPosition:3,frontMatter:{},sidebar:"tutorialSidebar",previous:{title:"Creating the structure",permalink:"/v0.27/guide/blog/scaffolding"},next:{title:"Updating posts",permalink:"/v0.27/guide/blog/update"}},p={},l=[{value:"Appending posts to the store",id:"appending-posts-to-the-store",level:2},{value:"Post key prefix",id:"post-key-prefix",level:3},{value:"Getting the post count",id:"getting-the-post-count",level:3},{value:"Converting post ID to bytes",id:"converting-post-id-to-bytes",level:3},{value:"Updating the post count",id:"updating-the-post-count",level:3},{value:"Handling the "create post" message",id:"handling-the-create-post-message",level:2},{value:"Summary",id:"summary",level:2}],d={toc:l};function g(e){let{components:t,...n}=e;return(0,i.yg)("wrapper",(0,o.A)({},d,n,{components:t,mdxType:"MDXLayout"}),(0,i.yg)("h1",{id:"creating-posts"},"Creating posts"),(0,i.yg)("p",null,'In this chapter, we will be focusing on the process of handling a "create post"\nmessage. This involves the use of a special type of function known as a keeper\nmethod. ',(0,i.yg)("a",{parentName:"p",href:"https://docs.cosmos.network/main/building-modules/keeper"},"Keeper"),"\nmethods are responsible for interacting with the blockchain and modifying its\nstate based on the instructions provided in a message."),(0,i.yg)("p",null,'When a "create post" message is received, the corresponding keeper method will\nbe called and passed the message as an argument. The keeper method can then use\nthe various getter and setter functions provided by the store object to retrieve\nand modify the current state of the blockchain. This allows the keeper method to\neffectively process the "create post" message and make the necessary updates to\nthe blockchain.'),(0,i.yg)("p",null,"In order to keep the code for accessing and modifying the store object clean and\nseparate from the logic implemented in the keeper methods, we will create a new\nfile called ",(0,i.yg)("inlineCode",{parentName:"p"},"post.go"),". This file will contain functions that are specifically\ndesigned to handle operations related to creating and managing posts within the\nblockchain."),(0,i.yg)("h2",{id:"appending-posts-to-the-store"},"Appending posts to the store"),(0,i.yg)("pre",null,(0,i.yg)("code",{parentName:"pre",className:"language-go",metastring:'title="x/blog/keeper/post.go"',title:'"x/blog/keeper/post.go"'},'package keeper\n\nimport (\n "encoding/binary"\n\n "blog/x/blog/types"\n\n "github.com/cosmos/cosmos-sdk/store/prefix"\n sdk "github.com/cosmos/cosmos-sdk/types"\n)\n\nfunc (k Keeper) AppendPost(ctx sdk.Context, post types.Post) uint64 {\n count := k.GetPostCount(ctx)\n post.Id = count\n store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.PostKey))\n appendedValue := k.cdc.MustMarshal(&post)\n store.Set(GetPostIDBytes(post.Id), appendedValue)\n
1k.SetPostCount(ctx, count+1)\n return count\n}\n')),(0,i.yg)("p",null,"This code defines a function called ",(0,i.yg)("inlineCode",{parentName:"p"},"AppendPost")," which belongs to a ",(0,i.yg)("inlineCode",{parentName:"p"},"Keeper"),"\ntype. The ",(0,i.yg)("inlineCode",{parentName:"p"},"Keeper")," type is responsible for interacting with the blockchain and\nmodifying its state in response to various messages."),(0,i.yg)("p",null,"The ",(0,i.yg)("inlineCode",{parentName:"p"},"AppendPost")," function takes in two arguments: a ",(0,i.yg)("inlineCode",{parentName:"p"},"Context")," object and a\n",(0,i.yg)("inlineCode",{parentName:"p"},"Post")," object. The ",(0,i.yg)("a",{parentName:"p",href:"https://docs.cosmos.network/main/core/context"},(0,i.yg)("inlineCode",{parentName:"a"},"Context")),"\nobject is a standard parameter in many functions in the Cosmos SDK and is used\nto provide contextual information about the current state of the blockchain,\nsuch as the current block height. The ",(0,i.yg)("inlineCode",{parentName:"p"},"Post")," object represents a post that will\nbe added to the blockchain."),(0,i.yg)("p",null,"The function begins by retrieving the current post count using the\n",(0,i.yg)("inlineCode",{parentName:"p"},"GetPostCount")," method. You will implement this method in the next step as it has\nnot been implemented yet. This method is called on the ",(0,i.yg)("inlineCode",{parentName:"p"},"Keeper")," object and takes\nin a ",(0,i.yg)("inlineCode",{parentName:"p"},"Context")," object as an argument. It returns the current number of posts\nthat have been added to the blockchain."),(0,i.yg)("p",null,"Next, the function sets the ID of the new post to be the current post count, so\nthat each post has a unique identifier. It does this by assigning the value of\ncount to the ",(0,i.yg)("inlineCode",{parentName:"p"},"Id")," field of the ",(0,i.yg)("inlineCode",{parentName:"p"},"Post")," object."),(0,i.yg)("p",null,"The function then creates a new\n",(0,i.yg)("a",{parentName:"p",href:"https://docs.cosmos.network/main/core/store"},"store")," object using the\n",(0,i.yg)("inlineCode",{parentName:"p"},"prefix.NewStore")," function. The ",(0,i.yg)("inlineCode",{parentName:"p"},"prefix.NewStore")," function takes in two\narguments: the ",(0,i.yg)("inlineCode",{parentName:"p"},"KVStore")," associated with the provided context and a key prefix\nfor the ",(0,i.yg)("inlineCode",{parentName:"p"},"Post")," objects. The ",(0,i.yg)("inlineCode",{parentName:"p"},"KVStore")," is a key-value store that is used to\npersist data on the blockchain, and the key prefix is used to differentiate the\n",(0,i.yg)("inlineCode",{parentName:"p"},"Post")," objects from other types of objects that may be stored in the same\n",(0,i.yg)("inlineCode",{parentName:"p"},"KVStore"),"."),(0,i.yg)("p",null,"The function then serializes the ",(0,i.yg)("inlineCode",{parentName:"p"},"Post")," object using the ",(0,i.yg)("inlineCode",{parentName:"p"},"cdc.MustMarshal"),"\nfunction and stores it in the blockchain using the ",(0,i.yg)("inlineCode",{parentName:"p"},"Set")," method of the store\nobject. The ",(0,i.yg)("inlineCode",{parentName:"p"},"cdc.MustMarshal")," function is part of the Cosmos SDK's\n",(0,i.yg)("a",{parentName:"p",href:"https://docs.cosmos.network/main/core/encoding"},"encoding/decoding")," library and\nis used to convert the ",(0,i.yg)("inlineCode",{parentName:"p"},"Post")," object into a byte slice that can be stored in the\n",(0,i.yg)("inlineCode",{parentName:"p"},"KVStore"),". The ",(0,i.yg)("inlineCode",{parentName:"p"},"Set")," method is called on the store object and takes in two\narguments: a key and a value. In this case, the key is a byte slice generated by\nthe ",(0,i.yg)("inlineCode",{parentName:"p"},"GetPostIDBytes")," function and the value is the serialized ",(0,i.yg)("inlineCode",{parentName:"p"},"Post")," object. You\nwill implement this method in the next step as it has not been implemented yet."),(0,i.yg)("p",null,"Finally, the function increments the post count by one and updates the\nblockchain state using the ",(0,i.yg)("inlineCode",{parentName:"p"},"SetPostCount")," method. You will implement this method\nin the next step as it has not been implemented yet. This method is called on\nthe Keeper object and takes in a ",(0,i.yg)("inlineCode",{parentName:"p"},"Context")," object and a new post count as\narguments. It updates the current post count in the blockchain to be the new\npost count provided."),(0,i.yg)("p",null,"The function then returns the ID of the newly created post, which is the current\npost count before it was incremented. This allows the caller of the function to\nknow the ID of the post that was just added to the blockchain."),(0,i.yg)("p",null,"To complete the implementation of ",(0,i.yg)("inlineCode",{parentName:"p"},"AppendPost"),", the following tasks need to be\nperformed:"),(0,i.yg)("ul",null,(0,i.yg)("li",{parentName:"ul"},"Define ",(0,i.yg)("inlineCode",{parentName:"li"},"PostKey"),", which will be used to store and retrieve posts from the\ndatabase."),(0,i.yg)("li",{parentName:"ul"},"Implement ",(0,i.yg)("inlineCode",{parentName:"li"},"GetPostCount"),", which will retrieve the current number of posts\nstored
1in the database."),(0,i.yg)("li",{parentName:"ul"},"Implement ",(0,i.yg)("inlineCode",{parentName:"li"},"GetPostIDBytes"),", which will convert a post ID to a byte array."),(0,i.yg)("li",{parentName:"ul"},"Implement ",(0,i.yg)("inlineCode",{parentName:"li"},"SetPostCount"),", which will update the post count stored in the\ndatabase.")),(0,i.yg)("h3",{id:"post-key-prefix"},"Post key prefix"),(0,i.yg)("p",null,"In the file ",(0,i.yg)("inlineCode",{parentName:"p"},"keys.go"),", let's define the ",(0,i.yg)("inlineCode",{parentName:"p"},"PostKey")," prefix as follows:"),(0,i.yg)("pre",null,(0,i.yg)("code",{parentName:"pre",className:"language-go",metastring:'title="x/blog/types/keys.go"',title:'"x/blog/types/keys.go"'},'const (\n PostKey = "Post/value/"\n)\n')),(0,i.yg)("p",null,"This prefix will be used to uniquely identify a post within the system. It will\nbe used as the beginning of the key for each post, followed by the ID of the\npost to create a unique key for each post."),(0,i.yg)("h3",{id:"getting-the-post-count"},"Getting the post count"),(0,i.yg)("p",null,"In the file ",(0,i.yg)("inlineCode",{parentName:"p"},"post.go"),", let's define the ",(0,i.yg)("inlineCode",{parentName:"p"},"GetPostCount")," function as follows:"),(0,i.yg)("pre",null,(0,i.yg)("code",{parentName:"pre",className:"language-go",metastring:'title="x/blog/keeper/post.go"',title:'"x/blog/keeper/post.go"'},"func (k Keeper) GetPostCount(ctx sdk.Context) uint64 {\n store := prefix.NewStore(ctx.KVStore(k.storeKey), []byte{})\n byteKey := types.KeyPrefix(types.PostCountKey)\n bz := store.Get(byteKey)\n if bz == nil {\n return 0\n }\n return binary.BigEndian.Uint64(bz)\n}\n")),(0,i.yg)("p",null,"This code defines a function named ",(0,i.yg)("inlineCode",{parentName:"p"},"GetPostCount")," that belongs to the ",(0,i.yg)("inlineCode",{parentName:"p"},"Keeper"),"\nstruct. The function takes in a single argument, a context object ",(0,i.yg)("inlineCode",{parentName:"p"},"ctx")," of type\n",(0,i.yg)("inlineCode",{parentName:"p"},"sdk.Context"),", and returns a value of type ",(0,i.yg)("inlineCode",{parentName:"p"},"uint64"),"."),(0,i.yg)("p",null,"The function begins by creating a new store using the key-value store in the\ncontext and an empty byte slice as the prefix. It then defines a byte slice\n",(0,i.yg)("inlineCode",{parentName:"p"},"byteKey")," using the ",(0,i.yg)("inlineCode",{parentName:"p"},"KeyPrefix")," function from the ",(0,i.yg)("inlineCode",{parentName:"p"},"types")," package, which takes\nin the ",(0,i.yg)("inlineCode",{parentName:"p"},"PostCountKey"),". You will define ",(0,i.yg)("inlineCode",{parentName:"p"},"PostCountKey")," in the next step."),(0,i.yg)("p",null,"The function then retrieves the value at the key ",(0,i.yg)("inlineCode",{parentName:"p"},"byteKey")," in the store using\nthe ",(0,i.yg)("inlineCode",{parentName:"p"},"Get")," method and stores it in a variable ",(0,i.yg)("inlineCode",{parentName:"p"},"bz"),"."),(0,i.yg)("p",null,"Next, the function checks if the value at ",(0,i.yg)("inlineCode",{parentName:"p"},"byteKey")," is ",(0,i.yg)("inlineCode",{parentName:"p"},"nil")," using an if\nstatement. If it is ",(0,i.yg)("inlineCode",{parentName:"p"},"nil"),", meaning that the key does not exist in the store, the\nfunction returns 0. This indicates that there are no elements or posts\nassociated with the key."),(0,i.yg)("p",null,"If the value at ",(0,i.yg)("inlineCode",{parentName:"p"},"byteKey")," is not nil, the function uses the ",(0,i.yg)("inlineCode",{parentName:"p"},"binary")," package's\n",(0,i.yg)("inlineCode",{parentName:"p"},"BigEndian")," type to parse the bytes in ",(0,i.yg)("inlineCode",{parentName:"p"},"bz")," and returns the resulting ",(0,i.yg)("inlineCode",{parentName:"p"},"uint64"),"\nvalue. The ",(0,i.yg)("inlineCode",{parentName:"p"},"BigEndian")," type is used to interpret the bytes in ",(0,i.yg)("inlineCode",{parentName:"p"},"bz")," as a\nbig-endian encoded unsigned 64-bit integer. The ",(0,i.yg)("inlineCode",{parentName:"p"},"Uint64")," method converts the\nbytes to a ",(0,i.yg)("inlineCode",{parentName:"p"},"uint64")," value and returns it."),(0,i.yg)("p",null,(0,i.yg)("inlineCode",{parentName:"p"},"GetPostCount")," function is used to retrieve the total number of posts stored in\nthe key-value store, represented as a ",(0,i.yg)("inlineCode",{parentName:"p"},"uint64")," value."),(0,i.yg)("p",null,"In the file ",(0,i.yg)("inlineCode",{parentName:"p"},"keys.go"),", let's define the ",(0,i.yg)("inlineCode",{parentName:"p"},"PostCountKey")," as follows:"),(0,i.yg)("pre",null,(0,i.yg)("code",{parentName:"pre",className:"language-go",metastring:'title="x/blog/types/keys.go"',title:'"x/blog/types/keys.go"'},'const (\n PostCountKey = "Post/count/"\n)\n')),(0,i.yg)("p",null,"This key will be used to keep track of the ID of the latest post added to the\nstore."),(0,i.yg)("h3",{id:"converting-post-id-to-bytes"}
1,"Converting post ID to bytes"),(0,i.yg)("p",null,"Now, let's implement ",(0,i.yg)("inlineCode",{parentName:"p"},"GetPostIDBytes"),", which will convert a post ID to a byte\narray."),(0,i.yg)("pre",null,(0,i.yg)("code",{parentName:"pre",className:"language-go",metastring:'title="x/blog/keeper/post.go"',title:'"x/blog/keeper/post.go"'},"func GetPostIDBytes(id uint64) []byte {\n bz := make([]byte, 8)\n binary.BigEndian.PutUint64(bz, id)\n return bz\n}\n")),(0,i.yg)("p",null,(0,i.yg)("inlineCode",{parentName:"p"},"GetPostIDBytes")," takes in a value ",(0,i.yg)("inlineCode",{parentName:"p"},"id")," of type ",(0,i.yg)("inlineCode",{parentName:"p"},"uint64")," and returns a value of\ntype ",(0,i.yg)("inlineCode",{parentName:"p"},"[]byte"),"."),(0,i.yg)("p",null,"The function starts by creating a new byte slice ",(0,i.yg)("inlineCode",{parentName:"p"},"bz")," with a length of 8 using\nthe ",(0,i.yg)("inlineCode",{parentName:"p"},"make")," built-in function. It then uses the ",(0,i.yg)("inlineCode",{parentName:"p"},"binary")," package's ",(0,i.yg)("inlineCode",{parentName:"p"},"BigEndian"),"\ntype to encode the value of ",(0,i.yg)("inlineCode",{parentName:"p"},"id")," as a big-endian encoded unsigned integer and\nstore the result in ",(0,i.yg)("inlineCode",{parentName:"p"},"bz")," using the ",(0,i.yg)("inlineCode",{parentName:"p"},"PutUint64")," method. Finally, the function\nreturns the resulting byte slice ",(0,i.yg)("inlineCode",{parentName:"p"},"bz"),"."),(0,i.yg)("p",null,"This function can be used to convert a post ID, represented as a ",(0,i.yg)("inlineCode",{parentName:"p"},"uint64"),", to a\nbyte slice that can be used as a key in a key-value store. The\n",(0,i.yg)("inlineCode",{parentName:"p"},"binary.BigEndian.PutUint64")," function encodes the ",(0,i.yg)("inlineCode",{parentName:"p"},"uint64")," value of ",(0,i.yg)("inlineCode",{parentName:"p"},"id")," as a\nbig-endian encoded unsigned integer and stores the resulting bytes in the\n",(0,i.yg)("inlineCode",{parentName:"p"},"[]byte")," slice ",(0,i.yg)("inlineCode",{parentName:"p"},"bz"),". The resulting byte slice can then be used as a key in the\nstore."),(0,i.yg)("h3",{id:"updating-the-post-count"},"Updating the post count"),(0,i.yg)("p",null,"Implement ",(0,i.yg)("inlineCode",{parentName:"p"},"SetPostCount")," in ",(0,i.yg)("inlineCode",{parentName:"p"},"post.go"),", which will update the post count stored\nin the database."),(0,i.yg)("pre",null,(0,i.yg)("code",{parentName:"pre",className:"language-go",metastring:'title="x/blog/keeper/post.go"',title:'"x/blog/keeper/post.go"'},"func (k Keeper) SetPostCount(ctx sdk.Context, count uint64) {\n store := prefix.NewStore(ctx.KVStore(k.storeKey), []byte{})\n byteKey := types.KeyPrefix(types.PostCountKey)\n bz := make([]byte, 8)\n binary.BigEndian.PutUint64(bz, count)\n store.Set(byteKey, bz)\n}\n")),(0,i.yg)("p",null,"This code defines a function ",(0,i.yg)("inlineCode",{parentName:"p"},"SetPostCount")," in the ",(0,i.yg)("inlineCode",{parentName:"p"},"Keeper")," struct. The function\ntakes in a context ",(0,i.yg)("inlineCode",{parentName:"p"},"ctx")," of type ",(0,i.yg)("inlineCode",{parentName:"p"},"sdk.Context")," and a value ",(0,i.yg)("inlineCode",{parentName:"p"},"count")," of type\n",(0,i.yg)("inlineCode",{parentName:"p"},"uint64"),", and does not return a value."),(0,i.yg)("p",null,"The function first creates a new store by calling the ",(0,i.yg)("inlineCode",{parentName:"p"},"NewStore")," function from\nthe prefix package and passing in the key-value store from the context and an\nempty byte slice as the prefix. It stores the resulting store in a variable\nnamed ",(0,i.yg)("inlineCode",{parentName:"p"},"store"),"."),(0,i.yg)("p",null,"Next, the function defines a byte slice ",(0,i.yg)("inlineCode",{parentName:"p"},"byteKey")," using the ",(0,i.yg)("inlineCode",{parentName:"p"},"KeyPrefix")," function\nfrom the ",(0,i.yg)("inlineCode",{parentName:"p"},"types")," package and passing in the ",(0,i.yg)("inlineCode",{parentName:"p"},"PostCountKey"),". The ",(0,i.yg)("inlineCode",{parentName:"p"},"KeyPrefix"),"\nfunction returns a byte slice with the given key as a prefix."),(0,i.yg)("p",null,"The function then creates a new byte slice ",(0,i.yg)("inlineCode",{parentName:"p"},"bz")," with a length of 8 using the\n",(0,i.yg)("inlineCode",{parentName:"p"},"make")," built-in function. It then uses the ",(0,i.yg)("inlineCode",{parentName:"p"},"binary")," package's ",(0,i.yg)("inlineCode",{parentName:"p"},"BigEndian")," type\nto encode the value of count as a big-endian encoded unsigned integer and store\
1nthe result in ",(0,i.yg)("inlineCode",{parentName:"p"},"bz")," using the ",(0,i.yg)("inlineCode",{parentName:"p"},"PutUint64")," method."),(0,i.yg)("p",null,"Finally, the function calls the ",(0,i.yg)("inlineCode",{parentName:"p"},"Set")," method on the ",(0,i.yg)("inlineCode",{parentName:"p"},"store")," variable, passing in\n",(0,i.yg)("inlineCode",{parentName:"p"},"byteKey")," and ",(0,i.yg)("inlineCode",{parentName:"p"},"bz")," as arguments. This sets the value at the key ",(0,i.yg)("inlineCode",{parentName:"p"},"byteKey")," in the\nstore to the value ",(0,i.yg)("inlineCode",{parentName:"p"},"bz"),"."),(0,i.yg)("p",null,"This function can be used to update the count of posts stored in the database.\nIt does this by converting the ",(0,i.yg)("inlineCode",{parentName:"p"},"uint64")," value of count to a byte slice using the\n",(0,i.yg)("inlineCode",{parentName:"p"},"binary.BigEndian.PutUint64")," function, and then storing the resulting byte slice\nat the key ",(0,i.yg)("inlineCode",{parentName:"p"},"byteKey")," in the store using the ",(0,i.yg)("inlineCode",{parentName:"p"},"Set")," method."),(0,i.yg)("p",null,'Now that you have implemented the code for creating blog posts, you can proceed\nto implement the keeper method that is invoked when the "create post" message is\nprocessed.'),(0,i.yg)("h2",{id:"handling-the-create-post-message"},'Handling the "create post" message'),(0,i.yg)("pre",null,(0,i.yg)("code",{parentName:"pre",className:"language-go",metastring:'title="x/blog/keeper/msg_server_create_post.go"',title:'"x/blog/keeper/msg_server_create_post.go"'},'package keeper\n\nimport (\n "context"\n\n "blog/x/blog/types"\n\n sdk "github.com/cosmos/cosmos-sdk/types"\n)\n\nfunc (k msgServer) CreatePost(goCtx context.Context, msg *types.MsgCreatePost) (*types.MsgCreatePostResponse, error) {\n ctx := sdk.UnwrapSDKContext(goCtx)\n var post = types.Post{\n Creator: msg.Creator,\n Title: msg.Title,\n Body: msg.Body,\n }\n id := k.AppendPost(\n ctx,\n post,\n )\n return &types.MsgCreatePostResponse{\n Id: id,\n }, nil\n}\n')),(0,i.yg)("p",null,"The ",(0,i.yg)("inlineCode",{parentName:"p"},"CreatePost")," function is a message handler for the ",(0,i.yg)("inlineCode",{parentName:"p"},"MsgCreatePost")," message\ntype. It is responsible for creating a new post on the blockchain based on the\ninformation provided in the ",(0,i.yg)("inlineCode",{parentName:"p"},"MsgCreatePost")," message."),(0,i.yg)("p",null,"The function first retrieves the Cosmos SDK context from the Go context using\nthe ",(0,i.yg)("inlineCode",{parentName:"p"},"sdk.UnwrapSDKContext")," function. It then creates a new ",(0,i.yg)("inlineCode",{parentName:"p"},"Post")," object using\nthe ",(0,i.yg)("inlineCode",{parentName:"p"},"Creator"),", ",(0,i.yg)("inlineCode",{parentName:"p"},"Title"),", and ",(0,i.yg)("inlineCode",{parentName:"p"},"Body")," fields from the MsgCreatePost message."),(0,i.yg)("p",null,"Next, the function calls the ",(0,i.yg)("inlineCode",{parentName:"p"},"AppendPost")," method on the ",(0,i.yg)("inlineCode",{parentName:"p"},"msgServer")," object\n(which is of the Keeper type) and passes in the Cosmos SDK context and the new\n",(0,i.yg)("inlineCode",{parentName:"p"},"Post")," object as arguments. The ",(0,i.yg)("inlineCode",{parentName:"p"},"AppendPost")," method is responsible for adding\nthe new post to the blockchain and returning the ID of the new post."),(0,i.yg)("p",null,"Finally, the function returns a ",(0,i.yg)("inlineCode",{parentName:"p"},"MsgCreatePostResponse")," object that contains the\nID of the new post. It also returns a nil error, indicating that the operation\nwas successful."),(0,i.yg)("h2",{id:"summary"},"Summary"),(0,i.yg)("p",null,'Great job! You have successfully implemented the logic for writing blog posts to\nthe blockchain store and the keeper method that will be called when a "create\npost" message is processed.'),(0,i.yg)("p",null,"The ",(0,i.yg)("inlineCode",{parentName:"p"},"AppendPost")," keeper method retrieves the current post count, sets the ID of\nthe new post to be the current post count, serializes the post object, and\nstores it in the blockchain using the ",(0,i.yg)("inlineCode",{parentName:"p"},"Set")," method of the ",(0,i.yg)("inlineCode",{parentName:"p"},"store")," object. The\nkey for the post in the store is a byte slice generated by the ",(0,i.yg)("inlineCode",{parentName:"p"},"GetPostIDBytes"),"\nfunction and the value is the serialized post object. The function then\nincrements the post count by one and updates the blockchain state using the\n",(0,i.yg)("inlineCode",{parentName:"p"}
1,"SetPostCount")," method."),(0,i.yg)("p",null,"The ",(0,i.yg)("inlineCode",{parentName:"p"},"CreatePost")," handler method receives a ",(0,i.yg)("inlineCode",{parentName:"p"},"MsgCreatePost")," message containing\nthe data for the new post, creates a new ",(0,i.yg)("inlineCode",{parentName:"p"},"Post")," object using this data, and\npasses it to the ",(0,i.yg)("inlineCode",{parentName:"p"},"AppendPost")," keeper method to be added to the blockchain. It\nthen returns a ",(0,i.yg)("inlineCode",{parentName:"p"},"MsgCreatePostResponse")," object containing the ID of the newly\ncreated post."),(0,i.yg)("p",null,'By implementing these methods, you have successfully implemented the necessary\nlogic for handling "create post" messages and adding posts to the blockchain.'))}g.isMDXComponent=!0}}]);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.