<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Anthony Law</title>
    <description>The latest articles on Forem by Anthony Law (@anthonylaw).</description>
    <link>https://forem.com/anthonylaw</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F171427%2Faf7b4e7d-8bfe-40a9-a7ca-62b01b546e2b.jpeg</url>
      <title>Forem: Anthony Law</title>
      <link>https://forem.com/anthonylaw</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/anthonylaw"/>
    <language>en</language>
    <item>
      <title>Symbol Mosaic Revocation Transaction In Metaverse</title>
      <dc:creator>Anthony Law</dc:creator>
      <pubDate>Wed, 01 Dec 2021 10:24:39 +0000</pubDate>
      <link>https://forem.com/anthonylaw/symbol-mosaic-revocation-transaction-in-metaverse-2dob</link>
      <guid>https://forem.com/anthonylaw/symbol-mosaic-revocation-transaction-in-metaverse-2dob</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In the new &lt;a href="https://github.com/symbol/catapult-client/releases/tag/v1.0.3.0"&gt;catapult-client v1.0.3.0&lt;/a&gt;, Symbol has added a &lt;strong&gt;Mosaic Supply Revocation&lt;/strong&gt; transaction type and a &lt;strong&gt;Revokable&lt;/strong&gt; mosaic flag.&lt;/p&gt;

&lt;p&gt;Mosaic Supply Revocation allows the mosaic &lt;strong&gt;creator&lt;/strong&gt; to collect back any mosaics flagged as &lt;strong&gt;Revokable&lt;/strong&gt; from whoever holds them, at anytime.&lt;/p&gt;

&lt;h2&gt;
  
  
  How it works
&lt;/h2&gt;

&lt;p&gt;The Mosaic Supply Revocation transaction only works with Revokable Mosaics.&lt;/p&gt;

&lt;p&gt;As an example, imagine a private property in the XYM City metaverse, where you must have access permission from the property owner to enter.&lt;/p&gt;

&lt;p&gt;Let's assume a private property called &lt;strong&gt;Bull Fight Club&lt;/strong&gt;. Users must own a &lt;code&gt;BFC.daily-pass&lt;/code&gt; mosaic to enter the club, which can be purchased from the counter.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LRuKUVIY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6435vgnvo8hyt4ww50go.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LRuKUVIY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6435vgnvo8hyt4ww50go.png" alt="BFC Banner" width="723" height="631"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Bull Fight Club will issue one &lt;code&gt;BFC.daily-pass&lt;/code&gt; revokable mosaic to a user once received the 10 XYM payment.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--XrbLdFoR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2lhlbk3k0hgxfr3bluab.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XrbLdFoR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2lhlbk3k0hgxfr3bluab.png" alt="Process" width="604" height="184"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When daily pass expires, Bull Fight Club can issue a Mosaic Supply Revocation transaction to collect back the &lt;code&gt;BFC.daily-pass&lt;/code&gt; without user interaction.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bIK5OX6W--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jil9l766961umw57u4ro.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bIK5OX6W--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jil9l766961umw57u4ro.png" alt="Mosaic Supply Revocation transaction" width="630" height="183"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Example code
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Create revokable mosaic
&lt;/h3&gt;

&lt;p&gt;I just want to highlight the new code. Refer to the full &lt;a href="https://docs.symbolplatform.com/guides/mosaic/creating-a-mosaic.html#method-02-using-the-sdk"&gt;example here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;When creating Revokable mosaics, I suggest you also make Transferable=false to prevent the recipient from transferring the mosaic to another account. Otherwise, recovering the mosaic will be harder.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;BFC_Operator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Account&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createFromPrivateKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;privateKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;networkType&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isSupplyMutable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isTransferable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;--&lt;/span&gt; &lt;span class="nx"&gt;prevert&lt;/span&gt; &lt;span class="nx"&gt;recipient&lt;/span&gt; &lt;span class="nx"&gt;trasfer&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;other&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isRestrictable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isRevokable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;---&lt;/span&gt; &lt;span class="nx"&gt;New&lt;/span&gt; &lt;span class="nx"&gt;flag&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nonce&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;MosaicNonce&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createRandom&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mosaicDefinitionTransaction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;MosaicDefinitionTransaction&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;Deadline&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;epochAdjustment&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="nx"&gt;nonce&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;MosaicId&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createFromNonce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nonce&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;BFC_Operator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="nx"&gt;MosaicFlags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isSupplyMutable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;isTransferable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;isRestrictable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;isRevokable&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// divisibility&lt;/span&gt;
  &lt;span class="nx"&gt;UInt64&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fromUint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="c1"&gt;// duration&lt;/span&gt;
  &lt;span class="nx"&gt;networkType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Mosaic Supply Revocation transaction
&lt;/h3&gt;

&lt;p&gt;This transaction allows the mosaic owner to collect back revokable mosaic from the specified holder.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mosaicSupplyRevocationTransaction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;MosaicSupplyRevocationTransaction&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;Deadline&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;epochAdjustment&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="nx"&gt;holderAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Symbol&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Mosaic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; 
    &lt;span class="nb"&gt;Symbol&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;MosaicId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;revokable_mosaic_id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; 
    &lt;span class="nb"&gt;Symbol&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;UInt64&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fromUint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt; &lt;span class="c1"&gt;// mosaic unit &lt;/span&gt;
  &lt;span class="nx"&gt;networkType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;maxFee&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Revokable&lt;/strong&gt; mosaic flag and the &lt;strong&gt;Mosaic supply revocation&lt;/strong&gt; transaction are super handy for the business operator who likes to control supply and reuse mosaics.&lt;/p&gt;

&lt;p&gt;In my opinion, the benefit to using it is that the owner of the mosaic can easily control the mosaic supply, and collect back the mosaics without the user paying any fees. The downside is that the holder of the mosaic does not have any control over it.&lt;/p&gt;

&lt;p&gt;Just &lt;strong&gt;be cautious&lt;/strong&gt;, revokable mosaics are not suitable to represent currency/token or share. When doing any mosaic trading, &lt;strong&gt;always ensure you understand the mosaic flags and purpose&lt;/strong&gt;. Keep in mind that any received &lt;strong&gt;revokable mosaics can be reclaimed at any time&lt;/strong&gt; without your consent!&lt;/p&gt;

&lt;p&gt;If you would like to know more about Symbol, please join the &lt;a href="https://discord.com/invite/xymcity"&gt;Discord&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Special thanks to &lt;a href="https://twitter.com/sigsegvx"&gt;Xavi&lt;/a&gt; for reviewing this article.&lt;/p&gt;

</description>
      <category>symbol</category>
      <category>catapult</category>
      <category>blockchain</category>
      <category>metaverse</category>
    </item>
    <item>
      <title>Symbol-GraphQL Server </title>
      <dc:creator>Anthony Law</dc:creator>
      <pubDate>Mon, 07 Dec 2020 18:02:01 +0000</pubDate>
      <link>https://forem.com/anthonylaw/intorduce-symbol-graphql-2h2d</link>
      <guid>https://forem.com/anthonylaw/intorduce-symbol-graphql-2h2d</guid>
      <description>&lt;p&gt;I'm a big fan of &lt;a href="https://graphql.org/"&gt;GraphQL&lt;/a&gt;. I had been following them quite some times but did not have the opportunity to work on it for any project. &lt;/p&gt;

&lt;p&gt;Besides that, &lt;a href="https://symbolplatform.com/"&gt;Symbol&lt;/a&gt; is my favorite blockchain project. I like to take this opportunity to build something cool. &lt;/p&gt;

&lt;p&gt;I decided to build &lt;a href="https://github.com/AnthonyLaw/symbol-graphql"&gt;Symbol-graphql&lt;/a&gt; as my personal side project. I hope it can benefit the Symbol or NEM community with this project.&lt;/p&gt;

&lt;h1&gt;
  
  
  What is Symbol-GraphQL.
&lt;/h1&gt;

&lt;p&gt;Before that, you may wonder what GraphQL is.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--pAZpCWtE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/max/1000/1%2AvGTInrWr7dRBsMDMTMoRRA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--pAZpCWtE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/max/1000/1%2AvGTInrWr7dRBsMDMTMoRRA.png" alt="graphql.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;GraphQL is developed by Facebook and open source in 2015. It's a query language for frontend developers in executing queries with existing data. Besides, it can optimize REST API calls. It gives a declarative way of fetching and updating your data. If you are interested, get more detail can visit &lt;a href="https://graphql.org/"&gt;GraphQL&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5gGGcNQN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://external-content.duckduckgo.com/iu/%3Fu%3Dhttps%253A%252F%252Fe5ce463uma323hyvrr4xumqs-wpengine.netdna-ssl.com%252Fwp-content%252Fuploads%252F2020%252F03%252FGraphQL_architecture_TutorialsPoint.png%26f%3D1%26nofb%3D1" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5gGGcNQN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://external-content.duckduckgo.com/iu/%3Fu%3Dhttps%253A%252F%252Fe5ce463uma323hyvrr4xumqs-wpengine.netdna-ssl.com%252Fwp-content%252Fuploads%252F2020%252F03%252FGraphQL_architecture_TutorialsPoint.png%26f%3D1%26nofb%3D1" alt="image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Summary, Graphql provided a single endpoint responsible for accepting queries, rather than relying on the REST API approach of having separate endpoints for each service.&lt;/p&gt;

&lt;p&gt;So I believe you have an idea of what is &lt;a href="https://github.com/AnthonyLaw/symbol-graphql"&gt;Symbol-graphql&lt;/a&gt;. It not to replace REST API getaway, but It provides an alternative way to retrieve symbol blockchain data just write the query.&lt;/p&gt;

&lt;p&gt;In Symbol-grahpql server we will use &lt;a href="https://github.com/nemtech/symbol-openapi"&gt;symbol-openapi&lt;/a&gt; as a data source, and use &lt;a href="https://graphql-mesh.com/"&gt;Graphql-mesh&lt;/a&gt; to setup graphql server.&lt;/p&gt;

&lt;h1&gt;
  
  
  What makes it different
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--GJ8AYzzO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/rd92lxez0ztu0lh229kh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GJ8AYzzO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/rd92lxez0ztu0lh229kh.png" alt="Screenshot 2020-12-08 at 6.08.50 AM"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I hope the diagram can make you understand. The client can define the data we need, and make a single request to the graphql server endpoint, and the symbol-graphql server will take care and handle the rest of the communication into the Symbol API node.&lt;/p&gt;

&lt;h1&gt;
  
  
  Why should use GraphQL in Symbol.
&lt;/h1&gt;

&lt;p&gt;As GraphQL server is provided a lot of benefit between frontend and backend development. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Developer can always define different types of data in the client application, without altering the backend server in the REST API server.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It has a huge improvement for data transfer speed between the Client application and network, you may need to request 3 API endpoints to get the data, rather than just request a single query from the symbol-graphql server.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It reduces network cost because it uses less bandwidth to transfer data. A big plus for mobile applications.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It enhances client application performance and efficiency because it takes less time to load data from the network.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Playground
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--O6WOlIpM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/0upap5zw91j174x9yx16.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--O6WOlIpM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/0upap5zw91j174x9yx16.png" alt="Screenshot 2020-12-21 at 12.00.03 PM"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Playground is a user interface to allow users to interact with the graphql server. You can write or test any query inside the playground interface before doing any development.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;Left side window&lt;/code&gt; in the Playground is allowed users to write queries. &lt;code&gt;Play button&lt;/code&gt; is for executing the query, and the &lt;code&gt;Right side window&lt;/code&gt; is showing the result.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kDmtWRi4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ijjm5xupjsbce0954pat.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kDmtWRi4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ijjm5xupjsbce0954pat.png" alt="Screenshot 2020-12-21 at 12.08.51 PM"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To check out more data types and schemes, you can click on &lt;code&gt;Docs&lt;/code&gt; and &lt;code&gt;Schemas&lt;/code&gt; on the right side.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4JZxSa4E--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/lkai08o0lgjqjweln70y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4JZxSa4E--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/lkai08o0lgjqjweln70y.png" alt="Screenshot 2020-12-21 at 12.10.51 PM"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Tips: Press &lt;code&gt;Ctrl + Space&lt;/code&gt; (or use Shift + Space as an alternate keyboard shortcut) to bring up the auto-complete window and &lt;code&gt;Ctrl + Enter&lt;/code&gt; to run the GraphQL query.&lt;/p&gt;

&lt;p&gt;let try it &lt;a href="http://139.162.19.139:4000/"&gt;Playground&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  How to implement symbol-graphql in your project.
&lt;/h1&gt;

&lt;p&gt;These are a few of the graphql client libraries you can install in your project. One of my favorites client is &lt;a href="https://www.apollographql.com/docs/react/"&gt;Apollo&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I will update more info and setup once have more free time.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://github.com/AnthonyLaw/symbol-graphql"&gt;Symbol-graphql&lt;/a&gt; server still in the early development stage, other than block schemes, the rest still working in progress such as &lt;code&gt;Account&lt;/code&gt;, &lt;code&gt;Transaction&lt;/code&gt;, &lt;code&gt;Mosaic&lt;/code&gt;, &lt;code&gt;Namespace&lt;/code&gt; and etc, and of course, it supports all the query import from &lt;a href="https://github.com/nemtech/symbol-openapi"&gt;symbol-openapi&lt;/a&gt; as well.&lt;/p&gt;

&lt;p&gt;I'm welcome anyone from the community who is interested and like to contribute and work together.&lt;/p&gt;

&lt;p&gt;Check out on Github: &lt;a href="https://github.com/AnthonyLaw/symbol-graphql"&gt;Symbol-graphql&lt;/a&gt;&lt;/p&gt;

</description>
      <category>graphql</category>
      <category>symbol</category>
      <category>catapult</category>
    </item>
    <item>
      <title>Setup catapult node using Terraform</title>
      <dc:creator>Anthony Law</dc:creator>
      <pubDate>Wed, 18 Dec 2019 01:23:11 +0000</pubDate>
      <link>https://forem.com/anthonylaw/setup-catapult-node-using-terraform-30a8</link>
      <guid>https://forem.com/anthonylaw/setup-catapult-node-using-terraform-30a8</guid>
      <description>&lt;p&gt;Catapult harvesting reward program is so attractive, you may want to learn how to setup node for harvesting before the mainnet is up.&lt;/p&gt;

&lt;p&gt;I like to share with you how you can write an infrastructure as code to deploy your catapult server in your terminal.&lt;/p&gt;

&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;Terraform is very powerful tools for devops, it can write a plan (infrastructure as code) and manage your cloud service.&lt;/p&gt;

&lt;p&gt;as mentioned cloud service, there is a list of the &lt;a href="https://www.terraform.io/docs/providers/index.html"&gt;cloud provider&lt;/a&gt; supported by terraform, in this case, it using Digital Ocean (DO). In case you are not DO user, register uses my &lt;a href="https://m.do.co/c/1b49da47c0eb"&gt;referrals link&lt;/a&gt;, you will get $100 in credit over 60 days.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JVRQ_ksk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.ibb.co/B37f9j7/Qiita.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JVRQ_ksk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.ibb.co/B37f9j7/Qiita.png" alt="Hight-level-diagram"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Write a plan to setup the infrastructure, and some of the script you wish to execute after server provision completed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Terraform will follow the "plan" to execute, starting provision a server.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;After the provision is completed, it will start to execute all the script.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The script will start pulling catapult server code from GitHub plus install essential tools such as docker.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  Objectives
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Provision server from Digital Ocean.&lt;/li&gt;
&lt;li&gt;Install essential tools such as docker.&lt;/li&gt;
&lt;li&gt;download catapult server code from Github. &lt;/li&gt;
&lt;li&gt;Deploy catapult node and join Testnet.&lt;/li&gt;
&lt;li&gt;Deploy all in terminal.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Prerequisites
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Install &lt;a href="https://learn.hashicorp.com/terraform/getting-started/install.html"&gt;Terraform&lt;/a&gt; in your local machine&lt;/li&gt;
&lt;li&gt;Register &lt;a href="https://m.do.co/c/1b49da47c0eb"&gt;DO&lt;/a&gt; account&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Hands-on
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;1. DO Account Setup&lt;/strong&gt; (you can skip, if you already have it)&lt;br&gt;
Add ssh-key in your DO account, it's easy for terminal ssh access to &lt;code&gt;Droplet&lt;/code&gt; later.&lt;/p&gt;

&lt;p&gt;1.1 let generate ssh key without passphrase in your local machine.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh-keygen &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; 100 &lt;span class="nt"&gt;-t&lt;/span&gt; ed25519 &lt;span class="nt"&gt;-f&lt;/span&gt; ~/.ssh/catapult_node
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;1.2 copy &lt;code&gt;catapult_node.pub&lt;/code&gt; to DO account. &lt;a href="https://www.digitalocean.com/docs/droplets/how-to/add-ssh-keys/to-account/"&gt;Tutorial&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;1.3 create access token for later terraform use. &lt;a href="https://www.digitalocean.com/docs/api/create-personal-access-token/"&gt;Tutorial&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Terraform&lt;/strong&gt;&lt;br&gt;
If you are new in Terraform, can start from &lt;a href="https://dev.to/anthonylaw/terraform-for-beginner-jak"&gt;here&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;let write infrastructure plan, I created 4 different files, which is &lt;code&gt;firewall.tf&lt;/code&gt;, &lt;code&gt;main.tf&lt;/code&gt;, &lt;code&gt;variables.tf&lt;/code&gt;, &lt;code&gt;output.tf&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;firewall.tf&lt;/code&gt;, we need define few inbound port for catapult use.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;&lt;span class="k"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"digitalocean_firewall"&lt;/span&gt; &lt;span class="s2"&gt;"catapult-node"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"ssh-and-catapult-port"&lt;/span&gt;
    &lt;span class="nx"&gt;droplet_ids&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;digitalocean_droplet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;catapult-node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="nx"&gt;inbound_rule&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;protocol&lt;/span&gt;         &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"tcp"&lt;/span&gt;
        &lt;span class="nx"&gt;port_range&lt;/span&gt;       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"22"&lt;/span&gt; &lt;span class="c1"&gt;// ssh access &lt;/span&gt;
        &lt;span class="nx"&gt;source_addresses&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"0.0.0.0/0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"::/0"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;inbound_rule&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;protocol&lt;/span&gt;         &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"tcp"&lt;/span&gt;
        &lt;span class="nx"&gt;port_range&lt;/span&gt;       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"3000"&lt;/span&gt; &lt;span class="c1"&gt;// Catapult Api endpoint&lt;/span&gt;
        &lt;span class="nx"&gt;source_addresses&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"0.0.0.0/0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"::/0"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;inbound_rule&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;protocol&lt;/span&gt;         &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"tcp"&lt;/span&gt;
        &lt;span class="nx"&gt;port_range&lt;/span&gt;       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"7900-7902"&lt;/span&gt; &lt;span class="c1"&gt;// Catapult peer communication&lt;/span&gt;
        &lt;span class="nx"&gt;source_addresses&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"0.0.0.0/0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"::/0"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In &lt;code&gt;variables.tf&lt;/code&gt;, define the variables need to be use in the server provision. here we need DO access token, and private_key for ssh login. so we no longer need for password.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;&lt;span class="k"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"do_token"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;default&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"your_DO_Access_Token"&lt;/span&gt; &lt;span class="c1"&gt;// refer 1.3&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"private_key"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;default&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"~/.ssh/catapult_node"&lt;/span&gt; &lt;span class="c1"&gt;// refer 1.1&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In &lt;code&gt;output.tf&lt;/code&gt;, print out the output return from Terraform. After Terraform successful provision, it will print the server ip address in terminal.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;&lt;span class="k"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"fip_output"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Droplet ipv4 address"&lt;/span&gt;
    &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;digitalocean_droplet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;catapult-node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ipv4_address&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Last &lt;code&gt;main.tf&lt;/code&gt;, this is an important part because all the server spec and script execution will be here.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;&lt;span class="c1"&gt;// We are pointing "digitalocean" as our provider.&lt;/span&gt;
&lt;span class="k"&gt;provider&lt;/span&gt; &lt;span class="s2"&gt;"digitalocean"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;token&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;do_token&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// request ssh public key from DO account refer 1.2&lt;/span&gt;
&lt;span class="k"&gt;data&lt;/span&gt; &lt;span class="s2"&gt;"digitalocean_ssh_key"&lt;/span&gt; &lt;span class="s2"&gt;"mykey"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"catapult_node"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// define droplet spec&lt;/span&gt;
&lt;span class="c1"&gt;// https://developers.digitalocean.com/documentation/v2/#list-all-sizes&lt;/span&gt;
&lt;span class="c1"&gt;// define server spec base on your need.&lt;/span&gt;
&lt;span class="k"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"digitalocean_droplet"&lt;/span&gt; &lt;span class="s2"&gt;"catapult-node"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;image&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"ubuntu-18-04-x64"&lt;/span&gt;
    &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"catapult-node-1"&lt;/span&gt;
    &lt;span class="nx"&gt;region&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"sgp1"&lt;/span&gt;
    &lt;span class="nx"&gt;size&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"s-1vcpu-2gb"&lt;/span&gt; &lt;span class="c1"&gt;// server spec&lt;/span&gt;
    &lt;span class="nx"&gt;ssh_keys&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;digitalocean_ssh_key&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mykey&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;// attach public key from my DO account&lt;/span&gt;

&lt;span class="c1"&gt;// script to install docker tools and git pull catapult-server-code&lt;/span&gt;
    &lt;span class="k"&gt;provisioner&lt;/span&gt; &lt;span class="s2"&gt;"remote-exec"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

      &lt;span class="nx"&gt;inline&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="s2"&gt;"export PATH=&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="s2"&gt;PATH:/usr/bin"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;"curl -fsSL https://get.docker.com -o get-docker.sh"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;"sudo sh get-docker.sh"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;"curl -L https://github.com/docker/compose/releases/download/1.22.0/docker-compose-`uname -s`-`uname -m` | sudo tee /usr/local/bin/docker-compose &amp;gt; /dev/null"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;"sudo chmod +x /usr/local/bin/docker-compose"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;"sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;"git config --global --unset http.proxy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;"git config --global --unset https.proxy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;"git clone https://github.com/nemfoundation/catapult-testnet-bootstrap.git"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;"cd catapult-testnet-bootstrap/api-harvest-assembly"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;"sudo docker-compose up --build --detach"&lt;/span&gt;
      &lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="c1"&gt;// for SSH connection to execute script&lt;/span&gt;
      &lt;span class="nx"&gt;connection&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;type&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"ssh"&lt;/span&gt;
        &lt;span class="nx"&gt;private_key&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;private_key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
        &lt;span class="nx"&gt;user&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"root"&lt;/span&gt;
        &lt;span class="nx"&gt;timeout&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"2m"&lt;/span&gt;
        &lt;span class="nx"&gt;host&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ipv4_address&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;play around with&lt;/p&gt;

&lt;p&gt;&lt;code&gt;git clone https://github.com/AnthonyLaw/catapult-terraform&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;cd catapult-terraform&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;terraform init&lt;/code&gt; - to init terraform project.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;terraform apply&lt;/code&gt; - to create droplet in your DO account&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;// output message
...
...
digitalocean_droplet.catapult-node &lt;span class="o"&gt;(&lt;/span&gt;remote-exec&lt;span class="o"&gt;)&lt;/span&gt;: Creating api-harvest-assembly_db_1 ...
digitalocean_droplet.catapult-node &lt;span class="o"&gt;(&lt;/span&gt;remote-exec&lt;span class="o"&gt;)&lt;/span&gt;: Creating api-harvest-assembly_api-broker_1 ...
digitalocean_droplet.catapult-node &lt;span class="o"&gt;(&lt;/span&gt;remote-exec&lt;span class="o"&gt;)&lt;/span&gt;: Creating api-harvest-assembly_store-addresses_1        ... &lt;span class="k"&gt;done
&lt;/span&gt;digitalocean_droplet.catapult-node &lt;span class="o"&gt;(&lt;/span&gt;remote-exec&lt;span class="o"&gt;)&lt;/span&gt;: Creating api-harvest-assembly_api-broker_1             ... &lt;span class="k"&gt;done
&lt;/span&gt;digitalocean_droplet.catapult-node &lt;span class="o"&gt;(&lt;/span&gt;remote-exec&lt;span class="o"&gt;)&lt;/span&gt;: 
digitalocean_droplet.catapult-node &lt;span class="o"&gt;(&lt;/span&gt;remote-exec&lt;span class="o"&gt;)&lt;/span&gt;: Creating api-harvest-assembly_update_vars_1            ... &lt;span class="k"&gt;done
&lt;/span&gt;digitalocean_droplet.catapult-node &lt;span class="o"&gt;(&lt;/span&gt;remote-exec&lt;span class="o"&gt;)&lt;/span&gt;: 
digitalocean_droplet.catapult-node &lt;span class="o"&gt;(&lt;/span&gt;remote-exec&lt;span class="o"&gt;)&lt;/span&gt;: Creating api-harvest-assembly_init-db_1                ... &lt;span class="k"&gt;done
&lt;/span&gt;digitalocean_droplet.catapult-node &lt;span class="o"&gt;(&lt;/span&gt;remote-exec&lt;span class="o"&gt;)&lt;/span&gt;: Creating api-harvest-assembly_rest-gateway_1           ... &lt;span class="k"&gt;done
&lt;/span&gt;digitalocean_droplet.catapult-node &lt;span class="o"&gt;(&lt;/span&gt;remote-exec&lt;span class="o"&gt;)&lt;/span&gt;: 
digitalocean_droplet.catapult-node: Still creating... &lt;span class="o"&gt;[&lt;/span&gt;3m40s elapsed]
digitalocean_droplet.catapult-node: Creation &lt;span class="nb"&gt;complete &lt;/span&gt;after 3m45s &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;171927070]
digitalocean_firewall.catapult-node: Creating...
digitalocean_firewall.catapult-node: Creation &lt;span class="nb"&gt;complete &lt;/span&gt;after 9s &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;98a6e7ed-c54a-4c0c-91b0-f0848fabfa68]

Apply &lt;span class="nb"&gt;complete&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; Resources: 2 added, 0 changed, 0 destroyed.

Outputs:

fip_output &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;
  &lt;span class="s2"&gt;"104.248.153.68"&lt;/span&gt;,
&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once &lt;code&gt;Apply complete&lt;/code&gt;, you can visit &lt;code&gt;&amp;lt;ip&amp;gt;:3000/chain/height&lt;/code&gt; to ensure your catapult server are successful setup.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;terraform destroy&lt;/code&gt; - to destroy droplet in your DO account&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Do you really want to destroy all resources?
  Terraform will destroy all your managed infrastructure, as shown above.
  There is no undo. Only &lt;span class="s1"&gt;'yes'&lt;/span&gt; will be accepted to confirm.

  Enter a value: &lt;span class="nb"&gt;yes

&lt;/span&gt;digitalocean_firewall.catapult-node: Destroying... &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;98a6e7ed-c54a-4c0c-91b0-f0848fabfa68]
digitalocean_firewall.catapult-node: Destruction &lt;span class="nb"&gt;complete &lt;/span&gt;after 10s
digitalocean_droplet.catapult-node: Destroying... &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;171927070]
digitalocean_droplet.catapult-node: Still destroying... &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;171927070, 10s elapsed]
digitalocean_droplet.catapult-node: Still destroying... &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;171927070, 20s elapsed]
digitalocean_droplet.catapult-node: Destruction &lt;span class="nb"&gt;complete &lt;/span&gt;after 22s

Destroy &lt;span class="nb"&gt;complete&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; Resources: 2 destroyed.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Summary
&lt;/h1&gt;

&lt;p&gt;Once your catapult node is up and running, you can easy change your &lt;code&gt;harvesterPrivateKey&lt;/code&gt; and &lt;code&gt;beneficiaryPublicKey&lt;/code&gt; in your node.&lt;/p&gt;

&lt;p&gt;With Terraform, you can easy to write the infrastructure plan to setup any server and join the catapult network.&lt;/p&gt;

&lt;p&gt;Read more :&lt;br&gt;
&lt;a href="https://github.com/AnthonyLaw/catapult-terraform"&gt;Source code&lt;/a&gt;&lt;br&gt;
&lt;a href="https://dev.to/anthonylaw/terraform-for-beginner-jak"&gt;Terraform for beginner&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.terraform.io/"&gt;Terraform.io&lt;/a&gt;&lt;br&gt;
&lt;a href="https://nemtech.github.io/guides/network/running-a-test-net-node.html"&gt;Running Catapult Testnet&lt;/a&gt;&lt;/p&gt;

</description>
      <category>devops</category>
      <category>catapult</category>
      <category>nem</category>
      <category>cloud</category>
    </item>
    <item>
      <title>NEM Catapult for common use Multisig Account</title>
      <dc:creator>Anthony Law</dc:creator>
      <pubDate>Tue, 10 Dec 2019 12:54:09 +0000</pubDate>
      <link>https://forem.com/anthonylaw/nem-catapult-for-common-use-multisig-account-3fae</link>
      <guid>https://forem.com/anthonylaw/nem-catapult-for-common-use-multisig-account-3fae</guid>
      <description>&lt;h2&gt;
  
  
  Integrate blockchain account into existing user management system.
&lt;/h2&gt;

&lt;p&gt;They are a lot of companies are interested in integrating blockchain into the current existing system. The first thing how to integrate the blockchain &lt;strong&gt;&lt;em&gt;Account (wallet)&lt;/em&gt;&lt;/strong&gt; to pair with their current existing user.&lt;/p&gt;

&lt;p&gt;The most common solution is to help the user to manage the private key and store it into a database. &lt;/p&gt;

&lt;p&gt;In my opinion, the first may user don't know how to take care of the private key, because the private key never recovers like “password”. Another reason it may be hard to do a secure way in a smart contract.&lt;/p&gt;

&lt;p&gt;That is not a good solution, because it’s not the decentralized solution and account security is not guaranteed. The blockchain account asset can be controlled by the company or the system admin. In security-wise, if the system admin accidentally deletes the database, otherwise the company needs to spend extra cost to maintain the database.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduce NEM Catapult Blockchain
&lt;/h2&gt;

&lt;p&gt;It’s a powerful blockchain engine, as a developer, it’s easy to implement and fast to integrate into any existing system.&lt;/p&gt;

&lt;p&gt;Catapult provided a lot of &lt;strong&gt;&lt;em&gt;on-chain&lt;/em&gt;&lt;/strong&gt; features, which &lt;strong&gt;&lt;em&gt;multisig account&lt;/em&gt;&lt;/strong&gt; is one of it, and we will be using Multisig Account to apply into user management solution.&lt;/p&gt;

&lt;p&gt;In this example, the company name called &lt;strong&gt;&lt;em&gt;Catapult Academy&lt;/em&gt;&lt;/strong&gt; provided NEM catapult related training and let participate enroll exam. Once the exam pass, Catapult Academy will certify the participant. &lt;/p&gt;

&lt;p&gt;The company like to Integrate NEM blockchain into the current existing system, to make the user traceability, in the future, all digital certificate will distribution via NEM blockchain.&lt;/p&gt;

&lt;h2&gt;
  
  
  Integrate Multisig Account to existing user in database
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sEgDUtuE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/539995/7522aa65-6f00-aa2d-13b2-cd671c5be2d6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sEgDUtuE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/539995/7522aa65-6f00-aa2d-13b2-cd671c5be2d6.png" alt="image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this diagram, we link 3 NEM Account as cosignatories to Multisig Account. In this example, we have &lt;strong&gt;&lt;em&gt;Catapult Academy Admin&lt;/em&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;em&gt;User Management Admin&lt;/em&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;em&gt;User&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;With this solution&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Users able to control the Multisig account by his own account.&lt;/li&gt;
&lt;li&gt;Every transaction detail can track using the Multisig Account. &lt;/li&gt;
&lt;li&gt;The multisig Account condition need to configure &lt;strong&gt;&lt;em&gt;1 minimum approval&lt;/em&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;em&gt;2 minimum removal&lt;/em&gt;&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  1 minimum approval
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;User can directly to interact with his multisig Account, without anyone else permission. &lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2 minimum removal
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Only &lt;strong&gt;&lt;em&gt;Catapult Academy Admin&lt;/em&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;em&gt;User Management Admin&lt;/em&gt;&lt;/strong&gt; can remove the User cosigner public key if users lose the account.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the solution, user are freely control the multisig account, even if user lose the account, user can just recreate the new NEM account and link back to multisig account.&lt;/p&gt;

&lt;h3&gt;
  
  
  High level overview flow (onboard user)
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gUKdn2m---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/539995/bbcc1318-f06f-b369-5283-ab0a818fa0f5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gUKdn2m---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/539995/bbcc1318-f06f-b369-5283-ab0a818fa0f5.png" alt="image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;User have to submit public key to the system.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Once user public key available, system will generate Multisig account and prepare multisig tranaction.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;System can &lt;code&gt;randomly&lt;/code&gt; generate Multisig Account&lt;/li&gt;
&lt;li&gt;Multisig configuration&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Announce Aggregate bonded transaction to network.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update Multisig Account in existing user database.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Related cosignatories must cosign the transaction.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Highlight
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Random account generation&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Account&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;NetworkType&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;nem2-sdk&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;Account&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;generateNewAccount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;NetworkType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;TEST_NET&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// Convert NEM account to Multisig account&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;multisigAccountModificationTransaction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;MultisigAccountModificationTransaction&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;Deadline&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// minimum approval&lt;/span&gt;
    &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// minimum removal&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;userManagementAdminAccount&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;publicAccount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;catapultAcademyAdminAccount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;userAccount&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;[],&lt;/span&gt;
    &lt;span class="nx"&gt;NetworkType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;TEST_NET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;UInt64&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fromUint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// fees&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  High level overview flow (update publickey for exisitng multisig account)
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8jtfv1dh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/539995/e5a07a51-6082-3a85-9c4b-07aff06fe5af.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8jtfv1dh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/539995/e5a07a51-6082-3a85-9c4b-07aff06fe5af.png" alt="image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;User have to submit new public key to system.&lt;/li&gt;
&lt;li&gt;System will prepare Multisig account modification.

&lt;ul&gt;
&lt;li&gt;Retrive the old user public key from multisig account.&lt;/li&gt;
&lt;li&gt;Remote &lt;code&gt;old user public key&lt;/code&gt; and assign the &lt;code&gt;new user public key&lt;/code&gt; to multisig account.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Announce aggregate bonded transaction to network.&lt;/li&gt;
&lt;li&gt;Related cosignatories must cosign the transaction.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Highlight
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Retrive cosignatories and fliter old user public key&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;multisigHttp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;MultisigHttp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;endpoint&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;oldUserPublicKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;multisigHttp&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getMultisigAccountInfo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;MutlisigAccount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toPromise&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;// Remote `old user public key` and assign the `new user public key` to multisig account&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;multisigAccountModificationTransaction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;MultisigAccountModificationTransaction&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;Deadline&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;newUserAccount&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="c1"&gt;// Add &lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;oldUserAccount&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="c1"&gt;// Remote&lt;/span&gt;
    &lt;span class="nx"&gt;networkType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;UInt64&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fromUint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200000&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// Fees&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Summary
&lt;/h3&gt;

&lt;p&gt;As we can see, with this solution, everything is tracking on-chain decentralized. The user database just only needs to add a multisig account record. The benefit for this design, decentralized account management, worry-free for users lose the private key, it won't affect the multisig account. It may be expensive to create Multisig account for every user, but for the long term, it's more secure and gains the decentralized advantage on the blockchain.&lt;/p&gt;

&lt;p&gt;I believe the solution can implement in many areas, such as National Voting, Exchange Catapult Wallet, Foreigner digital ID border control and etc.&lt;/p&gt;

&lt;p&gt;Read more : &lt;br&gt;
&lt;a href="https://github.com/AnthonyLaw/nem2-multisig-usecase"&gt;Source Code&lt;/a&gt;&lt;br&gt;
&lt;a href="https://medium.com/opening-line/opening-line-inc-bringing-catapult-to-the-masses-287edf36d059"&gt;NEM Catapult Explain By Opening line&lt;/a&gt;&lt;br&gt;
&lt;a href="https://nemtech.github.io/concepts/multisig-account.html"&gt;What is Multisig Account By NEM Tech&lt;/a&gt;&lt;/p&gt;

</description>
      <category>nem</category>
      <category>blockchain</category>
      <category>catapult</category>
      <category>nem2sdk</category>
    </item>
    <item>
      <title>Terraform for Beginner - AWS</title>
      <dc:creator>Anthony Law</dc:creator>
      <pubDate>Sat, 01 Jun 2019 15:52:30 +0000</pubDate>
      <link>https://forem.com/anthonylaw/terraform-for-beginner-jak</link>
      <guid>https://forem.com/anthonylaw/terraform-for-beginner-jak</guid>
      <description>&lt;h1&gt;
  
  
  Learning journey #RoadToDevOps
&lt;/h1&gt;

&lt;p&gt;Last week I pick Terraform as my study and learning topic.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.terraform.io/"&gt;Terraform&lt;/a&gt; are very useful and powerful tools for DevOps development, it allows you writing a plan (Infrastructure as Code) and manage your cloud service.&lt;/p&gt;

&lt;p&gt;which mean you can write a cloud infrastructure in coding, such as define how many instanse services, what port number you should active in the firewall. It's interesting to handling so many servers just a few lines of code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;By using Terrafrom to deploy a virtual machine (ubuntu OS) in AWS EC2.&lt;/p&gt;

&lt;h2&gt;
  
  
  Objectives
&lt;/h2&gt;

&lt;p&gt;In this article, you should able:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Setup AWS account &lt;/li&gt;
&lt;li&gt;Use Basic Terraform-CLI command&lt;/li&gt;
&lt;li&gt;Writing Terraform Language (HCL)&lt;/li&gt;
&lt;li&gt;Deploy Virtual machine (EC2) in AWS cloud.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  AWS Setup
&lt;/h2&gt;

&lt;p&gt;If you are new in AWS please sign up here enjoy &lt;a href="https://aws.amazon.com/free/"&gt;AWS Free Tier&lt;br&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We need User's &lt;code&gt;Access Key ID&lt;/code&gt; and &lt;code&gt;Secret Key ID&lt;/code&gt; from AWS User, and grant promission to &lt;code&gt;User&lt;/code&gt; with &lt;code&gt;AmazonEC2FullAccess&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;if you dont know how to create user -&amp;gt; &lt;a href="https://www.youtube.com/watch?v=XMi5fXL2Hes"&gt;watch this&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Terraform
&lt;/h2&gt;

&lt;p&gt;Ensure your machine are &lt;a href="https://learn.hashicorp.com/terraform/getting-started/install.html"&gt;Install Terraform&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We know if you writing in &lt;code&gt;javascript&lt;/code&gt; programming, you will name the file extension as &lt;code&gt;*.js&lt;/code&gt;. In Terraform the will define the extension as &lt;code&gt;*.tf&lt;/code&gt; and using JSON format or HCL (HashiCorp Configuration Language).&lt;/p&gt;

&lt;p&gt;You may feel strange what is HCL (HashiCorp Configuration Language). No worry, It's not complicated and easy to learn and understand. &lt;a href="https://www.terraform.io/docs/configuration/index.html"&gt;HCL Docs&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once you have done your &lt;code&gt;*.tf&lt;/code&gt; script, you have to use &lt;a href="https://www.terraform.io/docs/commands/index.html"&gt;Terrform-CLI&lt;/a&gt; to execute &lt;code&gt;tf&lt;/code&gt; files.&lt;/p&gt;
&lt;h3&gt;
  
  
  Hands-on
&lt;/h3&gt;

&lt;p&gt;We will use keywords from &lt;code&gt;HCL&lt;/code&gt;.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;keywords&lt;/th&gt;
&lt;th&gt;description&lt;/th&gt;
&lt;th&gt;example&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;provider&lt;/td&gt;
&lt;td&gt;define cloud service provider&lt;/td&gt;
&lt;td&gt;aws, google&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;resource&lt;/td&gt;
&lt;td&gt;define the resource we will use&lt;/td&gt;
&lt;td&gt;aws_instance, google_compute_instance&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;variable&lt;/td&gt;
&lt;td&gt;define variable&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;output&lt;/td&gt;
&lt;td&gt;print output after executed&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;We will use keywords from &lt;code&gt;Terraform CLI&lt;/code&gt;.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;keywords&lt;/th&gt;
&lt;th&gt;description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;init&lt;/td&gt;
&lt;td&gt;To init terraform project in the folder&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;plan&lt;/td&gt;
&lt;td&gt;To evaluate current your infrastructure from &lt;code&gt;*.tf&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;apply&lt;/td&gt;
&lt;td&gt;To add all define resources.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;show&lt;/td&gt;
&lt;td&gt;To list resource infomation and current state&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;destroy&lt;/td&gt;
&lt;td&gt;To remove all defined resources.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h3&gt;
  
  
  start
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Create a folder in your machine.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;create a files &lt;code&gt;my-first-vm.tf&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Open the files in the editor and start code.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;&lt;span class="c1"&gt;# my-first-vm.tf&lt;/span&gt;

&lt;span class="c1"&gt;# We are pointing "aws" as our provider.&lt;/span&gt;

&lt;span class="k"&gt;provider&lt;/span&gt; &lt;span class="s2"&gt;"aws"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;region&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"ap-southeast-1"&lt;/span&gt;
    &lt;span class="nx"&gt;access_key&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&amp;lt;access-key-from-aws-user&amp;gt;"&lt;/span&gt;
    &lt;span class="nx"&gt;secret_key&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&amp;lt;secret-key-from-aws-user&amp;gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;terraform init

Initializing provider plugins...

The following providers &lt;span class="k"&gt;do &lt;/span&gt;not have any version constraints &lt;span class="k"&gt;in &lt;/span&gt;configuration,
so the latest version was installed.

&lt;span class="k"&gt;*&lt;/span&gt; provider.aws: version &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"~&amp;gt; 2.12"&lt;/span&gt;

Terraform has been successfully initialized!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;append resource "aws_instance" in &lt;code&gt;my-first-vm.tf&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;&lt;span class="k"&gt;provider&lt;/span&gt; &lt;span class="s2"&gt;"aws"&lt;/span&gt; &lt;span class="p"&gt;{...}&lt;/span&gt;

&lt;span class="k"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_instance"&lt;/span&gt; &lt;span class="s2"&gt;"ec2"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;# I called name "ec2", you can change it&lt;/span&gt;
  &lt;span class="nx"&gt;ami&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"ami-0dad20bd1b9c8c004"&lt;/span&gt; &lt;span class="c1"&gt;# Image: Ubuntu Server 18.04 LTS (HVM), SSD Volume Type&lt;/span&gt;
  &lt;span class="nx"&gt;instance_type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"t2.micro"&lt;/span&gt; &lt;span class="c1"&gt;# VM Spec&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;terraform plan

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  + aws_instance.ec2
      &lt;span class="nb"&gt;id&lt;/span&gt;:                           &amp;lt;computed&amp;gt;
      ami:                          &lt;span class="s2"&gt;"0dad20bd1b9c8c004"&lt;/span&gt;
      arn:                          &amp;lt;computed&amp;gt;
      associate_public_ip_address:  &amp;lt;computed&amp;gt;
      availability_zone:            &amp;lt;computed&amp;gt;
      cpu_core_count:               &amp;lt;computed&amp;gt;
      cpu_threads_per_core:         &amp;lt;computed&amp;gt;
      ebs_block_device.#:           &amp;lt;computed&amp;gt;
      ephemeral_block_device.#:     &amp;lt;computed&amp;gt;
      get_password_data:            &lt;span class="s2"&gt;"false"&lt;/span&gt;
      host_id:                      &amp;lt;computed&amp;gt;
      instance_state:               &amp;lt;computed&amp;gt;
      instance_type:                &lt;span class="s2"&gt;"t2.micro"&lt;/span&gt;
      ipv6_address_count:           &amp;lt;computed&amp;gt;
      ipv6_addresses.#:             &amp;lt;computed&amp;gt;
      key_name:                     &amp;lt;computed&amp;gt;
      network_interface.#:          &amp;lt;computed&amp;gt;
      network_interface_id:         &amp;lt;computed&amp;gt;
      password_data:                &amp;lt;computed&amp;gt;
      placement_group:              &amp;lt;computed&amp;gt;
      primary_network_interface_id: &amp;lt;computed&amp;gt;
      private_dns:                  &amp;lt;computed&amp;gt;
      private_ip:                   &amp;lt;computed&amp;gt;
      public_dns:                   &amp;lt;computed&amp;gt;
      public_ip:                    &amp;lt;computed&amp;gt;
      root_block_device.#:          &amp;lt;computed&amp;gt;
      security_groups.#:            &amp;lt;computed&amp;gt;
      source_dest_check:            &lt;span class="s2"&gt;"true"&lt;/span&gt;
      subnet_id:                    &amp;lt;computed&amp;gt;
      tenancy:                      &amp;lt;computed&amp;gt;
      volume_tags.%:                &amp;lt;computed&amp;gt;
      vpc_security_group_ids.#:     &amp;lt;computed&amp;gt;


Plan: 1 to add, 0 to change, 0 to destroy.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;it showing infrastructure going to execute, you will see &lt;code&gt;computed&lt;/code&gt; it's because the terraform will help you assign the value, if you are not defined.&lt;/p&gt;

&lt;p&gt;In additional, you see &lt;code&gt;Plan: 1 to add, 0 to change, 0 to destroy.&lt;/code&gt; it mean 1 resource will be executed.&lt;/p&gt;

&lt;p&gt;So in this stage, actually you already completed setup an instance.&lt;/p&gt;

&lt;p&gt;command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;terraform apply
Terraform will perform the following actions:

  + aws_instance.ec2

...

Plan: 1 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only &lt;span class="s1"&gt;'yes'&lt;/span&gt; will be accepted to approve.

  Enter a value: &lt;span class="nb"&gt;yes&lt;/span&gt;

...

aws_instance.ec2: Still creating... &lt;span class="o"&gt;(&lt;/span&gt;10s elapsed&lt;span class="o"&gt;)&lt;/span&gt;
aws_instance.ec2: Still creating... &lt;span class="o"&gt;(&lt;/span&gt;20s elapsed&lt;span class="o"&gt;)&lt;/span&gt;
aws_instance.ec2: Creation &lt;span class="nb"&gt;complete &lt;/span&gt;after 22s &lt;span class="o"&gt;(&lt;/span&gt;ID: i-083d6c6c7b01d1640&lt;span class="o"&gt;)&lt;/span&gt;

Apply &lt;span class="nb"&gt;complete&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; Resources: 1 added, 0 changed, 0 destroyed.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Congratulations, you are successful setup an instance EC2 in AWS, you may login and check it out in AWS dashboard.&lt;/p&gt;

&lt;p&gt;Try on this command to get resource infomation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;terraform show 

aws_instance.ec2:
  &lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; i-083d6c6c7b01d1640
  ami &lt;span class="o"&gt;=&lt;/span&gt; ami-0dad20bd1b9c8c004
  arn &lt;span class="o"&gt;=&lt;/span&gt; arn:aws:ec2:ap-southeast-1:907443295242:instance/i-083d6c6c7b01d1640
  associate_public_ip_address &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt;
...
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;!!!!&lt;/p&gt;

&lt;p&gt;But wait, how you able to access without setup &lt;code&gt;ssh&lt;/code&gt; in the firewall.&lt;/p&gt;

&lt;p&gt;let append resource "aws_security_group" in &lt;code&gt;my-first-vm.tf&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;&lt;span class="k"&gt;provider&lt;/span&gt; &lt;span class="s2"&gt;"aws"&lt;/span&gt; &lt;span class="p"&gt;{...}&lt;/span&gt;

&lt;span class="k"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_instance"&lt;/span&gt; &lt;span class="s2"&gt;"ec2"&lt;/span&gt; &lt;span class="p"&gt;{...}&lt;/span&gt;

&lt;span class="c1"&gt;# Setup aws_security_group with SSH access&lt;/span&gt;

&lt;span class="k"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_security_group"&lt;/span&gt; &lt;span class="s2"&gt;"allow_ssh"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"allow ssh"&lt;/span&gt;
  &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"only ssh"&lt;/span&gt;

  &lt;span class="nx"&gt;ingress&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;from_port&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;
    &lt;span class="nx"&gt;to_port&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;
    &lt;span class="nx"&gt;protocol&lt;/span&gt;    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"TCP"&lt;/span&gt;
    &lt;span class="nx"&gt;cidr_blocks&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"0.0.0.0/0"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;egress&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;from_port&lt;/span&gt;       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="nx"&gt;to_port&lt;/span&gt;         &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="nx"&gt;protocol&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"-1"&lt;/span&gt;
    &lt;span class="nx"&gt;cidr_blocks&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"0.0.0.0/0"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we have let our "ec2" instance to apply "aws_security_group" we define, and also assign keypair for the instance.&lt;/p&gt;

&lt;p&gt;so we can use the &lt;code&gt;keypair&lt;/code&gt; to access instance with port &lt;code&gt;ssh 22&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;if you dont know how to create keypair in AWS, &lt;a href="https://www.youtube.com/watch?v=DpyLAdMD09w"&gt;watch this&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;&lt;span class="k"&gt;provider&lt;/span&gt; &lt;span class="s2"&gt;"aws"&lt;/span&gt; &lt;span class="p"&gt;{...}&lt;/span&gt;

&lt;span class="k"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_instance"&lt;/span&gt; &lt;span class="s2"&gt;"ec2"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;# I called name "ec2", you can change it&lt;/span&gt;
  &lt;span class="nx"&gt;ami&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"ami-0dad20bd1b9c8c004"&lt;/span&gt; &lt;span class="c1"&gt;# Image: Ubuntu Server 18.04 LTS (HVM), SSD Volume Type&lt;/span&gt;
  &lt;span class="nx"&gt;instance_type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"t2.micro"&lt;/span&gt; &lt;span class="c1"&gt;# VM Spec&lt;/span&gt;
  &lt;span class="nx"&gt;security_groups&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;aws_security_group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;allow_ssh&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="nx"&gt;key_name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"aws-anthony"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Setup aws_security_group with SSH access&lt;/span&gt;

&lt;span class="k"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_security_group"&lt;/span&gt; &lt;span class="s2"&gt;"allow_ssh"&lt;/span&gt; &lt;span class="p"&gt;{...}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;terraform apply
aws_instance.ec2: Refreshing state... &lt;span class="o"&gt;(&lt;/span&gt;ID: i-083d6c6c7b01d1640&lt;span class="o"&gt;)&lt;/span&gt;

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create
-/+ destroy and &lt;span class="k"&gt;then &lt;/span&gt;create replacement

Terraform will perform the following actions:

-/+ aws_instance.ec2 &lt;span class="o"&gt;(&lt;/span&gt;new resource required&lt;span class="o"&gt;)&lt;/span&gt;
...
...

+ aws_security_group.allow_ssh
...
...

Plan: 2 to add, 0 to change, 1 to destroy.
...
...
...
aws_instance.ec2: Still creating... &lt;span class="o"&gt;(&lt;/span&gt;10s elapsed&lt;span class="o"&gt;)&lt;/span&gt;
aws_instance.ec2: Still creating... &lt;span class="o"&gt;(&lt;/span&gt;20s elapsed&lt;span class="o"&gt;)&lt;/span&gt;
aws_instance.ec2: Creation &lt;span class="nb"&gt;complete &lt;/span&gt;after 32s &lt;span class="o"&gt;(&lt;/span&gt;ID: i-079e9b8c1d98e4af5&lt;span class="o"&gt;)&lt;/span&gt;

Apply &lt;span class="nb"&gt;complete&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; Resources: 2 added, 0 changed, 1 destroyed.

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You may see it's different from just now, because terraform will keep track all resource status in &lt;code&gt;*.tfstate&lt;/code&gt;.&lt;br&gt;
So it shows that, it will &lt;code&gt;destroy&lt;/code&gt; the previous instance and recreate again.&lt;/p&gt;

&lt;p&gt;great, you now can check it out in your AWS dashboard. &lt;/p&gt;

&lt;p&gt;finally, you successfully create an instance in Ubuntu OS. It's trouble to login AWS dashboard and checking what is the instance public ip address.&lt;/p&gt;

&lt;p&gt;you may use &lt;code&gt;output&lt;/code&gt; keywords to display the public IP address.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;&lt;span class="k"&gt;provider&lt;/span&gt; &lt;span class="s2"&gt;"aws"&lt;/span&gt; &lt;span class="p"&gt;{...}&lt;/span&gt;

&lt;span class="k"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_instance"&lt;/span&gt; &lt;span class="s2"&gt;"ec2"&lt;/span&gt; &lt;span class="p"&gt;{...}&lt;/span&gt;

&lt;span class="k"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_security_group"&lt;/span&gt; &lt;span class="s2"&gt;"allow_ssh"&lt;/span&gt; &lt;span class="p"&gt;{...}&lt;/span&gt;

&lt;span class="k"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"showPublicIP"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;aws_instance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ec2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;public_dns&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;terraform apply 

aws_security_group.allow_ssh: Refreshing state... &lt;span class="o"&gt;(&lt;/span&gt;ID: sg-0ca7e9133a701f216&lt;span class="o"&gt;)&lt;/span&gt;
aws_instance.ec2: Refreshing state... &lt;span class="o"&gt;(&lt;/span&gt;ID: i-079e9b8c1d98e4af5&lt;span class="o"&gt;)&lt;/span&gt;

Apply &lt;span class="nb"&gt;complete&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; Resources: 0 added, 0 changed, 0 destroyed.

Outputs:

showPublicIP &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;
    ec2-3-0-184-126.ap-southeast-1.compute.amazonaws.com
&lt;span class="o"&gt;]&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh &lt;span class="nt"&gt;-i&lt;/span&gt; aws-anthony.pem ubuntu@ec2-3-0-184-126.ap-southeast-1.compute.amazonaws.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Terraform always execute the &lt;code&gt;*tf&lt;/code&gt; in folder, each infrastructure should create a folder, such as &lt;code&gt;aws-instance&lt;/code&gt; or &lt;code&gt;google-instance&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;if you feel put everything in 1 &lt;code&gt;.tf&lt;/code&gt; file is to mess, you may seperate in different &lt;code&gt;.tf&lt;/code&gt; such as aws_provider.tf , aws_security.tf&lt;/p&gt;

&lt;p&gt;&lt;a href="https://gist.github.com/AnthonyLaw/0738a40d9f7e46111f6d670aa7684fdc"&gt;example code&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/AnthonyLaw/terraform-starter-pack"&gt;store sepearte example&lt;/a&gt;&lt;/p&gt;

</description>
      <category>devops</category>
      <category>aws</category>
    </item>
  </channel>
</rss>
