1"use strict";(globalThis.webpackChunkmy_website=globalThis.webpackChunkmy_website||[]).push([[1975],{15680(e,n,t){t.d(n,{xA:()=>g,yg:()=>u});var o=t(96540);function a(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function i(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);n&&(o=o.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,o)}return t}function l(e){for(var n=1;n<arguments.length;n++){var t=null!=arguments[n]?arguments[n]:{};n%2?i(Object(t),!0).forEach((function(n){a(e,n,t[n])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(t)):i(Object(t)).forEach((function(n){Object.defineProperty(e,n,Object.getOwnPropertyDescriptor(t,n))}))}return e}function r(e,n){if(null==e)return{};var t,o,a=function(e,n){if(null==e)return{};var t,o,a={},i=Object.keys(e);for(o=0;o<i.length;o++)t=i[o],n.indexOf(t)>=0||(a[t]=e[t]);return a}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(o=0;o<i.length;o++)t=i[o],n.indexOf(t)>=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(a[t]=e[t])}return a}var c=o.createContext({}),s=function(e){var n=o.useContext(c),t=n;return e&&(t="function"==typeof e?e(n):l(l({},n),e)),t},g=function(e){var n=s(e.components);return o.createElement(c.Provider,{value:n},e.children)},p={inlineCode:"code",wrapper:function(e){var n=e.children;return o.createElement(o.Fragment,{},n)}},d=o.forwardRef((function(e,n){var t=e.components,a=e.mdxType,i=e.originalType,c=e.parentName,g=r(e,["components","mdxType","originalType","parentName"]),d=s(t),u=a,h=d["".concat(c,".").concat(u)]||d[u]||p[u]||i;return t?o.createElement(h,l(l({ref:n},g),{},{components:t})):o.createElement(h,l({ref:n},g))}));function u(e,n){var t=arguments,a=n&&n.mdxType;if("string"==typeof e||a){var i=t.length,l=new Array(i);l[0]=d;var r={};for(var c in n)hasOwnProperty.call(n,c)&&(r[c]=n[c]);r.originalType=e,r.mdxType="string"==typeof e?e:a,l[1]=r;for(var s=2;s<i;s++)l[s]=t[s];return o.createElement.apply(null,l)}return o.createElement.apply(null,t)}d.displayName="MDXCreateElement"},27567(e,n,t){t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>l,default:()=>p,frontMatter:()=>i,metadata:()=>r,toc:()=>s});var o=t(58168),a=(t(96540),t(15680));const i={description:"Blockchain client in Go",title:"Go client"},l="A client in the Go programming language",r={unversionedId:"clients/go-client",id:"version-v0.26/clients/go-client",title:"Go client",description:"Blockchain client in Go",source:"@site/versioned_docs/version-v0.26/03-clients/01-go-client.md",sourceDirName:"03-clients",slug:"/clients/go-client",permalink:"/v0.26/clients/go-client",draft:!1,tags:[],version:"v0.26",sidebarPosition:1,frontMatter:{description:"Blockchain client in Go",title:"Go client"},sidebar:"tutorialSidebar",previous:{title:"Chain simulation",permalink:"/v0.26/guide/simapp"},next:{title:"TypeScript frontend",permalink:"/v0.26/clients/typescript"}},c={},s=[{value:"Create a blockchain",id:"create-a-blockchain",level:2},{value:"Creating a blockchain client",id:"creating-a-blockchain-client",level:2},{value:"Main logic of the client in <code>main.go</code>",id:"main-logic-of-the-client-in-maingo",level:3},{value:"Run the blockchain and the client",id:"run-the-blockchain-and-the-client",level:2}],g={toc:s};function p(e){let{components:n,...t}=e;return(0,a.yg)("wrapper",(0,o.A)({},g,t,{components:n,mdxType:"MDXLayout"}),(0,a.yg)("h1",{id:"a-client-in-the-go-programming-language"},"A client in the Go programming language"),(0,a.yg)("p",null,"In this tutorial, we will show you how to create a standalone Go program that\nserves as a client for a blockchain. We will use the Ignite CLI to set up a\nstandard blockchain. To communicate with the blockchain, we will utilize the\n",(0,a.yg)("inlineCode",{parentName:"p"},"cosmosclient")," package, which provides an easy-to-use interface for interacting\nwith the blockchain. You will learn how to use the ",(0,a.yg)("inlineCode",{parentName:"p"},"cosmosclient")," package to\nsend transactions and query the blockchain. By the end of this tutorial, you\nwill have a good understanding of how to build a client for a blockchain using\nGo and the ",(0,a.yg)("inlineCode",{parentName:"p"},"cosmosclient")," package."),(0,a.yg)("h2",{id:"create-a-blockchain"},"Create a blockchain"),(0,a.yg)("p",null,"To create a blockchain using the Ignite CLI, use the following command:"),(0,a.yg)("pre",null,(0,a.yg)("code",{parentName:"pre"},"ignite scaffold chain blog\n")),(0,a.yg)("p",null,'This will create a new Cosmos SDK blockchain called "blog".'),(0,a.yg)("p",null,'Once the blockchain has been created, you can generate code for a "blog" model\nthat will enable you to perform create, read, update, and delete (CRUD)\noperations on blog posts. To do this, you can use the following command:'),(0,a.yg)("pre",null,(0,a.yg)("code",{parentName:"pre"},"cd blog\nignite scaffold list post title body\n")),(0,a.yg)("p",null,'This will generate the necessary code for the "blog" model, including functions\nfor creating, reading, updating, and deleting blog posts. With this code in\nplace, you can now use your blockchain to perform CRUD operations on blog posts.\nYou can use the generated code to create new blog posts, retrieve existing ones,\nupdate their content, and delete them as needed. This will give you a fully\nfunctional Cosmos SDK blockchain with the ability to manage blog posts.'),(0,a.yg)("p",null,"Start your blockchain node with the following command:"),(0,a.yg)("pre",null,(0,a.yg)("code",{parentName:"pre"},"ignite chain serve\n")),(0,a.yg)("h2",{id:"creating-a-blockchain-client"},"Creating a blockchain client"),(0,a.yg)("p",null,"Create a new directory called ",(0,a.yg)("inlineCode",{parentName:"p"},"blogclient")," on the same level as ",(0,a.yg)("inlineCode",{parentName:"p"},"blog"),"\ndirectory. As the name suggests, ",(0,a.yg)("inlineCode",{parentName:"p"}
1,"blogclient")," will contain a standalone Go\nprogram that acts as a client to your ",(0,a.yg)("inlineCode",{parentName:"p"},"blog")," blockchain."),(0,a.yg)("pre",null,(0,a.yg)("code",{parentName:"pre",className:"language-bash"},"mkdir blogclient\n")),(0,a.yg)("p",null,"This command will create a new directory called ",(0,a.yg)("inlineCode",{parentName:"p"},"blogclient")," in your current\nlocation. If you type ",(0,a.yg)("inlineCode",{parentName:"p"},"ls")," in your terminal window, you should see both the\n",(0,a.yg)("inlineCode",{parentName:"p"},"blog")," and ",(0,a.yg)("inlineCode",{parentName:"p"},"blogclient")," directories listed."),(0,a.yg)("p",null,"To initialize a new Go package inside the ",(0,a.yg)("inlineCode",{parentName:"p"},"blogclient")," directory, you can use\nthe following command:"),(0,a.yg)("pre",null,(0,a.yg)("code",{parentName:"pre"},"cd blogclient\ngo mod init blogclient\n")),(0,a.yg)("p",null,"This will create a ",(0,a.yg)("inlineCode",{parentName:"p"},"go.mod")," file in the ",(0,a.yg)("inlineCode",{parentName:"p"},"blogclient")," directory, which contains\ninformation about the package and the Go version being used."),(0,a.yg)("p",null,"To import dependencies for your package, you can add the following code to the\n",(0,a.yg)("inlineCode",{parentName:"p"},"go.mod")," file:"),(0,a.yg)("pre",null,(0,a.yg)("code",{parentName:"pre",className:"language-text",metastring:'title="blogclient/go.mod"',title:'"blogclient/go.mod"'},"module blogclient\n\ngo 1.19\n\nrequire (\n blog v0.0.0-00010101000000-000000000000\n github.com/ignite/cli v0.25.2\n)\n\nreplace blog => ../blog\nreplace github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1\n")),(0,a.yg)("p",null,"Your package will import two dependencies:"),(0,a.yg)("ul",null,(0,a.yg)("li",{parentName:"ul"},(0,a.yg)("inlineCode",{parentName:"li"},"blog"),", which contains ",(0,a.yg)("inlineCode",{parentName:"li"},"types")," of messages and a query client"),(0,a.yg)("li",{parentName:"ul"},(0,a.yg)("inlineCode",{parentName:"li"},"ignite")," for the ",(0,a.yg)("inlineCode",{parentName:"li"},"cosmosclient")," package")),(0,a.yg)("p",null,"The ",(0,a.yg)("inlineCode",{parentName:"p"},"replace")," directive uses the package from the local ",(0,a.yg)("inlineCode",{parentName:"p"},"blog")," directory and is\nspecified as a relative path to the ",(0,a.yg)("inlineCode",{parentName:"p"},"blogclient")," directory."),(0,a.yg)("p",null,"Cosmos SDK uses a custom version of the ",(0,a.yg)("inlineCode",{parentName:"p"},"protobuf")," package, so use the ",(0,a.yg)("inlineCode",{parentName:"p"},"replace"),"\ndirective to specify the correct dependency."),(0,a.yg)("p",null,"Finally, install dependencies for your ",(0,a.yg)("inlineCode",{parentName:"p"},"blogclient"),":"),(0,a.yg)("pre",null,(0,a.yg)("code",{parentName:"pre",className:"language-bash"},"go mod tidy\n")),(0,a.yg)("h3",{id:"main-logic-of-the-client-in-maingo"},"Main logic of the client in ",(0,a.yg)("inlineCode",{parentName:"h3"},"main.go")),(0,a.yg)("p",null,"Create a ",(0,a.yg)("inlineCode",{parentName:"p"},"main.go")," file inside the ",(0,a.yg)("inlineCode",{parentName:"p"},"blogclient")," directory and add the following\ncode:"),(0,a.yg)("pre",null,(0,a.yg)("code",{parentName:"pre",className:"language-go",metastring:'title="blogclient/main.go"',title:'"blogclient/main.go"'},'package main\n\nimport (\n "context"\n "fmt"\n "log"\n\n // Importing the general purpose Cosmos blockchain client\n "github.com/ignite/cli/ignite/pkg/cosmosclient"\n\n // Importing the types package of your blog blockchain\n "blog/x/blog/types"\n)\n\nfunc main() {\n ctx := context.Background()\n addressPrefix := "cosmos"\n\n // Create a Cosmos client instance\n client, err := cosmosclient.New(ctx, cosmosclient.WithAddressPrefix(addressPrefix))\n if err != nil {\n log.Fatal(err)\n }\n\n // Account `alice` was initialized during `ignite chain serve`\n accountName := "alice"\n\n // Get account from the keyring\n account, err := client.Account(accountName)\n if err != nil {\n log.Fatal(err)\n }\n\n addr, err := account.Address(addressPrefix)\n if err != nil {\n log.Fatal(err)\n }\n\n // Define a message to create a post\n msg := &types.MsgCreatePost{\n Creator: addr,\n Title: "Hello!",\n Body: "This is the first post",\n }\n\n // Broadcast a transaction from account `alice` with the message\n // to create a post store response in txResp\n txResp, err := client.BroadcastTx(ctx, account, msg)\n if err != nil {\n log.Fatal(err)\n }\n\n // Print response from broadcasting a transaction\n fmt.Print("MsgCreatePost:\\n\\n")\n fmt.Println(txResp)\n\n // Instantiate a query client for your `blog` blockchain\n queryClient := types.NewQueryClient(client.Context())\n\n // Query the blockchain using the client\'s `PostAll` method\n // to get all posts store all posts in queryResp\n queryResp, err := queryClient.PostAll(ctx, &types.QueryAllPostRequest{})\n if err != nil {\n log.Fatal(err)\n }\n\n // Print response from querying all the posts\n fmt.Print("\\n\\nAll posts:\\n\\n")\n fmt.Println(queryResp)\n}\n')),(0,a.yg)("p",null,"The code above creates a standalone Go program that acts as a client to the\n",(0,a.yg)("inlineCode",{parentName:"p"},"blog")," blockchain. It begins by importing the required packages, including the\ngeneral purpose Cosmos blockchain client and the ",(0,a.yg)("inlineCode",{parentName:"p"},"types")," package of the ",(0,a.yg)("inlineCode",{parentName:"p"},"blog"),"\nblockchain."),(0,a.yg)("p",null,"In the ",(0,a.yg)("inlineCode",{parentName:"p"},"main"),' function, the code creates a Cosmos client instance and sets the\naddress prefix to "cosmos". It then retrieves an account named ',(0,a.yg)("inlineCode",{parentName:"p"},'"alice"')," from\nthe keyring and gets the address of the account using the address prefix."),(0,a.yg)("p",null,'Next, the code defines a message to create a blog post with the title "Hello!"\nand body "This is the first post". It then broadcasts a transaction from the\naccount "alice" with the message to create the post, and stores the response in\nthe variable ',(0,a.yg)("inlineCode",{parentName:"p"},"txResp"),"."),(0,a.yg)("p",null,"The code then instantiates a query client for the blog blockchain and uses it to\nquery the blockchain to retrieve all the posts. It stores the response in the\nvariable ",(0,a.yg)("inlineCode",{parentName:"p"},"queryResp")," and prints it to the console."),(0,a.yg)("p",null,"Finally, the code prints the response from broadcasting the transaction to the\nconsole. This allows the user to see the results of creating and querying a blog\npost on the ",(0,a.yg)("inlineCode",{parentName:"p"},"blog")," blockchain using the client."),(0,a.yg)("p",null,"To find out more about the ",(0,a.yg)("inlineCode",{parentName:"p"},"cosmosclient")," package, you can refer to the Go\npackage documentation for\n",(0,a.yg)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/ignite/cli/ignite/pkg/cosmosclient"},(0,a.yg)("inlineCode",{parentName:"a"},"cosmosclient")),".\nThis documentation provides information on how to use the ",(0,a.yg)("inlineCode",{parentName:"p"},"Client")," type with\n",(0,a.yg)("inlineCode",{parentName:"p"},"Options")," and ",(0,a.yg)("inlineCode",{parentName:"p"},"KeyringBackend"),"."),(0,a.yg)("h2",{id:"run-the-blockchain-and-the-client"},"Run the blockchain and the client"),(0,a.yg)("p",null,"Make sure your blog blockchain is still running with ",(0,a.yg)("inlineCode",{parentName:"p"},"ignite chain serve"),"."),(0,a.yg)("p",null,"Run the blockchain client:"),(0,a.yg)("pre",null,(0,a.yg)("code",{parentName:"pre",className:"language-bash"},"go run main.go\n")),(0,a.yg)("p",null,"If the command is successful, the results of running the command will be printed\nto the terminal. The output may include some warnings, which can be ignored."),(0,a.yg)("pre",null,(0,a.yg)("code",{parentName:"pre",className:"language-yml"},'MsgCreatePost:\n\ncode: 0\ncodespace: ""\ndata: 12220A202F626C6F672E626C6F672E4D7367437265617465506F7374526573706F6E7365\nevents:\n- attributes:\n - index: true\n key: ZmVl\n value: null\n - index: true\n key: ZmVlX3BheWVy\n value: Y29zbW9zMWR6ZW13NzZ3enQ3cDBnajd3MzQyN2E0eHg3MjRkejAzd3hnOGhk\n type: tx\n- attributes:\n - index: true\n key: YWNjX3NlcQ==\n value: Y29zbW9zMWR6ZW13NzZ3enQ3cDBnajd3MzQyN2E0eHg3MjRkejAzd3hnOGhkLzE=\n type: tx\n- attributes:\n - index: true\n key: c2lnbmF0dXJl\n value: UWZncUJCUFQvaWxWVzJwNUJNTngzcDlvRzVpSXp0elhXdE9yMHcwVE00OEtlSkRqR0FEdU9VNjJiY1ZRNVkxTHdEbXNuYUlsTmc3VE9uMnJ2ZWRHSlE9PQ==\n type: tx\n- attributes:\n - index: true\n key: YWN0aW9u\n value: L2Jsb2cuYmxvZy5Nc2dDcmVhdGVQb3N0\n type: message\ngas_used: "52085"\ngas_wanted: "300000"\nheight: "20"\ninfo: ""\nlogs:\n- events:\n - attributes:\n - key: action\n value: /blog.blog.MsgCreatePost\n type: message\n log: ""\n msg_index: 0\nraw_log: \'[{"msg_index":0,"events":[{"type":"message","attributes":[{"key":"action","value":"/blog.blog.MsgCreatePost"}]}]}]\'\ntimestamp: ""\ntx: null\ntxhash: 4F53B75C18254F96EF159821DDD665E965DBB576A5AC2B94CE863EB62E33156A\n\nAll posts:\n\nPost:<title:"Hello!" body:"This is the first post" creator:"cosmos1dzemw76wzt7p0gj7w3427a4xx724dz03wxg8hd" > pagination:<total:1 >\n')),(0,a.yg)("p",null,"As you can see the client has successfully broadcasted a transaction and queried\nthe chain for blog posts."),(0,a.yg)("p",null,"Please note, that some values in the output on your terminal (like transaction\nhash and block height) might be different from the output above."),(0,a.yg)("p",null,"You can confirm the new post with using the ",(0,a.yg)("inlineCode",{parentName:"p"},"blogd q blog list-post")," command:"),(0,a.yg)("pre",null,(0,a.yg)("code",{parentName:"pre",className:"language-yaml"},'Post:\n- body: This is the first post\n creator: cosmos1dzemw76wzt7p0gj7w3427a4xx724dz03wxg8hd\n id: "0"\n title: Hello!\npagination:\n next_key: null\n total: "0"\n')),(0,a.yg)("p",null,"Great job! You have successfully completed the process of creating a Go client\nfor your Cosmos SDK blockchain, submitting a transaction, and querying the\nchain."))}p.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.