Ở bài trước chúng ta đã code xong phần xử lý logic bên dưới, nhưng hiện tại user vẫn phải tương tác với hệ thống bằng command-line rất thủ công. Ở bài này chúng ta sẽ xây dựng phần rest-server để người dùng tương tác dễ hơn.
1. Các hàm xử lý request được gửi lên từ user bằng phương thức post
Các bạn mở file x/nameservice/client/rest/tx.go
lên và thêm các dòng sau vào:
1.1 Create Product
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | <span class="token keyword">type</span> createProductReq <span class="token keyword">struct</span> <span class="token punctuation">{</span> <span class="token comment">// cấu trúc của một request create product</span> BaseReq rest<span class="token punctuation">.</span>BaseReq <span class="token string">`json:"base_req"`</span> ProductID <span class="token builtin">string</span> <span class="token string">`json:"productID"`</span> Description <span class="token builtin">string</span> <span class="token string">`json:"description"`</span> Price <span class="token builtin">string</span> <span class="token string">`json:"price"`</span> <span class="token punctuation">}</span> <span class="token keyword">func</span> <span class="token function">createProductHandler</span><span class="token punctuation">(</span>cliCtx context<span class="token punctuation">.</span>CLIContext<span class="token punctuation">)</span> http<span class="token punctuation">.</span>HandlerFunc <span class="token punctuation">{</span> <span class="token comment">// hàm xử lý request createProductReq</span> <span class="token keyword">return</span> <span class="token keyword">func</span><span class="token punctuation">(</span>w http<span class="token punctuation">.</span>ResponseWriter<span class="token punctuation">,</span> r <span class="token operator">*</span>http<span class="token punctuation">.</span>Request<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">var</span> req createProductReq <span class="token keyword">if</span> <span class="token operator">!</span>rest<span class="token punctuation">.</span><span class="token function">ReadRESTReq</span><span class="token punctuation">(</span>w<span class="token punctuation">,</span> r<span class="token punctuation">,</span> cliCtx<span class="token punctuation">.</span>Codec<span class="token punctuation">,</span> <span class="token operator">&</span>req<span class="token punctuation">)</span> <span class="token punctuation">{</span> rest<span class="token punctuation">.</span><span class="token function">WriteErrorResponse</span><span class="token punctuation">(</span>w<span class="token punctuation">,</span> http<span class="token punctuation">.</span>StatusBadRequest<span class="token punctuation">,</span> <span class="token string">"failed to parse request"</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token punctuation">}</span> baseReq <span class="token operator">:=</span> req<span class="token punctuation">.</span>BaseReq<span class="token punctuation">.</span><span class="token function">Sanitize</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">if</span> <span class="token operator">!</span>baseReq<span class="token punctuation">.</span><span class="token function">ValidateBasic</span><span class="token punctuation">(</span>w<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token punctuation">}</span> signer<span class="token punctuation">,</span> err <span class="token operator">:=</span> sdk<span class="token punctuation">.</span><span class="token function">AccAddressFromBech32</span><span class="token punctuation">(</span>req<span class="token punctuation">.</span>BaseReq<span class="token punctuation">.</span>From<span class="token punctuation">)</span> <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> rest<span class="token punctuation">.</span><span class="token function">WriteErrorResponse</span><span class="token punctuation">(</span>w<span class="token punctuation">,</span> http<span class="token punctuation">.</span>StatusBadRequest<span class="token punctuation">,</span> err<span class="token punctuation">.</span><span class="token function">Error</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token punctuation">}</span> price<span class="token punctuation">,</span> err <span class="token operator">:=</span> sdk<span class="token punctuation">.</span><span class="token function">ParseCoins</span><span class="token punctuation">(</span>req<span class="token punctuation">.</span>Price<span class="token punctuation">)</span> <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> rest<span class="token punctuation">.</span><span class="token function">WriteErrorResponse</span><span class="token punctuation">(</span>w<span class="token punctuation">,</span> http<span class="token punctuation">.</span>StatusBadRequest<span class="token punctuation">,</span> err<span class="token punctuation">.</span><span class="token function">Error</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token punctuation">}</span> msg <span class="token operator">:=</span> types<span class="token punctuation">.</span><span class="token function">NewMsgCreateProduct</span><span class="token punctuation">(</span>req<span class="token punctuation">.</span>ProductID<span class="token punctuation">,</span> req<span class="token punctuation">.</span>Description<span class="token punctuation">,</span> price<span class="token punctuation">,</span> signer<span class="token punctuation">)</span> err <span class="token operator">=</span> msg<span class="token punctuation">.</span><span class="token function">ValidateBasic</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> rest<span class="token punctuation">.</span><span class="token function">WriteErrorResponse</span><span class="token punctuation">(</span>w<span class="token punctuation">,</span> http<span class="token punctuation">.</span>StatusBadRequest<span class="token punctuation">,</span> err<span class="token punctuation">.</span><span class="token function">Error</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token punctuation">}</span> <span class="token comment">// broadcast message để handler có thể bắt được </span> utils<span class="token punctuation">.</span><span class="token function">WriteGenerateStdTxResponse</span><span class="token punctuation">(</span>w<span class="token punctuation">,</span> cliCtx<span class="token punctuation">,</span> baseReq<span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token punctuation">]</span>sdk<span class="token punctuation">.</span>Msg<span class="token punctuation">{</span>msg<span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
Một số chỗ cần lưu ý:
- kiểu base request được định nghĩa bởi cosmos sdk
- giá của product là string ví dụ “10nametoken” sau đó sẽ được dùng hàm
sdk.ParseCoins()
để convert về dạng sdk.Coins - req.Base.From sẽ lấy ra địa chỉ của người gửi request nhưng ở dạng string phải dùng hàm
sdk.AccAddressFromBech32()
để convert về dạng sdk.AccAddress
1.2 Update product
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | <span class="token keyword">type</span> updateProductReq <span class="token keyword">struct</span> <span class="token punctuation">{</span> BaseReq rest<span class="token punctuation">.</span>BaseReq <span class="token string">`json:"base_req"`</span> ProductID <span class="token builtin">string</span> <span class="token string">`json:"productID"`</span> Description <span class="token builtin">string</span> <span class="token string">`json:"description"`</span> Price <span class="token builtin">string</span> <span class="token string">`json:"price"`</span> <span class="token punctuation">}</span> <span class="token keyword">func</span> <span class="token function">updateProductHandler</span><span class="token punctuation">(</span>cliCtx context<span class="token punctuation">.</span>CLIContext<span class="token punctuation">)</span> http<span class="token punctuation">.</span>HandlerFunc <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token keyword">func</span><span class="token punctuation">(</span>w http<span class="token punctuation">.</span>ResponseWriter<span class="token punctuation">,</span> r <span class="token operator">*</span>http<span class="token punctuation">.</span>Request<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">var</span> req createProductReq <span class="token keyword">if</span> <span class="token operator">!</span>rest<span class="token punctuation">.</span><span class="token function">ReadRESTReq</span><span class="token punctuation">(</span>w<span class="token punctuation">,</span> r<span class="token punctuation">,</span> cliCtx<span class="token punctuation">.</span>Codec<span class="token punctuation">,</span> <span class="token operator">&</span>req<span class="token punctuation">)</span> <span class="token punctuation">{</span> rest<span class="token punctuation">.</span><span class="token function">WriteErrorResponse</span><span class="token punctuation">(</span>w<span class="token punctuation">,</span> http<span class="token punctuation">.</span>StatusBadRequest<span class="token punctuation">,</span> <span class="token string">"failed to parse request"</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token punctuation">}</span> baseReq <span class="token operator">:=</span> req<span class="token punctuation">.</span>BaseReq<span class="token punctuation">.</span><span class="token function">Sanitize</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">if</span> <span class="token operator">!</span>baseReq<span class="token punctuation">.</span><span class="token function">ValidateBasic</span><span class="token punctuation">(</span>w<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token punctuation">}</span> signer<span class="token punctuation">,</span> err <span class="token operator">:=</span> sdk<span class="token punctuation">.</span><span class="token function">AccAddressFromBech32</span><span class="token punctuation">(</span>req<span class="token punctuation">.</span>BaseReq<span class="token punctuation">.</span>From<span class="token punctuation">)</span> <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> rest<span class="token punctuation">.</span><span class="token function">WriteErrorResponse</span><span class="token punctuation">(</span>w<span class="token punctuation">,</span> http<span class="token punctuation">.</span>StatusBadRequest<span class="token punctuation">,</span> err<span class="token punctuation">.</span><span class="token function">Error</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token punctuation">}</span> price<span class="token punctuation">,</span> err <span class="token operator">:=</span> sdk<span class="token punctuation">.</span><span class="token function">ParseCoins</span><span class="token punctuation">(</span>req<span class="token punctuation">.</span>Price<span class="token punctuation">)</span> <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> rest<span class="token punctuation">.</span><span class="token function">WriteErrorResponse</span><span class="token punctuation">(</span>w<span class="token punctuation">,</span> http<span class="token punctuation">.</span>StatusBadRequest<span class="token punctuation">,</span> err<span class="token punctuation">.</span><span class="token function">Error</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token punctuation">}</span> <span class="token comment">// create the message</span> msg <span class="token operator">:=</span> types<span class="token punctuation">.</span><span class="token function">NewMsgUpdateProduct</span><span class="token punctuation">(</span>req<span class="token punctuation">.</span>ProductID<span class="token punctuation">,</span> req<span class="token punctuation">.</span>Description<span class="token punctuation">,</span> price<span class="token punctuation">,</span> signer<span class="token punctuation">)</span> err <span class="token operator">=</span> msg<span class="token punctuation">.</span><span class="token function">ValidateBasic</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> rest<span class="token punctuation">.</span><span class="token function">WriteErrorResponse</span><span class="token punctuation">(</span>w<span class="token punctuation">,</span> http<span class="token punctuation">.</span>StatusBadRequest<span class="token punctuation">,</span> err<span class="token punctuation">.</span><span class="token function">Error</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token punctuation">}</span> utils<span class="token punctuation">.</span><span class="token function">WriteGenerateStdTxResponse</span><span class="token punctuation">(</span>w<span class="token punctuation">,</span> cliCtx<span class="token punctuation">,</span> baseReq<span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token punctuation">]</span>sdk<span class="token punctuation">.</span>Msg<span class="token punctuation">{</span>msg<span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
1.3 Delete product
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | <span class="token keyword">type</span> deleteProductReq <span class="token keyword">struct</span> <span class="token punctuation">{</span> BaseReq rest<span class="token punctuation">.</span>BaseReq <span class="token string">`json:"base_req"`</span> ProductID <span class="token builtin">string</span> <span class="token string">`json:"productID"`</span> <span class="token punctuation">}</span> <span class="token keyword">func</span> <span class="token function">deleteProductHandler</span><span class="token punctuation">(</span>cliCtx context<span class="token punctuation">.</span>CLIContext<span class="token punctuation">)</span> http<span class="token punctuation">.</span>HandlerFunc <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token keyword">func</span><span class="token punctuation">(</span>w http<span class="token punctuation">.</span>ResponseWriter<span class="token punctuation">,</span> r <span class="token operator">*</span>http<span class="token punctuation">.</span>Request<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">var</span> req deleteProductReq <span class="token keyword">if</span> <span class="token operator">!</span>rest<span class="token punctuation">.</span><span class="token function">ReadRESTReq</span><span class="token punctuation">(</span>w<span class="token punctuation">,</span> r<span class="token punctuation">,</span> cliCtx<span class="token punctuation">.</span>Codec<span class="token punctuation">,</span> <span class="token operator">&</span>req<span class="token punctuation">)</span> <span class="token punctuation">{</span> rest<span class="token punctuation">.</span><span class="token function">WriteErrorResponse</span><span class="token punctuation">(</span>w<span class="token punctuation">,</span> http<span class="token punctuation">.</span>StatusBadRequest<span class="token punctuation">,</span> <span class="token string">"failed to parse request"</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token punctuation">}</span> baseReq <span class="token operator">:=</span> req<span class="token punctuation">.</span>BaseReq<span class="token punctuation">.</span><span class="token function">Sanitize</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">if</span> <span class="token operator">!</span>baseReq<span class="token punctuation">.</span><span class="token function">ValidateBasic</span><span class="token punctuation">(</span>w<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token punctuation">}</span> signer<span class="token punctuation">,</span> err <span class="token operator">:=</span> sdk<span class="token punctuation">.</span><span class="token function">AccAddressFromBech32</span><span class="token punctuation">(</span>req<span class="token punctuation">.</span>BaseReq<span class="token punctuation">.</span>From<span class="token punctuation">)</span> <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> rest<span class="token punctuation">.</span><span class="token function">WriteErrorResponse</span><span class="token punctuation">(</span>w<span class="token punctuation">,</span> http<span class="token punctuation">.</span>StatusBadRequest<span class="token punctuation">,</span> err<span class="token punctuation">.</span><span class="token function">Error</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token punctuation">}</span> <span class="token comment">// create the message</span> msg <span class="token operator">:=</span> types<span class="token punctuation">.</span><span class="token function">NewMsgDeleteProduct</span><span class="token punctuation">(</span>req<span class="token punctuation">.</span>ProductID<span class="token punctuation">,</span> signer<span class="token punctuation">)</span> err <span class="token operator">=</span> msg<span class="token punctuation">.</span><span class="token function">ValidateBasic</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> rest<span class="token punctuation">.</span><span class="token function">WriteErrorResponse</span><span class="token punctuation">(</span>w<span class="token punctuation">,</span> http<span class="token punctuation">.</span>StatusBadRequest<span class="token punctuation">,</span> err<span class="token punctuation">.</span><span class="token function">Error</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token punctuation">}</span> utils<span class="token punctuation">.</span><span class="token function">WriteGenerateStdTxResponse</span><span class="token punctuation">(</span>w<span class="token punctuation">,</span> cliCtx<span class="token punctuation">,</span> baseReq<span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token punctuation">]</span>sdk<span class="token punctuation">.</span>Msg<span class="token punctuation">{</span>msg<span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
1.4 Buy Product
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | <span class="token keyword">type</span> buyProductReq <span class="token keyword">struct</span> <span class="token punctuation">{</span> BaseReq rest<span class="token punctuation">.</span>BaseReq <span class="token string">`json:"base_req"`</span> ProductID <span class="token builtin">string</span> <span class="token string">`json:"productID"`</span> <span class="token punctuation">}</span> <span class="token keyword">func</span> <span class="token function">buyProductHandler</span><span class="token punctuation">(</span>cliCtx context<span class="token punctuation">.</span>CLIContext<span class="token punctuation">)</span> http<span class="token punctuation">.</span>HandlerFunc <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token keyword">func</span><span class="token punctuation">(</span>w http<span class="token punctuation">.</span>ResponseWriter<span class="token punctuation">,</span> r <span class="token operator">*</span>http<span class="token punctuation">.</span>Request<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">var</span> req buyProductReq <span class="token keyword">if</span> <span class="token operator">!</span>rest<span class="token punctuation">.</span><span class="token function">ReadRESTReq</span><span class="token punctuation">(</span>w<span class="token punctuation">,</span> r<span class="token punctuation">,</span> cliCtx<span class="token punctuation">.</span>Codec<span class="token punctuation">,</span> <span class="token operator">&</span>req<span class="token punctuation">)</span> <span class="token punctuation">{</span> rest<span class="token punctuation">.</span><span class="token function">WriteErrorResponse</span><span class="token punctuation">(</span>w<span class="token punctuation">,</span> http<span class="token punctuation">.</span>StatusBadRequest<span class="token punctuation">,</span> <span class="token string">"failed to parse request"</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token punctuation">}</span> baseReq <span class="token operator">:=</span> req<span class="token punctuation">.</span>BaseReq<span class="token punctuation">.</span><span class="token function">Sanitize</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">if</span> <span class="token operator">!</span>baseReq<span class="token punctuation">.</span><span class="token function">ValidateBasic</span><span class="token punctuation">(</span>w<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token punctuation">}</span> signer<span class="token punctuation">,</span> err <span class="token operator">:=</span> sdk<span class="token punctuation">.</span><span class="token function">AccAddressFromBech32</span><span class="token punctuation">(</span>req<span class="token punctuation">.</span>BaseReq<span class="token punctuation">.</span>From<span class="token punctuation">)</span> <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> rest<span class="token punctuation">.</span><span class="token function">WriteErrorResponse</span><span class="token punctuation">(</span>w<span class="token punctuation">,</span> http<span class="token punctuation">.</span>StatusBadRequest<span class="token punctuation">,</span> err<span class="token punctuation">.</span><span class="token function">Error</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token punctuation">}</span> <span class="token comment">// create the message</span> msg <span class="token operator">:=</span> types<span class="token punctuation">.</span><span class="token function">NewMsgBuyProduct</span><span class="token punctuation">(</span>req<span class="token punctuation">.</span>ProductID<span class="token punctuation">,</span> signer<span class="token punctuation">)</span> err <span class="token operator">=</span> msg<span class="token punctuation">.</span><span class="token function">ValidateBasic</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> rest<span class="token punctuation">.</span><span class="token function">WriteErrorResponse</span><span class="token punctuation">(</span>w<span class="token punctuation">,</span> http<span class="token punctuation">.</span>StatusBadRequest<span class="token punctuation">,</span> err<span class="token punctuation">.</span><span class="token function">Error</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token punctuation">}</span> utils<span class="token punctuation">.</span><span class="token function">WriteGenerateStdTxResponse</span><span class="token punctuation">(</span>w<span class="token punctuation">,</span> cliCtx<span class="token punctuation">,</span> baseReq<span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token punctuation">]</span>sdk<span class="token punctuation">.</span>Msg<span class="token punctuation">{</span>msg<span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
2 Các hàm query để xử lý request được gửi lên bằng phương thức get.
Mở file x/nameservice/client/rest/query.go
và thêm các dòng sau vào:
2.1 Query Product theo productID
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <span class="token keyword">func</span> <span class="token function">queryProductHandler</span><span class="token punctuation">(</span>cliCtx context<span class="token punctuation">.</span>CLIContext<span class="token punctuation">,</span> storeName <span class="token builtin">string</span><span class="token punctuation">)</span> http<span class="token punctuation">.</span>HandlerFunc <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token keyword">func</span><span class="token punctuation">(</span>w http<span class="token punctuation">.</span>ResponseWriter<span class="token punctuation">,</span> r <span class="token operator">*</span>http<span class="token punctuation">.</span>Request<span class="token punctuation">)</span> <span class="token punctuation">{</span> vars <span class="token operator">:=</span> mux<span class="token punctuation">.</span><span class="token function">Vars</span><span class="token punctuation">(</span>r<span class="token punctuation">)</span> productID <span class="token operator">:=</span> vars<span class="token punctuation">[</span><span class="token string">"productID"</span><span class="token punctuation">]</span> <span class="token comment">// lấy productID từ url</span> res<span class="token punctuation">,</span> <span class="token boolean">_</span><span class="token punctuation">,</span> err <span class="token operator">:=</span> cliCtx<span class="token punctuation">.</span><span class="token function">QueryWithData</span><span class="token punctuation">(</span>fmt<span class="token punctuation">.</span><span class="token function">Sprintf</span><span class="token punctuation">(</span><span class="token string">"custom/%s/product/%s"</span><span class="token punctuation">,</span> storeName<span class="token punctuation">,</span> productID<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token boolean">nil</span><span class="token punctuation">)</span> <span class="token comment">// query product</span> <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> rest<span class="token punctuation">.</span><span class="token function">WriteErrorResponse</span><span class="token punctuation">(</span>w<span class="token punctuation">,</span> http<span class="token punctuation">.</span>StatusNotFound<span class="token punctuation">,</span> err<span class="token punctuation">.</span><span class="token function">Error</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token punctuation">}</span> rest<span class="token punctuation">.</span><span class="token function">PostProcessResponse</span><span class="token punctuation">(</span>w<span class="token punctuation">,</span> cliCtx<span class="token punctuation">,</span> res<span class="token punctuation">)</span> <span class="token comment">// trả về kết quả</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
2.1 Query tất cả products
1 2 3 4 5 6 7 8 9 10 11 | <span class="token keyword">func</span> <span class="token function">allProductsHandler</span><span class="token punctuation">(</span>cliCtx context<span class="token punctuation">.</span>CLIContext<span class="token punctuation">,</span> storeName <span class="token builtin">string</span><span class="token punctuation">)</span> http<span class="token punctuation">.</span>HandlerFunc <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token keyword">func</span><span class="token punctuation">(</span>w http<span class="token punctuation">.</span>ResponseWriter<span class="token punctuation">,</span> r <span class="token operator">*</span>http<span class="token punctuation">.</span>Request<span class="token punctuation">)</span> <span class="token punctuation">{</span> res<span class="token punctuation">,</span> <span class="token boolean">_</span><span class="token punctuation">,</span> err <span class="token operator">:=</span> cliCtx<span class="token punctuation">.</span><span class="token function">QueryWithData</span><span class="token punctuation">(</span>fmt<span class="token punctuation">.</span><span class="token function">Sprintf</span><span class="token punctuation">(</span><span class="token string">"custom/%s/products"</span><span class="token punctuation">,</span> storeName<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token boolean">nil</span><span class="token punctuation">)</span> <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> rest<span class="token punctuation">.</span><span class="token function">WriteErrorResponse</span><span class="token punctuation">(</span>w<span class="token punctuation">,</span> http<span class="token punctuation">.</span>StatusNotFound<span class="token punctuation">,</span> err<span class="token punctuation">.</span><span class="token function">Error</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token punctuation">}</span> rest<span class="token punctuation">.</span><span class="token function">PostProcessResponse</span><span class="token punctuation">(</span>w<span class="token punctuation">,</span> cliCtx<span class="token punctuation">,</span> res<span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
3 Thêm các routes để gọi đến các hàm trong tx.go và query.go
Mở file x/nameservice/client/rest/rest.go
và thêm các dòng sau:
1 2 3 4 5 6 | r<span class="token punctuation">.</span><span class="token function">HandleFunc</span><span class="token punctuation">(</span>fmt<span class="token punctuation">.</span><span class="token function">Sprintf</span><span class="token punctuation">(</span><span class="token string">"/%s/product"</span><span class="token punctuation">,</span> storeName<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">createProductHandler</span><span class="token punctuation">(</span>cliCtx<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Methods</span><span class="token punctuation">(</span><span class="token string">"POST"</span><span class="token punctuation">)</span> r<span class="token punctuation">.</span><span class="token function">HandleFunc</span><span class="token punctuation">(</span>fmt<span class="token punctuation">.</span><span class="token function">Sprintf</span><span class="token punctuation">(</span><span class="token string">"/%s/product"</span><span class="token punctuation">,</span> storeName<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">updateProductHandler</span><span class="token punctuation">(</span>cliCtx<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Methods</span><span class="token punctuation">(</span><span class="token string">"PUT"</span><span class="token punctuation">)</span> r<span class="token punctuation">.</span><span class="token function">HandleFunc</span><span class="token punctuation">(</span>fmt<span class="token punctuation">.</span><span class="token function">Sprintf</span><span class="token punctuation">(</span><span class="token string">"/%s/product/buyProduct"</span><span class="token punctuation">,</span> storeName<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">buyProductHandler</span><span class="token punctuation">(</span>cliCtx<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Methods</span><span class="token punctuation">(</span><span class="token string">"POST"</span><span class="token punctuation">)</span> r<span class="token punctuation">.</span><span class="token function">HandleFunc</span><span class="token punctuation">(</span>fmt<span class="token punctuation">.</span><span class="token function">Sprintf</span><span class="token punctuation">(</span><span class="token string">"/%s/product/{productID}"</span><span class="token punctuation">,</span> storeName<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">queryProductHandler</span><span class="token punctuation">(</span>cliCtx<span class="token punctuation">,</span> storeName<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Methods</span><span class="token punctuation">(</span><span class="token string">"GET"</span><span class="token punctuation">)</span> r<span class="token punctuation">.</span><span class="token function">HandleFunc</span><span class="token punctuation">(</span>fmt<span class="token punctuation">.</span><span class="token function">Sprintf</span><span class="token punctuation">(</span><span class="token string">"/%s/product"</span><span class="token punctuation">,</span> storeName<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">allProductsHandler</span><span class="token punctuation">(</span>cliCtx<span class="token punctuation">,</span> storeName<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Methods</span><span class="token punctuation">(</span><span class="token string">"GET"</span><span class="token punctuation">)</span> |
4. Test
Ở thư mục gố chạy câu lệnh sau để make lại tools:
1 2 | <span class="token function">make</span> <span class="token function">install</span> |
Init lại network
1 2 3 | ./init.sh nsd start |
Để nguyên terminal đó, mở 1 terminal khác lên để chạy câu lệnh run rest-server
1 2 | nscli rest-server --chain-id namechain --trust-node |
Mở thêm một terminal khác và chạy các câu lệnh sau để test, đầu tiên là jack tạo product:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <span class="token comment"># lấy thông tin của jack</span> <span class="token function">curl</span> -s http://localhost:1317/auth/accounts/<span class="token variable"><span class="token variable">$(</span>nscli keys show jack -a<span class="token variable">)</span></span> <span class="token comment"># lấy thông tin của alice</span> <span class="token function">curl</span> -s http://localhost:1317/auth/accounts/<span class="token variable"><span class="token variable">$(</span>nscli keys show alice -a<span class="token variable">)</span></span> <span class="token comment"># jack gọi đến route http://localhost:1317/nameservice/product tạo một tạo một proposal có chứ MsgCreateProduct</span> <span class="token function">curl</span> -XPOST -s http://localhost:1317/nameservice/product --data-binary <span class="token string">'{"base_req":{"from":"'</span><span class="token variable"><span class="token variable">$(</span>nscli keys show jack -a<span class="token variable">)</span></span><span class="token string">'","chain_id":"namechain"},"productID":"product01","description":"description01","price":"10nametoken"}'</span> <span class="token operator">></span> unsignedTx.json <span class="token comment"># một giao dịch chưa được ký đã được lưu vào file unsignedTx.json, ta sẽ phải chạy một lệnh để cho jack ký nó, chú ý đến sequence và account-number </span> nscli tx sign unsignedTx.json --from jack --offline --chain-id namechain --sequence 1 --account-number 3 <span class="token operator">></span> signedTx.json <span class="token comment"># sau đó broadcast tx để handler có thể bắt được</span> nscli tx broadcast signedTx.json <span class="token comment"># query để thấy product vừa được tạo</span> <span class="token function">curl</span> -s http://localhost:1317/nameservice/product/product01 |
Kết quả
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <span class="token punctuation">{</span> <span class="token property">"height"</span><span class="token operator">:</span> <span class="token string">"0"</span><span class="token punctuation">,</span> <span class="token property">"result"</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token property">"productID"</span><span class="token operator">:</span> <span class="token string">"product01"</span><span class="token punctuation">,</span> <span class="token property">"description"</span><span class="token operator">:</span> <span class="token string">"description01"</span><span class="token punctuation">,</span> <span class="token property">"owner"</span><span class="token operator">:</span> <span class="token string">"cosmos1wzktejtsnpa0pzzyzth780sl2tcstj86pm4wr6"</span><span class="token punctuation">,</span> <span class="token property">"price"</span><span class="token operator">:</span> <span class="token punctuation">[</span> <span class="token punctuation">{</span> <span class="token property">"denom"</span><span class="token operator">:</span> <span class="token string">"nametoken"</span><span class="token punctuation">,</span> <span class="token property">"amount"</span><span class="token operator">:</span> <span class="token string">"10"</span> <span class="token punctuation">}</span> <span class="token punctuation">]</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
Tiếp theo là alice mua product:
1 2 3 4 5 6 7 8 9 10 | <span class="token comment"># alice gọi route http://localhost:1317/nameservice/product/buyProduct để tạo một proposal có chưa MsgBuyProduct</span> <span class="token function">curl</span> -XPOST -s http://localhost:1317/nameservice/product/buyProduct --data-binary <span class="token string">'{"base_req":{"from":"'</span><span class="token variable"><span class="token variable">$(</span>nscli keys show alice -a<span class="token variable">)</span></span><span class="token string">'","chain_id":"namechain"},"productID":"product01"}'</span> <span class="token operator">></span> unsignedTx.json <span class="token comment"># alice ký, chú ý đến sequence và account-number</span> nscli tx sign unsignedTx.json --from alice --offline --chain-id namechain --sequence 0 --account-number 4 <span class="token operator">></span> signedTx.json <span class="token comment"># broadcast giao dịch</span> nscli tx broadcast signedTx.json <span class="token comment"># query lại product, để thấy owner đã được thay đổi</span> <span class="token function">curl</span> -s http://localhost:1317/nameservice/product/product01 |
Kết quả:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <span class="token punctuation">{</span> <span class="token property">"height"</span><span class="token operator">:</span> <span class="token string">"0"</span><span class="token punctuation">,</span> <span class="token property">"result"</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token property">"productID"</span><span class="token operator">:</span> <span class="token string">"product01"</span><span class="token punctuation">,</span> <span class="token property">"description"</span><span class="token operator">:</span> <span class="token string">"description01"</span><span class="token punctuation">,</span> <span class="token property">"owner"</span><span class="token operator">:</span> <span class="token string">"cosmos1my6qwkz6cz40ful4tquckhhuajzzxcj80rsdrr"</span><span class="token punctuation">,</span> <span class="token property">"price"</span><span class="token operator">:</span> <span class="token punctuation">[</span> <span class="token punctuation">{</span> <span class="token property">"denom"</span><span class="token operator">:</span> <span class="token string">"nametoken"</span><span class="token punctuation">,</span> <span class="token property">"amount"</span><span class="token operator">:</span> <span class="token string">"10"</span> <span class="token punctuation">}</span> <span class="token punctuation">]</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
Xem lại thông tin của jack và alice để thấy tiền đã được chuyển từ alice sang jack
1 2 3 | <span class="token function">curl</span> -s http://localhost:1317/auth/accounts/<span class="token variable"><span class="token variable">$(</span>nscli keys show jack -a<span class="token variable">)</span></span> <span class="token function">curl</span> -s http://localhost:1317/auth/accounts/<span class="token variable"><span class="token variable">$(</span>nscli keys show alice -a<span class="token variable">)</span></span> |
Kết quả:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | <span class="token punctuation">{</span> <span class="token property">"height"</span><span class="token operator">:</span> <span class="token string">"506"</span><span class="token punctuation">,</span> <span class="token property">"result"</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token property">"type"</span><span class="token operator">:</span> <span class="token string">"cosmos-sdk/Account"</span><span class="token punctuation">,</span> <span class="token property">"value"</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token property">"address"</span><span class="token operator">:</span> <span class="token string">"cosmos1wzktejtsnpa0pzzyzth780sl2tcstj86pm4wr6"</span><span class="token punctuation">,</span> <span class="token property">"coins"</span><span class="token operator">:</span> <span class="token punctuation">[</span> <span class="token punctuation">{</span> <span class="token property">"denom"</span><span class="token operator">:</span> <span class="token string">"nametoken"</span><span class="token punctuation">,</span> <span class="token property">"amount"</span><span class="token operator">:</span> <span class="token string">"1010"</span> <span class="token punctuation">}</span> <span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token property">"public_key"</span><span class="token operator">:</span> <span class="token string">"cosmospub1addwnpepqddtqrpnq6889s5wet6m4s9khgrdqfjwyje09kzd7rsgh76zv8ftzpj3d36"</span><span class="token punctuation">,</span> <span class="token property">"account_number"</span><span class="token operator">:</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token property">"sequence"</span><span class="token operator">:</span> <span class="token number">2</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | <span class="token punctuation">{</span> <span class="token property">"height"</span><span class="token operator">:</span> <span class="token string">"513"</span><span class="token punctuation">,</span> <span class="token property">"result"</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token property">"type"</span><span class="token operator">:</span> <span class="token string">"cosmos-sdk/Account"</span><span class="token punctuation">,</span> <span class="token property">"value"</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token property">"address"</span><span class="token operator">:</span> <span class="token string">"cosmos1my6qwkz6cz40ful4tquckhhuajzzxcj80rsdrr"</span><span class="token punctuation">,</span> <span class="token property">"coins"</span><span class="token operator">:</span> <span class="token punctuation">[</span> <span class="token punctuation">{</span> <span class="token property">"denom"</span><span class="token operator">:</span> <span class="token string">"nametoken"</span><span class="token punctuation">,</span> <span class="token property">"amount"</span><span class="token operator">:</span> <span class="token string">"990"</span> <span class="token punctuation">}</span> <span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token property">"public_key"</span><span class="token operator">:</span> <span class="token string">"cosmospub1addwnpepqwj7up3q7lcwxj80fc07mely24acltafpangq8r2f42f788zzn8a5yw06rq"</span><span class="token punctuation">,</span> <span class="token property">"account_number"</span><span class="token operator">:</span> <span class="token number">4</span><span class="token punctuation">,</span> <span class="token property">"sequence"</span><span class="token operator">:</span> <span class="token number">1</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
Tổng kết
Như vậy là đã xong, nhưng còn một điều là hiện tại user vẫn phải ký và broadcast giao dịch bằng câu lệnh, bài sau – bài cuối cùng trong series này mình sẽ hướng dẫn các bạn viết route cho việc ký và broadcast giao dịch để sau đó có thể test dễ dàng trên PostMan và ghép với giao diện
Link tham khảo
https://tutorials.cosmos.network/nameservice/tutorial/23-run-rest.html