--- id: extensions_tutorial_chat_command title: Extension chat command tutorial --- # Write a chat command One of the main use case for extensions is to add new chat commands. This tutorial will go step by step through the creation and deployment of a chat command allowing to send NFTs. ## Add meta data First step is to create the skeleton extension with some relevant metadata: ```clojure {meta {:name "My command name" :description "My command description" :documentation "Some more details can go there"}} ``` Metadata will be displayed to the end user before installing an extension. ## Define hook entry point (chat command) Hooks identify what part of status will be extended. Each hook has a unique identifier and a set of key/value elements specific to this hook. An extension can implement several hooks. In this tutorial a chat command is created: it's specific id is `collectible` and the generic hook type for a chat command is `commands`. A `command` hook requires the following properties to be set: * scope * preview and short-preview * parameters ### Scope Scope can be any combination of: * personal-chats * group-chats * public-chats Here we will demonstrate `personal-chats`. ```clojure {hooks/commands.collectible {... :scope #{:personal-chats}} ;; Could be #{:personal-chats :group-chats} ``` ### Previews `Previews` are used to display the result of a command execution in a chat. `Short previews` will be displayed as last message in the chat item of the Home tab of Status. Both previews must point to definition of UI in [Hiccup syntax](https://github.com/weavejester/hiccup/wiki/Syntax) using a combination of views, queries and events supported by status host. More details can be found [here](https://status-im.github.io/pluto/docs/concepts/Anatomy.html). Previews receive data from status encapsulating the parameters provided by the end user and some relevant contextual information. Those can be accessed in a view using the `properties` reference. Our short preview definition: ```clojure {views/short-preview (let [{{{symbol :symbol} :params} :content outgoing :outgoing} properties] [view {:flex-direction :row :align-items :flex-start} [text (if outgoing "Sent " "Received ")] [text symbol]])} ``` `properties` data is accessed using [destructuring](https://status-im.github.io/pluto/docs/concepts/View.html#destructuring). `text` and `view` are view elements available for all hosts. `if` is a block providing conditional logic. Our preview definition: ```clojure {views/preview (let [{{{symbol :symbol token :token tx-hash :tx-hash} :params} :content outgoing :outgoing timestamp-str :timestamp-str} properties collectible-token [get-collectible-token {:symbol symbol :token token}] [view {:flex-direction :column :align-items :flex-start} [status/nft-token collectible-token] [view {:color (if outgoing "#707caf" "#939ba1") :margin-top 6 :font-size 12 :flex-direction :row} [text "Sent at "] [text timestamp-str]] [status/send-status {:tx-hash tx-hash :outgoing outgoing}]])} ``` `status/nft-token` and `status/send-status` are view element specific to status. `[status/get-collectible-token {:symbol symbol :token token}]` is a query giving access to details for a specific collectible. ### Parameters The NFT chat command has 2 required parameters: the NFT type and the specific NFT you want to exchange. Both will use Status UI components to provide a nice visual selection experience. A parameter is identified by its `id` and must define a `type` and a `placeholder` (any string). In this tutorial `:text` and `:number` will be used. `suggestions` can be optionally provided and must point to a `view`. ```clojure {hooks/commands.collectible {... :parameters [{:id :symbol :type :text :placeholder "Collectible symbol" :suggestions status/asset-selector} {:id :token :type :number :placeholder "Collectible token" :suggestions status/token-selector}]}} ``` ## Deploy Extensions are identified by a URI and can be loaded in status via a universal link. Currently only GitHub gist is supported as provider. A universal link pointing to an extension would then look like: `https://get.status.im/extension/gist@janherich/92747e730b2e115bcbe145114d024e66` ## Use The simplest option is to scan a QR code pointing to your extension. You can also navigate to status user profile and open the `Extensions` item in the `Advanced` section. This option is only available in developer mode. Once loaded, details about an extension are available. An extension can then be installed. Once installed all hooks are `active`. Any extension can then be `deactivated` or re-`activated`. Associated hooks will then be removed/added from Status. You can now use your new extension from within a 1-1 chat! ![collectibles in chat](/tutorials/thumbnails/collectible-chat-command.gif) ## Full extension code ```clojure {meta {:name "Collectibles" :description "Demonstration of collectible command" :documentation "Some nice documentation"} views/preview (let [{{{symbol :symbol token :token tx-hash :tx-hash} :params} :content outgoing :outgoing timestamp-str :timestamp-str} properties collectible-token [get-collectible-token {:symbol symbol :token token}] [view {:flex-direction :column :align-items :flex-start} [status/nft-token collectible-token] [view {:color (if outgoing "#707caf" "#939ba1") :margin-top 6 :font-size 12 :flex-direction :row} [text "Sent at "] [text timestamp-str]] [status/send-status {:tx-hash tx-hash :outgoing outgoing}]]) views/short-preview (let [{{{symbol :symbol} :params} :content outgoing :outgoing} properties] [view {:flex-direction :row :align-items :flex-start} [text (if outgoing "Sent " "Received ")] [text symbol]]) hooks/commands.collectible {:scope #{:personal-chats} :preview preview :short-preview short-preview :parameters [{:id :symbol :type :text :placeholder "Collectible symbol" :suggestions status/asset-selector} {:id :token :type :number :placeholder "Collectible token" :suggestions status/token-selector}]}} ```