<?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>DEV Community: José Diogo Viana</title>
    <description>The latest articles on DEV Community by José Diogo Viana (@zediogoviana).</description>
    <link>https://dev.to/zediogoviana</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%2F516892%2F51fcdfd6-09da-409e-a06c-7aecfb8a251d.jpeg</url>
      <title>DEV Community: José Diogo Viana</title>
      <link>https://dev.to/zediogoviana</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/zediogoviana"/>
    <language>en</language>
    <item>
      <title>Sign in with Metamask using LiveView</title>
      <dc:creator>José Diogo Viana</dc:creator>
      <pubDate>Fri, 05 May 2023 09:38:24 +0000</pubDate>
      <link>https://dev.to/finiam/sign-in-with-metamask-using-liveview-28b3</link>
      <guid>https://dev.to/finiam/sign-in-with-metamask-using-liveview-28b3</guid>
      <description>&lt;p&gt;There's a chance that you have heard of &lt;a href="https://metamask.io/"&gt;&lt;em&gt;Metamask&lt;/em&gt;&lt;/a&gt; in the past year or two. But, if you haven't, don't worry, as I'll try to explain it quickly. &lt;em&gt;Metamask&lt;/em&gt; is an &lt;a href="https://ethereum.org/en/"&gt;&lt;em&gt;Ethereum&lt;/em&gt;&lt;/a&gt; crypto wallet, and serves as a gateway to &lt;em&gt;dApps&lt;/em&gt; (decentralized Apps). &lt;em&gt;Coinbase&lt;/em&gt; has the following definition for a crypto wallet:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Crypto wallets store your private keys, keeping your crypto safe and accessible. They also allow you to send, receive, and spend cryptocurrencies like Bitcoin and Ethereum.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For a more complete explanation, I recommend reading &lt;a href="https://www.coinbase.com/learn/crypto-basics/what-is-a-crypto-wallet"&gt;their full blog post&lt;/a&gt;, but for the ones that won't read it, I want to highlight that &lt;em&gt;Metamask&lt;/em&gt; is just one option between several existing &lt;strong&gt;Hot Wallets (Online Wallets)&lt;/strong&gt;. However, for various reasons that don't matter here, &lt;em&gt;Metamask&lt;/em&gt; grew into one of the most used wallets. &lt;/p&gt;

&lt;p&gt;The main idea of my discussion today is not limited to the &lt;em&gt;Metamask&lt;/em&gt; wallet only but can be applied to any other wallet as well. However, you'd need to adjust the code a bit for other wallets, as they may handle &lt;em&gt;Javascript&lt;/em&gt; events differently. If you want to support multiple wallets in your &lt;em&gt;dApp&lt;/em&gt; instead of doing all the manual work for each one individually, it's probably best to look into things like &lt;a href="https://www.rainbowkit.com/"&gt;RainbowKit&lt;/a&gt;, &lt;a href="https://wagmi.sh/"&gt;wagmi&lt;/a&gt;, etc.&lt;/p&gt;

&lt;p&gt;My teammate &lt;a href="https://github.com/davelange"&gt;David Lange&lt;/a&gt; did an awesome talk for &lt;a href="https://twitter.com/coimblockchain?lang=en"&gt;Coimbra.Blockchain&lt;/a&gt; where he talks about some of the hurdles and tools to use when developing a frontend for a &lt;em&gt;dApp&lt;/em&gt;. I definitely recommend watching &lt;a href="https://www.youtube.com/live/qqlRjpXY_Pc?feature=share&amp;amp;t=256"&gt;the presentation video&lt;/a&gt;. (It takes about 40 minutes.)&lt;/p&gt;

&lt;h2&gt;
  
  
  Why is it relevant?
&lt;/h2&gt;

&lt;p&gt;By using a solution such as &lt;code&gt;Sign in with Metamask&lt;/code&gt; (or any other wallet, as highlighted before) the user doesn't need to worry about an extra &lt;code&gt;username + password&lt;/code&gt; combo for our App. Yes, I know that there are password managers, and it makes these worries a bit redundant, but let's be honest... End users of these apps don't want to trust us with their emails and passwords, even if they are random. Also, they already need to have a wallet to interact with other Blockchain features, so we might as well take advantage of that.&lt;/p&gt;

&lt;p&gt;This can be used as a reliable authentication method because we know that only the person with access to that wallet's private key will be able to cryptographically sign a message, that when verified it'll correspond to the public key. &lt;strong&gt;Side note: in Ethereum, and some other blockchains, the public key corresponds to the &lt;em&gt;Wallet's Address&lt;/em&gt;.&lt;/strong&gt; We'll see below how this works with a bit more detail.&lt;/p&gt;

&lt;h2&gt;
  
  
  How does it work?
&lt;/h2&gt;

&lt;p&gt;If you are still here, then I'm going to assume that you're familiar with how &lt;strong&gt;Asymmetric Encryption&lt;/strong&gt; works (read &lt;a href="https://www.babypips.com/crypto/learn/what-is-asymmetric-encryption"&gt;this post&lt;/a&gt; if not).&lt;/p&gt;

&lt;p&gt;The image below tries to represent how a crypto wallet can be used as a valid sign-in mechanism. The application's backend gives the User a message to sign with the wallet's private key. The backend then receives the encrypted message and uses the Wallet's Public Key (its Address, for Ethereum) to decrypt it and verify it against the original one.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7iQAKi60--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.sanity.io/images/5aprln8a/production/6896ce3bd0deef7a875a6fc54d8457a5d9b120ba-716x361.png%3Fw%3D450" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7iQAKi60--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.sanity.io/images/5aprln8a/production/6896ce3bd0deef7a875a6fc54d8457a5d9b120ba-716x361.png%3Fw%3D450" alt="sign in with wallet" width="450" height="227"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Some of the more trained eyes may have seen a possible issue with the scheme above. Bear with me for a little more, because I'm going to address it in some paragraphs below.&lt;/p&gt;

&lt;p&gt;An &lt;strong&gt;important note&lt;/strong&gt; for this blog post is that the flow I'm talking about is for situations where we have a dedicated backend, and we want to maintain some kind of session between our App and the User. It's very frequent to have &lt;em&gt;dApps&lt;/em&gt; that don't need a dedicated backend, so the User just connects its Wallet to the frontend, and can then interact directly with Smart Contracts running in the blockchain.&lt;/p&gt;

&lt;p&gt;In the same way, &lt;code&gt;Metamask&lt;/code&gt; gives you an interface to make transactions in the blockchain, it also allows the User to just sign simple text messages, using their private keys. The following image is one example. This action is completely off-chain, so therefore it doesn't have associated costs or delays.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4Q6XVTcP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.sanity.io/images/5aprln8a/production/f2ba908431467adc0e935632b2016e0437969924-499x684.png%3Fw%3D450" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4Q6XVTcP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.sanity.io/images/5aprln8a/production/f2ba908431467adc0e935632b2016e0437969924-499x684.png%3Fw%3D450" alt="metamask signature request example" width="450" height="617"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Elixir and Liveview?
&lt;/h2&gt;

&lt;p&gt;Well, why not? That's a valid reason, but I like to think that I have a more elaborate answer for this. To start, most projects in the Web3/Crypto space have separate frontends from the backend (at least the ones that have a dedicated backend). The reason for this is mainly because there are a lot of tools that can help with quick development if using any modern Javascript Framework. &lt;/p&gt;

&lt;p&gt;In my case, I just wanted to do a simple &lt;strong&gt;API Playground&lt;/strong&gt; where any user could interact with the &lt;a href="https://dora-the-tipset-explorer.fly.dev/"&gt;project I was working on&lt;/a&gt;, but where it'd be possible to have an authenticated place. The API was all built with &lt;em&gt;Elixir&lt;/em&gt;, and &lt;em&gt;Phoenix 1.7&lt;/em&gt; was a couple of days from being released, so I decided to take the opportunity and do something using &lt;em&gt;LiveView&lt;/em&gt;, and have a learning experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  A look into the desired Flow
&lt;/h2&gt;

&lt;p&gt;I can't say I have used many crypto Wallets, but most of them work pretty much the same way. Before interacting with a &lt;em&gt;dApp&lt;/em&gt;, you first need to connect the wallet to that website. I'll explain better what this is, down the line, but it's a required step regardless if you want the app to trigger any action from the wallet.&lt;/p&gt;

&lt;p&gt;Focusing only on our goal of implementing a &lt;strong&gt;Sign In with Metamask&lt;/strong&gt; flow, the base flow should look like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Connect the wallet;&lt;/li&gt;
&lt;li&gt;Sign a message;&lt;/li&gt;
&lt;li&gt;Validate the signature on the backend;&lt;/li&gt;
&lt;li&gt;Create a Session token, if the signature is valid.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Above, we have already seen how we can sign messages using &lt;em&gt;Metamask&lt;/em&gt;, but there is a problem with the flow I described... In that example, the user signs a message saying &lt;code&gt;Here is a message!&lt;/code&gt;, and then the backend validates the signature, checking if it matches the original message. Even if you don't know much about cryptography, you can understand that if you always sign the same message contents, the resulting signature is the same, also. So, if your key is &lt;code&gt;A&lt;/code&gt; and you are signing &lt;code&gt;B&lt;/code&gt;, the final signature is always &lt;code&gt;C&lt;/code&gt;. This way, if an attacker can intercept the Signature going from &lt;em&gt;Metamask&lt;/em&gt; to the backend, then it'd be able to impersonate the actual wallet owner and sign in with our Application because the signature would be valid!&lt;/p&gt;

&lt;p&gt;To solve that problem, we need to have a &lt;code&gt;Nonce&lt;/code&gt; associated with each User in the database. With it, we make sure that every time a user is signing a message to log in to our app, that message has an extra number/string to make it different every time, therefore resulting in different signatures. Then, as our backend knows the base message, and the &lt;code&gt;nonce&lt;/code&gt; given to the respective user trying to sign in, it's still possible to fully validate if the signature is valid or not.&lt;/p&gt;

&lt;p&gt;All good up until now? It's time to dive into some code and see how all of this glues together.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting our hands dirty
&lt;/h2&gt;

&lt;p&gt;The first step I took was to look for existing examples using &lt;em&gt;Elixir&lt;/em&gt; and &lt;em&gt;LiveView&lt;/em&gt;. I end up finding &lt;a href="https://www.youtube.com/watch?v=YzB0-8syuTU"&gt;this interesting presentation&lt;/a&gt;, by Crystal Adkins, talking about what I wanted to learn about! The presentation links to the respective &lt;a href="https://github.com/revelrylabs/liveview_web3/tree/presentation"&gt;Github Repo&lt;/a&gt; of the project demonstrated during it. After exploring for a bit, I was able to understand how the interactions between &lt;em&gt;LiveView&lt;/em&gt; and &lt;em&gt;Metamask&lt;/em&gt; worked through JS, so I started working on my own version of the code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; There are some differences between the project presented by Crystal Adkins and our use case. For example, you first had to sign in/up using email and password, and only then you could associate and connect &lt;em&gt;Metamask&lt;/em&gt; with your account. In that codebase, you always sign the same message (the problem I mentioned), but I assume that it was just a Proof of Concept of the capabilities of &lt;em&gt;LiveView&lt;/em&gt;. The same project also did more complex stuff like actually interacting with Smart Contracts, something that I'm not talking about today, and it wouldn't be present in our situation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Second Note:&lt;/strong&gt; The message structure being signed in my version, doesn't follow any &lt;a href="https://eips.ethereum.org/"&gt;Ethereum Improvement Proposals (EIPs)&lt;/a&gt; like &lt;a href="https://eips.ethereum.org/EIPS/eip-4361"&gt;EIP-4361&lt;/a&gt;. EIPs describe standards for the Ethereum platform, including core protocol specifications, client APIs, and contract standards. To implement something like that, you'd just need to change the message contents and add more information for User signing it.&lt;/p&gt;

&lt;p&gt;To manage sessions and all the corresponding logic, I decided to use the &lt;code&gt;mix phx.gen.auth Accounts User users&lt;/code&gt; generator, and remove all of the unwanted parts (like account confirmation, reset password flows, etc...). It's a pretty standard approach and works just fine.&lt;/p&gt;

&lt;p&gt;Then I started the actual implementation of the &lt;strong&gt;Sign In&lt;/strong&gt; button. This button is a &lt;em&gt;LiveView&lt;/em&gt; component, and has the following &lt;code&gt;mount&lt;/code&gt; function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;DoraWeb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;MetamaskButtonLive&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="no"&gt;DoraWeb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:live_view&lt;/span&gt;

  &lt;span class="nv"&gt;@impl&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;mount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_params&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_session&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="n"&gt;assign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="ss"&gt;connected:&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="ss"&gt;current_wallet_address:&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="ss"&gt;signature:&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="ss"&gt;verify_signature:&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;
     &lt;span class="p"&gt;)}&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="c1"&gt;# render logic and event handlers...&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Looking at the &lt;code&gt;assigns&lt;/code&gt; and explaining what each of them represents, is very simple:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;connected&lt;/code&gt;: if the &lt;em&gt;Metamask&lt;/em&gt; Wallet is already connected to our website or not. (The connect thing, I mentioned before). We can get this information from &lt;code&gt;window.ethereum&lt;/code&gt;, and I'll explain what it is, next.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;current_wallet_address&lt;/code&gt;: if the Wallet is already connected, or the User just connected, we can retrieve which Address it corresponds to. (Don't forget that here the Address is also the Public Key.)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;signature&lt;/code&gt;: after triggering a signing request, this &lt;code&gt;assign&lt;/code&gt; will hold the signature to be sent to the backend, for verification.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;verify-signature&lt;/code&gt;: is supposed to work as a flag to trigger the verification process or not.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The render function is also understandable at first look. If we have &lt;code&gt;@connected&lt;/code&gt; as true, then we can render the &lt;code&gt;Sign In&lt;/code&gt; message, trigger a new Signature Request, and then the respective verification. If &lt;code&gt;@connected&lt;/code&gt; is false, then we render &lt;code&gt;Connect&lt;/code&gt;, and clicking on the button triggers the Wallet connection, instead.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="nv"&gt;@impl&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;assigns&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="sx"&gt;~H""&lt;/span&gt;&lt;span class="s2"&gt;"
  &amp;lt;span title="&lt;/span&gt;&lt;span class="no"&gt;Metamask&lt;/span&gt;&lt;span class="s2"&gt;" id="&lt;/span&gt;&lt;span class="n"&gt;metamask&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;button&lt;/span&gt;&lt;span class="s2"&gt;" phx-hook="&lt;/span&gt;&lt;span class="no"&gt;Metamask&lt;/span&gt;&lt;span class="s2"&gt;"&amp;gt;
    &amp;lt;%= if @connected do %&amp;gt;
      &amp;lt;.form
        for={%{}}
        action={~p"&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;log_in&lt;/span&gt;&lt;span class="s2"&gt;"}
        as={:user}
        phx-submit="&lt;/span&gt;&lt;span class="n"&gt;verify&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;current&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;wallet&lt;/span&gt;&lt;span class="s2"&gt;"
        phx-trigger-action={@verify_signature}
      &amp;gt;
        &amp;lt;.input type="&lt;/span&gt;&lt;span class="n"&gt;hidden&lt;/span&gt;&lt;span class="s2"&gt;" name="&lt;/span&gt;&lt;span class="n"&gt;public_address&lt;/span&gt;&lt;span class="s2"&gt;" value={@current_wallet_address} /&amp;gt;
        &amp;lt;.input type="&lt;/span&gt;&lt;span class="n"&gt;hidden&lt;/span&gt;&lt;span class="s2"&gt;" name="&lt;/span&gt;&lt;span class="n"&gt;signature&lt;/span&gt;&lt;span class="s2"&gt;" value={@signature} /&amp;gt;
        &amp;lt;.button class={button_css()}&amp;gt;
          &amp;lt;span class="&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="s2"&gt;"&amp;gt;&amp;lt;.metamask_icon /&amp;gt;&amp;lt;/span&amp;gt; Sign in
        &amp;lt;/.button&amp;gt;
      &amp;lt;/.form&amp;gt;
    &amp;lt;% else %&amp;gt;
      &amp;lt;.button class={button_css()} phx-click="&lt;/span&gt;&lt;span class="n"&gt;connect&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;metamask&lt;/span&gt;&lt;span class="s2"&gt;"&amp;gt;
        &amp;lt;span class="&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="s2"&gt;"&amp;gt;&amp;lt;.metamask_icon /&amp;gt;&amp;lt;/span&amp;gt; Connect
      &amp;lt;/.button&amp;gt;
    &amp;lt;% end %&amp;gt;
  &amp;lt;/span&amp;gt;
  """&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's start by inspecting &lt;code&gt;phx-click="connect-metamask"&lt;/code&gt; for the case where the Wallet is not connected. It relies on the &lt;code&gt;push_event&lt;/code&gt; function. It's a small function, but very powerful in that way that enables us to easily communicate with the Javascript side of the App, by &lt;a href="https://hexdocs.pm/phoenix_live_view/Phoenix.LiveView.html#push_event/3"&gt;pushing an event to the client&lt;/a&gt;, and where we can interact directly with &lt;em&gt;Metamask&lt;/em&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="nv"&gt;@impl&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;handle_event&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"connect-metamask"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_params&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:noreply&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;push_event&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"connect-metamask"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;%{})}&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  How to interact with &lt;em&gt;Metamask&lt;/em&gt; from Javascript?
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;MetaMask&lt;/em&gt; injects a global API into websites visited by its users at &lt;code&gt;window.ethereum&lt;/code&gt;. This API allows websites to request users' Ethereum accounts, read data from blockchains the user is connected to, and suggest that the user sign messages and transactions. &lt;/p&gt;

&lt;p&gt;Consequently, to interact with &lt;code&gt;window.ethereum&lt;/code&gt;, we have Javascript libraries like &lt;a href="https://docs.ethers.org/v5/getting-started/"&gt;Ethers&lt;/a&gt; or &lt;a href="https://web3js.readthedocs.io/en/v1.8.2/"&gt;web3.js&lt;/a&gt;. I end up using &lt;code&gt;Ethers&lt;/code&gt;, but you can select whatever you see fit. To handle the event above, you need something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;web3Provider&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;ethers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;providers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Web3Provider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ethereum&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`phx:connect-metamask`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;web3Provider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;eth_requestAccounts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;accounts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;accounts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;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;signer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getAddress&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;then&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pushEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;wallet-connected&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;public_address&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="p"&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;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&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;Upon successful connection of the Wallet, a new event &lt;code&gt;"wallet-connected"&lt;/code&gt; is pushed with the respectively connected address. We can handle this event in our &lt;em&gt;LiveView&lt;/em&gt; file, just like any other emitted by our template. When receiving that event, we set &lt;code&gt;@connected&lt;/code&gt; to its new state, and we also update &lt;code&gt;@current_wallet_address&lt;/code&gt;. By changing these two &lt;code&gt;assigns&lt;/code&gt; the button will now render a different thing entirely because the Wallet is already connected to our app.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="nv"&gt;@impl&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;handle_event&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"wallet-connected"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:noreply&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="n"&gt;assign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="ss"&gt;connected:&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;is_nil&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"public_address"&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;
     &lt;span class="ss"&gt;current_wallet_address:&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"public_address"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
   &lt;span class="p"&gt;)}&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since we are already connected, when clicking our new button, the event emitted when trying to submit the form is &lt;code&gt;phx-submit="verify-current-wallet"&lt;/code&gt;. Even though this form is a post to &lt;code&gt;~p"/users/log_in"&lt;/code&gt;, this action will only be triggered when &lt;code&gt;@verify_signature&lt;/code&gt; is true, due to &lt;code&gt;phx-trigger-action={@verify_signature}&lt;/code&gt; (check the &lt;a href="https://hexdocs.pm/phoenix_live_view/form-bindings.html#submitting-the-form-action-over-http"&gt;&lt;code&gt;px-trigger-action&lt;/code&gt; docs&lt;/a&gt; for more info on how it works).&lt;/p&gt;

&lt;p&gt;The handler for this event looks for an existing account to return its current &lt;code&gt;nonce&lt;/code&gt;, or if an account for that Address doesn't exist, then it generates a new &lt;code&gt;nonce&lt;/code&gt; in the spot. This way, we don't distinguish if a User trying to sign a message to log in will have a valid account or not (the process will fail later instead). This &lt;code&gt;nonce&lt;/code&gt; is then pushed to the Javascript client side and will be used for the signing process.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="nv"&gt;@impl&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;handle_event&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"verify-current-wallet"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_params&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;nonce&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="no"&gt;Accounts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_user_by_eth_address&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assigns&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;current_wallet_address&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Accounts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;generate_account_nonce&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nonce&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:noreply&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;push_event&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"get-current-wallet"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;nonce:&lt;/span&gt; &lt;span class="n"&gt;nonce&lt;/span&gt;&lt;span class="p"&gt;})}&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Javascript code is actually very similar, and through &lt;code&gt;signer.signMessage(message)&lt;/code&gt; a window, similar to the image shown in the introduction part, will appear and the User will be able to sign that message. If the user ends up signing the message, we can push a new event with the result in the payload, and listen to it on the &lt;em&gt;LiveView&lt;/em&gt; component side.&lt;/p&gt;

&lt;p&gt;As a separate note, there are several events triggered by &lt;em&gt;Metamask&lt;/em&gt; (and not our app) that you can also listen to, and make everything feel even snappier. I didn't dive into details, but &lt;a href="https://docs.metamask.io/guide/ethereum-provider.html#table-of-contents"&gt;here&lt;/a&gt; you can find docs for API description and the full list of events.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`phx:get-current-wallet`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;signer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getAddress&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;then&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="o"&gt;=&amp;gt;&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;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`You are signing this message to sign in with Dora. Nonce: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;detail&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="s2"&gt;`&lt;/span&gt;

        &lt;span class="nx"&gt;signer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;signMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;signature&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pushEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;verify-signature&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;public_address&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="na"&gt;signature&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;signature&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;

            &lt;span class="k"&gt;return&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;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, the event pushed by &lt;em&gt;Javascript&lt;/em&gt; is handled again on the &lt;em&gt;LiveView&lt;/em&gt; Component, and &lt;code&gt;@verify_signature&lt;/code&gt; is marked as &lt;code&gt;true&lt;/code&gt;. This way, the form submission is triggered at this time, and the post to &lt;code&gt;~p"/users/log_in"&lt;/code&gt; is done.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="nv"&gt;@impl&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;handle_event&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"verify-signature"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:noreply&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="n"&gt;assign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="ss"&gt;signature:&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"signature"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
     &lt;span class="ss"&gt;verify_signature:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
   &lt;span class="p"&gt;)}&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On the Session controller's side, we receive the form params (&lt;code&gt;public_address&lt;/code&gt; and &lt;code&gt;signature&lt;/code&gt;), and we verify the signature. If it's valid we call &lt;code&gt;UserAuth.log_in_user(user, params)&lt;/code&gt;, if it's not, we redirect back to &lt;code&gt;~p"/"&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To verify the User's signature, &lt;a href="https://hexdocs.pm/ex_web3_ec_recover/0.1.0/ExWeb3EcRecover.html"&gt;&lt;code&gt;ExWeb3EcRecover&lt;/code&gt;&lt;/a&gt; is being used. This is a "simple" library that exports one function &lt;code&gt;recover_personal_signature/2&lt;/code&gt;. This function returns the address that created the signature for a personally signed message by an Ethereum Wallet. So, in our case, we can reconstruct the original messages by the User (we have its &lt;code&gt;nonce&lt;/code&gt; stored in the DB still), and then we check if the Address trying to sign in with that signature is the same that signed the message in the first place. If so, we update the &lt;code&gt;nonce&lt;/code&gt; to a new random value, and we return the &lt;code&gt;user&lt;/code&gt; model as success.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;verify_message_signature&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;eth_address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;signature&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;%&lt;/span&gt;&lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;find_user_by_public_address&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;eth_address&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"You are signing this message to sign in with Dora. Nonce: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nonce&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

    &lt;span class="n"&gt;signing_address&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;ExWeb3EcRecover&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;recover_personal_signature&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;signature&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="no"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;downcase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;signing_address&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="no"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;downcase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;eth_address&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;update_user_nonce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;eth_address&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="n"&gt;user&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;ExWeb3EcRecover&lt;/code&gt; depends on &lt;a href="https://hexdocs.pm/ex_keccak/ExKeccak.html"&gt;&lt;code&gt;ex_keccak&lt;/code&gt;&lt;/a&gt;, which means you'll need to have &lt;em&gt;Rust&lt;/em&gt; installed to compile it. For a quick and easy &lt;em&gt;Rust&lt;/em&gt; install follow &lt;a href="https://www.rust-lang.org/tools/install"&gt;these instructions&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;As you probably have noticed, in our flow no new accounts are created. That's because, for this project, only pre-configured wallets should be able to sign in. However, the change needed to have that working as a &lt;code&gt;sign up&lt;/code&gt; should be pretty simple. For example, in the code snippet for the wallet connected, we can do something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="nv"&gt;@impl&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;handle_event&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"wallet-connected"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"public_address"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="c1"&gt;# also validate if is not nil! The User may not connect the wallet&lt;/span&gt;
  &lt;span class="no"&gt;Accounts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create_user_if_not_exists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 

  &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:noreply&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="n"&gt;assign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="ss"&gt;connected:&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;is_nil&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
     &lt;span class="ss"&gt;current_wallet_address:&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt;
   &lt;span class="p"&gt;)}&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;This post had a bunch of code that may be hard to follow, but I tried to explain it as best as I can. Now, to fill in the gaps, feel free to look at the full code where this was implemented and the final result:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/finiam/dora-the-tipset-explorer"&gt;Github Repo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://dora-the-tipset-explorer.fly.dev/"&gt;Example App&lt;/a&gt; deployed with &lt;a href="https://fly.io/"&gt;Fly.io&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you have any questions or comments, &lt;a href="https://zediogoviana.github.io/"&gt;reach out&lt;/a&gt; in one of my socials. And as always, stick around for the next one 👋&lt;/p&gt;

</description>
      <category>metamask</category>
      <category>liveview</category>
      <category>elixir</category>
      <category>signin</category>
    </item>
    <item>
      <title>How to build a Concurrent &amp; Resilient Service in Elixir</title>
      <dc:creator>José Diogo Viana</dc:creator>
      <pubDate>Thu, 16 Feb 2023 17:05:42 +0000</pubDate>
      <link>https://dev.to/finiam/how-to-build-a-concurrent-resilient-service-in-elixir-14gb</link>
      <guid>https://dev.to/finiam/how-to-build-a-concurrent-resilient-service-in-elixir-14gb</guid>
      <description>&lt;p&gt;During the last 12 months, more or less, I had to build 3 different services that were highly concurrent and required some degree of &lt;strong&gt;resilience&lt;/strong&gt; and &lt;strong&gt;fault tolerance&lt;/strong&gt;. These services had different requirements and did completely different things, but after the third one, I noticed that I'm pretty much using the same &lt;strong&gt;&lt;em&gt;recipe&lt;/em&gt;&lt;/strong&gt; for the structure. That's what I'll talk about in this blog post, and at the end, I expect to have given enough insight into this &lt;strong&gt;&lt;em&gt;recipe&lt;/em&gt;&lt;/strong&gt;, so that you can also follow it in your next project or even make it better (if you have suggestions feel free to &lt;a href="https://zediogoviana.github.io/" rel="noopener noreferrer"&gt;contact me&lt;/a&gt; at one of my socials).&lt;/p&gt;

&lt;h2&gt;
  
  
  Resilience &amp;amp; Fault Tolerance
&lt;/h2&gt;

&lt;p&gt;In this title, I mention &lt;strong&gt;Resilience&lt;/strong&gt; and there's also &lt;strong&gt;Fault Tolerance&lt;/strong&gt; in the first paragraph. After all, what are these concepts about? I learned about them, more in-depth, back when I was getting my Master's Degree in Distributed Systems, and I've had them at the back of my mind every time I need to build a system that requires high availability and correctness.&lt;/p&gt;

&lt;p&gt;If you want to be &lt;strong&gt;Fault Tolerant&lt;/strong&gt;, then as the name says, it needs to be able to deal with possible failures that may occur. This ranges from writing defensive code, and being prepared to handle these errors, to the ability to maintain functionality when portions of a system break. The &lt;a href="https://en.wikipedia.org/wiki/Fault_tolerance" rel="noopener noreferrer"&gt;Wikipedia definition&lt;/a&gt; has the following analogy:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;An example in another field is a motor vehicle designed so it will continue to be drivable if one of the tires is punctured, or a structure that is able to retain its integrity in the presence of damage due to causes such as fatigue, corrosion, manufacturing flaws, or impact. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The example above can also enter the realm of &lt;strong&gt;Resilience&lt;/strong&gt;, but I see it more as the ability to recover from a partial or total crash. If you have a running service that shuts down for some reason, you may not need to do anything special when restarting, but for some occasions, it can be necessary to recover the previous known state and resume from that. These systems are very common when the previous state matters.&lt;/p&gt;

&lt;p&gt;I think &lt;a href="https://www.ufried.com/blog/resilience_vs_fault_tolerance/" rel="noopener noreferrer"&gt;this Post from Uwe Friedrichsen&lt;/a&gt; makes a good summary of what &lt;strong&gt;Fault Tolerance&lt;/strong&gt; is, and it also makes a comparison between both concepts, as they have a lot in common.&lt;/p&gt;

&lt;p&gt;Please don't get confused or think I'm talking about &lt;strong&gt;Byzantine Fault Tolerance&lt;/strong&gt;, as that's a matter for actual &lt;em&gt;Distributed&lt;/em&gt; Systems, and not for &lt;em&gt;Concurrent&lt;/em&gt; ones. &lt;em&gt;Concurrency&lt;/em&gt; is also not the same thing as &lt;em&gt;Parallelism&lt;/em&gt;, so what is &lt;em&gt;Concurrency&lt;/em&gt; after all?&lt;/p&gt;

&lt;h2&gt;
  
  
  Concurrency
&lt;/h2&gt;

&lt;p&gt;In computing, concurrency refers to multiple things that overlap in time, so that one starts before the other finishes, and they "fight" each other over CPU time. Parallelism is multiple things happening at the same time. Multiple processes or threads on a single time-sliced CPU might exhibit concurrency but not parallelism. Parallelism is about multiple tasks that literally run at the same time on hardware with multiple computing resources like a multi-core CPU. As per Rob Pike:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Concurrency is about dealing with lots of things at once. Parallelism is about doing lots of things at once.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In &lt;a href="https://freecontent.manning.com/concurrency-vs-parallelism/" rel="noopener noreferrer"&gt;this blog post&lt;/a&gt; by &lt;em&gt;Manning Free Content Center&lt;/em&gt; there's a great explanation including two images that inspired me to do my own below. You should definitely read it if you're interested in the matter. (Or if you just want the 5 year old explanation check Joe Armstrong's &lt;a href="https://joearms.github.io/published/2013-04-05-concurrent-and-parallel-programming.html" rel="noopener noreferrer"&gt;Concurrent and Parallel Programming&lt;/a&gt;.)&lt;/p&gt;

&lt;p&gt;As for &lt;em&gt;Distributed&lt;/em&gt; systems, well, they're distributed... Who would have guessed? 😅 This means that a distributed system is one in which components are decoupled from one another. Distribution also introduces issues of consistency and separate failure domains (that's where those &lt;strong&gt;Byzantine Faults&lt;/strong&gt; enter). In a non-distributed system, consistency is often handled by that single machine and everything lives or dies together. If the hardware fully fails, then the service is completely down.&lt;/p&gt;

&lt;p&gt;So here is a small summary just to consolidate knowledge before jumping on to the next phase of this post.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz3a2yqex64synrxr3zo6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz3a2yqex64synrxr3zo6.png" title="Concurrency (A robot only Singing and Dancing at each point in time)." alt="Concurrency" width="705" height="213"&gt;&lt;/a&gt;&lt;br&gt;
Concurrency (A robot only Singing and Dancing at each point in time).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fty8bqypp6p00gsnq2j7u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fty8bqypp6p00gsnq2j7u.png" title="Parallelism (A band performer Singing and Dancing at the same time)." alt="Parallelism" width="704" height="211"&gt;&lt;/a&gt;&lt;br&gt;
Parallelism (A band performer Singing and Dancing at the same time).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgqv2qtr75yum3bhydq7k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgqv2qtr75yum3bhydq7k.png" title="Distributed (A full band performing together)." alt="Distributed Systems" width="800" height="280"&gt;&lt;/a&gt;&lt;br&gt;
Distributed (A full band performing together).&lt;/p&gt;
&lt;h2&gt;
  
  
  The &lt;em&gt;BEAM&lt;/em&gt; &amp;amp; &lt;em&gt;Elixir&lt;/em&gt;
&lt;/h2&gt;

&lt;p&gt;As almost everybody at this point knows, &lt;em&gt;Elixir&lt;/em&gt; compiles into &lt;em&gt;BEAM&lt;/em&gt; (the &lt;em&gt;Erlang Virtual Machine&lt;/em&gt;) byte code (via &lt;em&gt;Erlang Abstract Format&lt;/em&gt;). This means that &lt;em&gt;Elixir&lt;/em&gt; code can be called from &lt;em&gt;Erlang&lt;/em&gt; and vice versa, without the need to write any bindings. &lt;/p&gt;

&lt;p&gt;For the ones that don't know &lt;a href="https://erlang.org/doc/getting_started/conc_prog.html" rel="noopener noreferrer"&gt;&lt;em&gt;Erlang&lt;/em&gt;&lt;/a&gt; or its background, it's a language developed back in the ‘80s by &lt;em&gt;Ericsson&lt;/em&gt; for better development and stability of telephony applications, and that was made &lt;a href="https://web.archive.org/web/19991009002753/http://www.erlang.se/onlinenews/ErlangOTPos.shtml" rel="noopener noreferrer"&gt;open source in 1998&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;This way, &lt;em&gt;Elixir&lt;/em&gt; has all of the benefits of the battle-proven system that is &lt;em&gt;Erlang&lt;/em&gt;, and it is possible to use the existing &lt;em&gt;Erlang&lt;/em&gt; libraries with no performance penalty. Another strong point for &lt;em&gt;Elixir&lt;/em&gt; is concurrency (you probably see where I'm going with the line of thought), which, in most languages, is a bit of a pain. Not only is dangerous, but it's also hard to achieve synchronisation. In &lt;em&gt;Elixir&lt;/em&gt; it is effortless to create a new process, and it performs very well. It is a core feature of the platform and does not require a separate library. Note that &lt;em&gt;Erlang&lt;/em&gt;/&lt;em&gt;Elixir&lt;/em&gt; processes are not native processes; they are much more lightweight and are scheduled by the BEAM.&lt;/p&gt;

&lt;p&gt;So, introductions aside, from this point I'm going to assume that you have at least the basic knowledge about the &lt;em&gt;Erlang&lt;/em&gt; and &lt;em&gt;Elixir&lt;/em&gt; ecosystems.&lt;/p&gt;

&lt;p&gt;If you're reading this, there's a chance that you already built some &lt;a href="https://www.phoenixframework.org/" rel="noopener noreferrer"&gt;&lt;em&gt;Phoenix&lt;/em&gt; Apps&lt;/a&gt; and know how amazing it is to build upon it while keeping the concepts above somewhat abstracted under it. However, that's not why I'm here today. Have you ever needed to build a resilient and concurrent system, just like &lt;em&gt;Phoenix&lt;/em&gt;, for example, inside your usual Backend (if you're into Monoliths) or as a stand-alone app (if you're into Microservices)? In the case you already have, you may see a lot of similarities between them, and it's those that I want to talk about and include in my &lt;strong&gt;recipe&lt;/strong&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Taking advantage of Supervisors
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Erlang&lt;/em&gt; has the &lt;strong&gt;&lt;em&gt;Let it crash&lt;/em&gt;&lt;/strong&gt; philosophy, and that's where &lt;strong&gt;Resilience&lt;/strong&gt; and &lt;strong&gt;Fault Tolerance&lt;/strong&gt; enter the scene. Don't get confused, the idea behind is not to &lt;strong&gt;let it crash and burn&lt;/strong&gt;, but to &lt;strong&gt;let it crash and recover&lt;/strong&gt;. Instead of having uncontrolled failures, &lt;em&gt;Erlang&lt;/em&gt; turns failures, exceptions and crashes into tools that we can use and control.&lt;/p&gt;

&lt;p&gt;The language comes with a lot of different tools, and you should definitely learn more about them. Here, I'll mostly prioritise &lt;code&gt;Supervisors&lt;/code&gt;, but &lt;a href="https://medium.com/@vamsimokari/erlang-let-it-crash-philosophy-53486d2a6da" rel="noopener noreferrer"&gt;in this Medium post&lt;/a&gt; you can find more info on &lt;code&gt;Processes&lt;/code&gt;, &lt;code&gt;Monitors&lt;/code&gt;, and others.&lt;/p&gt;

&lt;p&gt;Even though &lt;code&gt;Supervisors&lt;/code&gt; come from &lt;em&gt;Erlang&lt;/em&gt;, I want to clarify that from now on I'm talking of &lt;code&gt;Supervisors&lt;/code&gt; on &lt;em&gt;Elixir&lt;/em&gt;. Looking at the definition in the &lt;a href="https://hexdocs.pm/elixir/1.12/Supervisor.html" rel="noopener noreferrer"&gt;&lt;em&gt;Elixir&lt;/em&gt; docs&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A supervisor is a process which supervises other processes, which we refer to as child processes. Supervisors are used for building a hierarchical process structure called a supervision tree. Supervision trees provide fault tolerance and encapsulate how our applications start and shut down.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;Supervisor&lt;/code&gt; process has the job of looking at the health of its child processes and acting accordingly to the &lt;a href="https://hexdocs.pm/elixir/1.12/Supervisor.html#module-child-specification" rel="noopener noreferrer"&gt;specified configuration and strategy&lt;/a&gt;. These can range from configuring:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;:shutdown&lt;/code&gt;: defines how a child process should be terminated.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;:restart&lt;/code&gt;: defines when a terminated child process should be restarted.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;:strategy&lt;/code&gt;: how the supervisor should act when a process terminates.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;:max_restarts&lt;/code&gt;: the maximum number of restarts allowed in a time frame.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are several more, and each of these has various options, but I feel that with the ones above you can already grasp what we can achieve with &lt;em&gt;Elixir&lt;/em&gt; to quickly develop a &lt;strong&gt;Fault Tolerant&lt;/strong&gt; and &lt;strong&gt;Resilient&lt;/strong&gt; service.&lt;/p&gt;
&lt;h3&gt;
  
  
  Dynamic and Partition Supervisors
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;DynamicSupervisor&lt;/code&gt;: As the name implies, it's a supervisor that starts children dynamically. The &lt;code&gt;Supervisor&lt;/code&gt; module (in &lt;em&gt;Elixir&lt;/em&gt;) was designed to handle mostly static children that are started in the given order when the supervisor starts. A &lt;code&gt;DynamicSupervisor&lt;/code&gt; starts with no children. Instead, children are started on demand. When a dynamic supervisor terminates, all children are shut down at the same time, with no guarantee of order. We'll see them in my &lt;em&gt;simple framework&lt;/em&gt; for these services.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;PartitionSupervisor&lt;/code&gt;: A supervisor that starts multiple partitions of the same child. Certain processes may become bottlenecks in large systems. If those processes can have their state trivially partitioned, in a way there is no dependency between them, then they can use the &lt;code&gt;PartitionSupervisor&lt;/code&gt; to create multiple isolated and independent partitions. It's also possible to combine a &lt;code&gt;PartitionSupervisor&lt;/code&gt; with a &lt;code&gt;DynamicSupervisor&lt;/code&gt; (check &lt;a href="https://blog.appsignal.com/2022/09/20/fix-process-bottlenecks-with-elixir-1-14s-partition-supervisor.html" rel="noopener noreferrer"&gt;this amazing post&lt;/a&gt; by &lt;em&gt;AppSignal&lt;/em&gt; for a concrete example).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  A simple Framework
&lt;/h2&gt;

&lt;p&gt;We have the concepts in place, and we also know about &lt;em&gt;Erlang&lt;/em&gt;/&lt;em&gt;Elixir&lt;/em&gt; tools to manage processes, so it's time to jump into some actual code.&lt;/p&gt;

&lt;p&gt;The following image tries to represent the base structure I've been using for these last 3 services I had to build/incorporate into an &lt;em&gt;Elixir&lt;/em&gt; app. It all starts by starting a &lt;code&gt;DynamicSupervisor&lt;/code&gt; under the main App Supervisor (usually where the &lt;code&gt;Application&lt;/code&gt; code is). Then this &lt;code&gt;DynamicSupervisor&lt;/code&gt; starts and manages all worker processes that should do all the heavy and concurrent lifting. Note that as stated above, the &lt;code&gt;DynamicSupervisor&lt;/code&gt; can be replaced or mixed in with a &lt;code&gt;PartitionSupervisor&lt;/code&gt; if the use case requires (in my situation, I haven't had to use them yet, but they are next in line if there is any bottleneck in the process).&lt;/p&gt;

&lt;p&gt;With this approach, you can also guarantee that an unhealthy Worker Process won't affect the others, as they are separate entities. If you want to ensure synchronization between them, then adding a new &lt;code&gt;Manager&lt;/code&gt; process can be an easy solution (check my previous &lt;a href="https://blog.finiam.com/blog/simulations-with-elixir-and-the-actor-model" rel="noopener noreferrer"&gt;blog post on Simulations with Elixir&lt;/a&gt; for a quick example). For the hard way but more robust, you probably need to look into &lt;a href="https://www.baeldung.com/cs/consensus-algorithms-distributed-systems" rel="noopener noreferrer"&gt;&lt;strong&gt;Consensus Algorithms&lt;/strong&gt;&lt;/a&gt;, but that's more in the realm of &lt;em&gt;Distributed&lt;/em&gt; and not &lt;em&gt;Concurrent&lt;/em&gt; only systems.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftwajbfuuxhe5cqryda3r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftwajbfuuxhe5cqryda3r.png" alt="concurrent and resilient base structure" width="521" height="372"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You probably noticed a new term in the image, the&lt;code&gt;ETS&lt;/code&gt; or &lt;code&gt;Erlang Term Storage&lt;/code&gt;. An &lt;code&gt;ETS&lt;/code&gt; allows us to store any Elixir term in an in-memory table and use it as a cache mechanism (&lt;a href="https://elixir-lang.org/getting-started/mix-otp/ets.html" rel="noopener noreferrer"&gt;learn more about them&lt;/a&gt;). I usually use this table to keep track of Worker Processes' &lt;code&gt;PIDs&lt;/code&gt; and other metadata about each one of them (depending on the use case and the amount of information that each Worker needs to know about itself, or others). &lt;strong&gt;Be careful not to use it as a cache prematurely! It's an in-memory store only! For persistent solutions, we'll see other possibilities, below&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Usually, I also add some client functions to the &lt;code&gt;DynamicSupervisor&lt;/code&gt; module, in order for Worker Processes to be able to update info on the &lt;code&gt;ETS&lt;/code&gt; or trigger the start/stop of other Workers if needed. These functions can be abstracted into a separate Module if this one starts to grow indefinitely, and you feel they should be separated.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;MyApp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;MyModule&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="kn"&gt;require&lt;/span&gt; &lt;span class="no"&gt;Logger&lt;/span&gt;

  &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="no"&gt;DynamicSupervisor&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;start_link&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;init_arg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pid&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="no"&gt;DynamicSupervisor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start_link&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;__MODULE__&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;init_arg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;name:&lt;/span&gt; &lt;span class="bp"&gt;__MODULE__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="c1"&gt;# Extra logic here if needed&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pid&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
      &lt;span class="n"&gt;_error&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="no"&gt;Logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Error starting MyApp"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="nv"&gt;@impl&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_init_arg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="no"&gt;DynamicSupervisor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;strategy:&lt;/span&gt; &lt;span class="ss"&gt;:one_for_one&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;start_worker_instance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;spec&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;MyApp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;MyModule&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Worker&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="no"&gt;DynamicSupervisor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start_child&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;__MODULE__&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="no"&gt;Logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Error starting new Worker: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;inspect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;stop_worker_instance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;some_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pid&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;get_pid_worker_instance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;some_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="no"&gt;Worker&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:closed&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;get_pid_worker_instance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;some_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="ss"&gt;:ets&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lookup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:my_ets_table&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;some_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:not_found&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="n"&gt;_some_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_rest&lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pid&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;delete_worker_from_ets&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;some_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="ss"&gt;:ets&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:my_ets_table&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;some_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;insert_worker_in_ets&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;some_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="ss"&gt;:ets&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;insert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:my_ets_table&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;some_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="c1"&gt;# ...&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With the piece of code above, we already have a very basic supervision tree that can help us achieve a lot of things without much hassle. If a Worker Process dies, it's restarted, and the same thing for the &lt;code&gt;DynamicSupervisor&lt;/code&gt; itself. &lt;strong&gt;Don't forget to start this Supervisor under the Application, or another already there.&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;The code for the Worker usually looks something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;MyApp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;MyModule&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Explorer&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="kn"&gt;require&lt;/span&gt; &lt;span class="no"&gt;Logger&lt;/span&gt;
  &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="no"&gt;GenServer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;restart:&lt;/span&gt; &lt;span class="ss"&gt;:transient&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;start_link&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pid&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;GenServer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start_link&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;__MODULE__&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="no"&gt;MyApp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;MyModule&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;insert_worker_in_ets&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;some_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:start&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="no"&gt;Logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Starting &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;some_id&lt;/span&gt;&lt;span class="si"&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="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pid&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;some_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="no"&gt;GenServer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;some_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="nv"&gt;@impl&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;init_arg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="c1"&gt;# new_state = some kind of computation on init_arg&lt;/span&gt;

    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;new_state&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="nv"&gt;@impl&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;handle_info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="c1"&gt;# start work&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="c1"&gt;# ...&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note the usage of &lt;code&gt;use GenServer, restart: :transient&lt;/code&gt;. This piece of code tells the Supervisor to not restart this process if it stopped in a normal/controlled way. Only in a case of a crash, it will be automatically restarted. (You can then play around with &lt;a href="https://hexdocs.pm/elixir/1.12/GenServer.html" rel="noopener noreferrer"&gt;other options&lt;/a&gt;.)&lt;/p&gt;

&lt;h2&gt;
  
  
  Going the Extra mile
&lt;/h2&gt;

&lt;p&gt;I want to reiterate that the approach, or "&lt;strong&gt;recipe&lt;/strong&gt;" as I called it previously, is as simple as you can get in order to start. There are obviously a lot of extra things you can add to make your system even more robust to &lt;strong&gt;faults&lt;/strong&gt;. Here are some of them, that I've used in the past.&lt;/p&gt;

&lt;h3&gt;
  
  
  Using a &lt;code&gt;:dets&lt;/code&gt; and other disk storage mechanisms
&lt;/h3&gt;

&lt;p&gt;Imagine the situation that our service is indexing Events that happen in a separate place. If the service completely fails, when restarting we want to resume/continue indexing in the place where we left off before the downtime. This way we won't have any duplicated events, and won't miss others while down. &lt;/p&gt;

&lt;p&gt;We can achieve this with the help of disk storage-based mechanisms, like using a &lt;code&gt;:dets&lt;/code&gt; or the Database itself. A &lt;code&gt;:dets&lt;/code&gt; is very similar to the &lt;code&gt;:ets&lt;/code&gt;, but it's disk-based instead. It features a lot of helper functions that you can find in &lt;a href="https://www.erlang.org/doc/man/dets.html" rel="noopener noreferrer"&gt;the docs&lt;/a&gt;, including ways to quickly turn it into an &lt;code&gt;ETS&lt;/code&gt;, if we want. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;IMPORTANT NOTICE: if you use services like &lt;a href="https://www.heroku.com/" rel="noopener noreferrer"&gt;&lt;em&gt;Heroku&lt;/em&gt;&lt;/a&gt; or &lt;a href="https://www.fly.io/" rel="noopener noreferrer"&gt;&lt;em&gt;Fly.io&lt;/em&gt;&lt;/a&gt;, relying on this file approach may not work! Changes to the filesystem on one machine may not be propagated to others and are not persisted across deploys and/or restarts (depending on service specifics, they don't work the same way).&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To avoid the problem above, you can rely on your dedicated Database or other services like &lt;em&gt;Redis&lt;/em&gt; to keep track of it. The &lt;code&gt;start_link&lt;/code&gt; code for the Supervisor would look like this now:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;start_link&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;init_arg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pid&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="no"&gt;DynamicSupervisor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start_link&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;__MODULE__&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;init_arg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;name:&lt;/span&gt; &lt;span class="bp"&gt;__MODULE__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="ss"&gt;:dets&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;open_file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:my_dets&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[])&lt;/span&gt;

    &lt;span class="n"&gt;restore_previous_state&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pid&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;else&lt;/span&gt;
    &lt;span class="n"&gt;_error&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
      &lt;span class="no"&gt;Logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Error starting Dora"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;restore_previous_state&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ss"&gt;:ets&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;whereis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:some_pid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="ss"&gt;:undefined&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="ss"&gt;:ets&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:my_ets&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:set&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:public&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:named_table&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="ss"&gt;:dets&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;match_object&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:workers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:_&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
      &lt;span class="no"&gt;MyApp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Workers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;list_workers&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;each&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;start_worker_instance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;&amp;amp;1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;some_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;&amp;amp;1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;extra_info&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="n"&gt;list&lt;/span&gt; &lt;span class="ow"&gt;when&lt;/span&gt; &lt;span class="n"&gt;is_list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
      &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;each&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;some_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;extra_info&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="n"&gt;start_worker_instance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;some_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;extra_info&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Some unexpected error happened!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that it's also required to &lt;strong&gt;add/remove&lt;/strong&gt; workers' entries from these tracking systems when a new Worker Process is started/stopped with success.&lt;/p&gt;

&lt;p&gt;You can check our &lt;a href="https://github.com/finiam/dora-the-tipset-explorer" rel="noopener noreferrer"&gt;&lt;strong&gt;&lt;em&gt;Dora, the TipsetExplorer&lt;/em&gt;&lt;/strong&gt; repo&lt;/a&gt; with this approach, as one of the projects we submitted for the &lt;a href="https://ethglobal.com/events/spacewarp" rel="noopener noreferrer"&gt;&lt;strong&gt;FVM Space Warp Hackathon&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Process Pool
&lt;/h3&gt;

&lt;p&gt;If your use case requires a lot of Worker Processes, and you don't want to flood the BEAM with new processes, you should definitely go with a Process Pool solution. You can easily exhaust your system resources if you do not limit the maximum number of concurrent processes that your program can spawn. The solution is to use a set of workers (processes) to limit the number of connections instead of creating a process for every individual action. For this, I would suggest two different approaches:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Poolboy&lt;/code&gt;: widely used lightweight, generic pooling library for &lt;em&gt;Erlang&lt;/em&gt; that addresses this issue. This &lt;a href="https://elixirschool.com/en/lessons/misc/poolboy" rel="noopener noreferrer"&gt;Elixir School guide&lt;/a&gt; is very helpful to get started quickly.&lt;/li&gt;
&lt;li&gt;Custom solution: if &lt;code&gt;Poolboy&lt;/code&gt; doesn't fit well within your constraints, you can always build your custom solution. For a previous personal project, I took the opportunity to build my custom solution, not because I had special requirements, but because I wanted to try my own thing. You can find the code for this &lt;a href="https://github.com/zediogoviana/ethcule-poirot/blob/master/lib/ethcule_poirot/network_explorer.ex" rel="noopener noreferrer"&gt;custom pool here&lt;/a&gt;. The file code I linked is a "special type" of Worker Process, under the &lt;code&gt;DynamicSupervisor&lt;/code&gt; supervision tree, but only keeps track of the pool and other Process management-related things.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Different Handlers that can be plugged and played
&lt;/h3&gt;

&lt;p&gt;Suppose we continue our Indexing example, highlighted in the persistent-store mechanisms chapter, and we have different ways to listen/query for those events being emitted. We could have for example a queue/socket for passive listening, but the other service could also feature an HTTP API that we could poll. &lt;/p&gt;

&lt;p&gt;This way if we want an even more &lt;strong&gt;fault tolerant&lt;/strong&gt; and &lt;strong&gt;resilient&lt;/strong&gt; service, we can make our Worker Processes use different &lt;code&gt;Handlers&lt;/code&gt; to interact with the external system. So, in case we start listening to events via a socket/queue and the external service has a failure on that section, we can switch to automatically polling it through the HTTP API. This approach requires some overhead to manage which handlers are being used, and when to switch between them.&lt;/p&gt;

&lt;h3&gt;
  
  
  Further Reading
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.amazon.com/Concurrent-Data-Processing-Elixir-Applications/dp/1680508199?&amp;amp;linkCode=sl1&amp;amp;tag=devchattv-20&amp;amp;linkId=35799dc8e559aabae945523ec346c19d&amp;amp;language=en_US&amp;amp;ref_=as_li_ss_tl" rel="noopener noreferrer"&gt;&lt;em&gt;"Concurrent Data Processing in Elixir: Fast, Resilient Applications with OTP, GenStage, Flow, and Broadway"&lt;/em&gt;&lt;/a&gt;, by Svilen Gospodinov, is a book that talks about the &lt;em&gt;Concurrency&lt;/em&gt; part I talked about here, and more, explaining things in more detail. It goes into more specific situations, use cases you may have, and which tools to use, as I only followed a more generic approach.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;We've now reached the end of this post... It was probably a bit too technical, but I tried to explain all base concepts in a way that any developer, with different degrees of experience, could understand the problem and the proposed approaches. If you have any suggestions to add under the &lt;code&gt;Extra mile&lt;/code&gt; section or even the base Framework, feel free to reach out! &lt;/p&gt;

&lt;p&gt;As hinted in the previous sub-section, there are a lot more things to be explored and looked at according to your needs. &lt;strong&gt;&lt;em&gt;I don't believe this is a hammer, and all my problems are nails, and you shouldn't believe it also&lt;/em&gt;&lt;/strong&gt;! However, I think it should give a good place to start for personal/side projects.&lt;/p&gt;

&lt;p&gt;Image from: &lt;a href="https://raspstephan.github.io/blog/hammer-and-nail/#" rel="noopener noreferrer"&gt;https://raspstephan.github.io/blog/hammer-and-nail/#&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6zj4w2dwjag17dzb1d7d.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6zj4w2dwjag17dzb1d7d.jpeg" alt="a hammer trying to hit a screw as if it were a nail" width="434" height="339"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And as always, thank you for taking the time to read this, and see you in the next one 👋&lt;/p&gt;

</description>
      <category>rust</category>
      <category>discuss</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Genetic Algorithms to optimize an Asset Portfolio</title>
      <dc:creator>José Diogo Viana</dc:creator>
      <pubDate>Fri, 23 Dec 2022 21:54:58 +0000</pubDate>
      <link>https://dev.to/finiam/genetic-algorithms-to-optimize-an-asset-portfolio-3k0b</link>
      <guid>https://dev.to/finiam/genetic-algorithms-to-optimize-an-asset-portfolio-3k0b</guid>
      <description>&lt;p&gt;On the last weekend of October, we (&lt;a href="https://finiam.com" rel="noopener noreferrer"&gt;finiam&lt;/a&gt;) participated in &lt;a href="https://www.ethlisbon.org/" rel="noopener noreferrer"&gt;ETHLisbon&lt;/a&gt;, an Ethereum-related hackathon, and our submitted project, &lt;a href="https://taikai.network/ethlisbon/hackathons/ethlisbon-2022/projects/cl9ssst4a8562890118gtnyuahe/idea" rel="noopener noreferrer"&gt;&lt;em&gt;Matusalem&lt;/em&gt;&lt;/a&gt;, resembled a pension fund scheme but only for Crypto Assets - I won't dwell here into much details of the project, as we'll probably have a dedicated blog post explaining it.&lt;/p&gt;

&lt;p&gt;So, why am I talking about an Ethereum hackathon and Genetic Algorithms? Well, by the title of this post, you can probably guess why. For the last few weeks I had been reading &lt;a href="https://pragprog.com/titles/smgaelixir/genetic-algorithms-in-elixir/" rel="noopener noreferrer"&gt;&lt;em&gt;Genetic Algorithms in Elixir&lt;/em&gt;&lt;/a&gt; by Sean Moriarity, and I was hooked on giving them a try in a use case outside the book. Fast forward to ETHLisbon, and our idea for the project, we found a place where Genetic Algorithms could be a nice path to explore, trying to figure out from a set of Crypto Assets which ones should make it into our pension fund portfolio, and I became responsible for it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The base idea
&lt;/h2&gt;

&lt;p&gt;Forgetting the details of how the whole thing would work, in this blog post, we'll focus only on the process of calculating the percentages of the funds we should allocate to each asset from a given list, using Genetic Algorithms.&lt;/p&gt;

&lt;p&gt;Starting from the simplest use case, imagine we have 4 Assets to choose from and invest the money. Let's call them assets &lt;strong&gt;A&lt;/strong&gt;, &lt;strong&gt;B&lt;/strong&gt;, &lt;strong&gt;C&lt;/strong&gt;, and &lt;strong&gt;D&lt;/strong&gt;. Supposing the table below represents their expected returns and associated risk (1-7).&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Returns (%)&lt;/th&gt;
&lt;th&gt;Risk Level&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;A&lt;/td&gt;
&lt;td&gt;4%&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;B&lt;/td&gt;
&lt;td&gt;2%&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;C&lt;/td&gt;
&lt;td&gt;8%&lt;/td&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;D&lt;/td&gt;
&lt;td&gt;5%&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;If we wanted to calculate the percentages we should invest in each asset, just by looking at the expected returns, it's clear that we should put all eggs in the basket &lt;strong&gt;C&lt;/strong&gt;. However, things are just not that simple regarding investments, as we can understand that different assets have different risk levels. Normally, the higher the expected return, the higher the risk, but that's not always the case. So, our final goal, for this hackathon, was to optimize for a portfolio allocation that would maximize returns while bearing minimal risk. How can we do that? (At least in a mathematical way).&lt;/p&gt;

&lt;h3&gt;
  
  
  Sharpe Ratio
&lt;/h3&gt;

&lt;p&gt;Here comes in &lt;strong&gt;Sharpe Ratio&lt;/strong&gt;. We can evaluate the investment performance based on the risk-free return. The risk-free return is the return of an investment with zero risks for the investor (for example US Government Bonds, etc.). &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A Higher Sharpe metric is always better than a lower one because a higher ratio indicates that the portfolio is making a better investment decision.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Since Genetic Algorithms are an optimization problem, and I'll explain further down how they work, we can use &lt;strong&gt;Sharpe Ratio&lt;/strong&gt; as the metric we want to optimize. It takes into account expected returns and also associated risks. But how does it work, then?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.sanity.io%2Fimages%2F5aprln8a%2Fproduction%2F279f8d2bf722bdde32b92788ba660c8a26be8d10-1024x461.webp%3Fw%3D450" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.sanity.io%2Fimages%2F5aprln8a%2Fproduction%2F279f8d2bf722bdde32b92788ba660c8a26be8d10-1024x461.webp%3Fw%3D450" alt="sharp-ratio-formula"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;The image is from &lt;a href="https://www.wallstreetmojo.com/sharpe-ratio-formula/" rel="noopener noreferrer"&gt;WallStreetMojo's explanation of the Sharpe Ratio&lt;/a&gt;, and I recommend reading it if you're curious about these subjects.&lt;/p&gt;

&lt;p&gt;If you're not familiar with &lt;strong&gt;Sharpe Ratio&lt;/strong&gt; or Statistics in general, you may be asking how does the formula above take into account the assets' risks? Well, that part is handled by the portfolio's standard deviation. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Portfolio Standard Deviation refers to the volatility of the portfolio, which is calculated based on three important factors that include the standard deviation of each of the assets present in the total Portfolio, the respective weight of that individual asset in the total portfolio, and the correlation between each pair of assets of the portfolio.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This way, if a portfolio has a high standard deviation it means that the risk is high, it has more volatility and therefore not so stable returns. A portfolio with a low standard deviation has less associated risk.&lt;/p&gt;

&lt;p&gt;We will see below how we can calculate the standard deviation for a portfolio and use it inside our Genetic Algorithms' fitness function. But what is a &lt;strong&gt;fitness function&lt;/strong&gt;?&lt;/p&gt;

&lt;h2&gt;
  
  
  Genetic Algorithms
&lt;/h2&gt;

&lt;p&gt;As stated above, Genetic Algorithms are used to solve optimization problems. An optimization problem is a problem of finding the best solution from all feasible solutions. Usually, the solution to that problem is hard to obtain using conventional mathematics, requiring a lot of computation (brute force). &lt;/p&gt;

&lt;p&gt;One example of an optimization problem is the &lt;a href="https://en.wikipedia.org/wiki/Knapsack_problem" rel="noopener noreferrer"&gt;Knapsack problem&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Genetic Algorithms help us overcome this brute force approach, by using certain heuristics that enable us to find a "good enough" solution, but not necessarily the best one.&lt;/p&gt;

&lt;p&gt;Despite the cool name, how does a Genetic Algorithm actually work? It tries to mimic evolution the same way it happens in nature. Concepts like &lt;a href="https://en.wikipedia.org/wiki/Natural_selection" rel="noopener noreferrer"&gt;&lt;em&gt;Natural Selection&lt;/em&gt;&lt;/a&gt; are known by almost everyone, and if you're reading this post, you're probably familiar with it. Individuals with certain variants of a trait tend to survive and reproduce more than individuals with other less successful variants. This gives that phenotype (with valuable traits) a reproductive advantage and may become more common in a population - &lt;strong&gt;survival of the fittest&lt;/strong&gt;. A key part of this is also &lt;a href="https://en.wikipedia.org/wiki/Sexual_selection" rel="noopener noreferrer"&gt;&lt;em&gt;Sexual Selection&lt;/em&gt;&lt;/a&gt;, where this form of selection, together with &lt;em&gt;Natural Selection&lt;/em&gt;, means that some individuals have greater reproductive success than others within a population, for example, because they are more attractive or prefer more attractive partners to produce offspring. A Genetic Algorithm takes these concepts and runs a sort of simulation for an evolution of a population.&lt;/p&gt;

&lt;p&gt;In his book &lt;strong&gt;Genetic Algorithms in Elixir&lt;/strong&gt;, Sean provides a simple scheme like the one below, that summarizes really well the different components that take part in these algorithms.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.sanity.io%2Fimages%2F5aprln8a%2Fproduction%2F3e3738b763d2d2db838caabe6cf0f5cdaf17b6da-841x138.jpg%3Fw%3D450" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.sanity.io%2Fimages%2F5aprln8a%2Fproduction%2F3e3738b763d2d2db838caabe6cf0f5cdaf17b6da-841x138.jpg%3Fw%3D450" alt="genetic-algorithms"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What does it mean, and how does it relate to Darwin's theories? Let's imagine we have a population for a species of &lt;strong&gt;Unicorns&lt;/strong&gt; and follow the diagram above.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Initialize Population:&lt;/strong&gt; In our case the starting population doesn't evolve out of a different species, it just gets "initialized randomly" (we'll see how we can represent a population later). That means that we start with a population of individuals we know are &lt;strong&gt;unicorns&lt;/strong&gt; (four legs, a spiralling horn projecting from its forehead, etc), but their traits (genotypes) would be randomized across the entire population. Traits like height, horn size, muscle density, etc. A good starting population for these algorithms should be random enough (but still inside valid boundaries) so that we don't simulate evolution with a starting bias. The population size also needs to be a finite number, for example, 100 individuals.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Evaluate Population:&lt;/strong&gt; In this phase, we give each individual in our population a rating, accordingly to a pre-defined &lt;em&gt;fitness function&lt;/em&gt;. After the rating process, all individuals are sorted by the rating they got. The best one is checked against the termination criteria. What are the termination criteria? It's a function that verifies if we have reached an optimal solution (it compares with a reference value) or could check if the rating is getting better each generation, if we've reached a specific number of generations, etc. If this function determines to not stop the process, the algorithm advances to &lt;strong&gt;step 3&lt;/strong&gt;, otherwise, it returns the best individual and its rating (fitness function) providing us with the solution for the problem.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Select Parents:&lt;/strong&gt; If the simulation continues to this step, then we must select the parents for the next generation. Selecting parents is basically following the idea stated in the &lt;em&gt;Sexual Selection&lt;/em&gt; theory, and we group the best individual with the 2nd best, the 3rd with 4th, etc. for all individuals in the population set. This way, we plan to create children out of the best chromosomes, with the hopes of obtaining a fitter individual out of the match.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Create Children:&lt;/strong&gt; After grouping each individual it's time to generate their children. To create children out of each pair of parents, we'll use &lt;em&gt;crossover&lt;/em&gt;. Crossover is analogous to reproduction. It’s a genetic operator that takes two or more parent chromosomes and produces two or more child chromosomes. So, supposing we have parents &lt;strong&gt;P1&lt;/strong&gt; and &lt;strong&gt;P2&lt;/strong&gt;, we can combine them by splitting their chromosomes randomly, and obtaining four chromosome parts &lt;strong&gt;P1-1&lt;/strong&gt;, &lt;strong&gt;P1-2&lt;/strong&gt;, &lt;strong&gt;P2-1&lt;/strong&gt;, &lt;strong&gt;P2-2&lt;/strong&gt;. Children for these two individuals are the chromosomes &lt;strong&gt;P1-1|P2-2&lt;/strong&gt; and &lt;strong&gt;P1-2|P2-1&lt;/strong&gt;. Repeating this crossover process for all parent pairs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Mutate Children:&lt;/strong&gt; Despite initializing the population to a seemingly random distribution, eventually the parents get too genetically similar to make any improvements during the crossover. In order to reach a proper solution, Genetic algorithms, also need to insert some entropy into the simulation, by provoking "mutations". Mutations to children's chromosomes should happen with a relatively low frequency, for example, a 5% probability of a mutation occurring. Mutations in Genetic Algorithms could range from shuffling individual genes', to swapping them entirely with a new value, etc. Too many mutations could add too much entropy to the algorithm, and it wouldn't get a proper result.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Start from &lt;strong&gt;step 2&lt;/strong&gt;, and redo the process again, starting a new generation, until it reaches an optimal solution, triggered by the fitness function rating being high enough to reach the termination criteria.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I hope that this explanation has been enough to understand how a Genetic Algorithm works before we enter into the technical bits.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Book's framework
&lt;/h3&gt;

&lt;p&gt;When starting to read the book, after a more in-depth explanation of what I mentioned here (a lot of things in this post are from there, also), the author guides the reader through the development of a framework that we can use for almost any Genetic Algorithm problem with minimal adjustments to its base logic.&lt;/p&gt;

&lt;p&gt;Recalling the simple flow specified above, we can see that some things can be abstracted through some code, by using a defined API for what &lt;code&gt;chromosomes&lt;/code&gt; and &lt;code&gt;genes&lt;/code&gt; should be. To fully grasp how we got to the next pieces of code, you'll need to read the book, but the most important parts can be summarized into the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The definition of the &lt;code&gt;Chromosome&lt;/code&gt; type. 

&lt;ul&gt;
&lt;li&gt;By using &lt;code&gt;:genes&lt;/code&gt; as an &lt;code&gt;Enum&lt;/code&gt; we can take advantage of all the existing functions. We can use complex structs to represent a single &lt;code&gt;gene&lt;/code&gt;, but the set of them follows the same API.&lt;/li&gt;
&lt;li&gt;Defining other helpful fields like &lt;code&gt;fitness&lt;/code&gt;, &lt;code&gt;size&lt;/code&gt; and &lt;code&gt;age&lt;/code&gt; that will help in the evaluation of the population.
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;Types&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Chromosome&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="nv"&gt;@type&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="p"&gt;::&lt;/span&gt; &lt;span class="p"&gt;%&lt;/span&gt;&lt;span class="bp"&gt;__MODULE__&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="ss"&gt;genes:&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
          &lt;span class="ss"&gt;size:&lt;/span&gt; &lt;span class="n"&gt;integer&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
          &lt;span class="ss"&gt;fitness:&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
          &lt;span class="ss"&gt;age:&lt;/span&gt; &lt;span class="n"&gt;integer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nv"&gt;@enforce_keys&lt;/span&gt; &lt;span class="ss"&gt;:genes&lt;/span&gt;
  &lt;span class="k"&gt;defstruct&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:genes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;size:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;fitness:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;age:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;evolve&lt;/code&gt; function. This represents the flow above, where we get a population (list of Chromosomes), and iterate recursively over &lt;code&gt;selection -&amp;gt; crossover -&amp;gt; mutation -&amp;gt; restart&lt;/code&gt; until the termination criteria are reached. I'll skip that part here, but this and the other functions remain almost the same across problems, but the book also shows different approaches.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;evolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;population&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;problem&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;generation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;opts&lt;/span&gt; &lt;span class="p"&gt;\\&lt;/span&gt; &lt;span class="p"&gt;[])&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;population&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;evaluate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;population&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;problem&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fitness_function&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;best&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;hd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;population&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;best_fitness&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;best&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fitness&lt;/span&gt;

    &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\r&lt;/span&gt;&lt;span class="s2"&gt;Current Best: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;best_fitness&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;problem&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;terminate?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;population&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;generation&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;best&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
      &lt;span class="n"&gt;generation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;generation&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

      &lt;span class="n"&gt;population&lt;/span&gt;
      &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;select&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;crossover&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;mutation&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;evolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;problem&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;generation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This way, the few things we need to worry about are providing the framework with an initial population and defining the &lt;code&gt;terminate?(population, generation)&lt;/code&gt; function, which evaluates the termination criteria.&lt;/p&gt;

&lt;h3&gt;
  
  
  Using expected returns as Fitness Function
&lt;/h3&gt;

&lt;p&gt;Recalling the problem stated above, for this project we wanted to know which Assets would make it into the portfolio using Genetic Algorithms. A good first approach for this, and one that is very simple, is just optimizing for the expected returns. Why? We can avoid the complex math related to &lt;strong&gt;Sharpe Ratio&lt;/strong&gt;, and just worry about a singular variable: &lt;em&gt;the asset expected return&lt;/em&gt;. We had already selected the assets we were going to use. Some of the expected returns, at the time of writing, were:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;ETH Staking&lt;/th&gt;
&lt;th&gt;Uniswap&lt;/th&gt;
&lt;th&gt;BTC&lt;/th&gt;
&lt;th&gt;Maker&lt;/th&gt;
&lt;th&gt;Filecoin&lt;/th&gt;
&lt;th&gt;Aave&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;4%&lt;/td&gt;
&lt;td&gt;-0.0054%&lt;/td&gt;
&lt;td&gt;-0.0017%&lt;/td&gt;
&lt;td&gt;-0.0038%&lt;/td&gt;
&lt;td&gt;-0.011%&lt;/td&gt;
&lt;td&gt;-0.0009%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Note that this return would be in ETH tokens, and not Euros or USD. Looking at the table, the crypto winter is clear, and the only positive return is ETH Staking (you can check more &lt;a href="https://ethereum.org/en/staking/" rel="noopener noreferrer"&gt;here&lt;/a&gt; on how it works). It's not necessary to be a great Math genius to understand that the best solution to optimize our risk-reward portfolio, a huge chunk (100% basically) of the allocation should be placed under ETH Staking, looking just at expected returns. It's the only positive one 😅. We can use this knowledge to scope out the values presented as results by our Genetic Algorithm. If the optimal solution, when the termination criteria are reached, has higher allocations on negative expected return Assets, then something is not right. Pretty easy, no?&lt;/p&gt;

&lt;p&gt;Let's start by modelling our problem in a structure that corresponds to the framework's API.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Gene:&lt;/strong&gt; is a value ranging from 0 to 100, and represents the percentage of portfolio allocation to an asset. Initialized randomly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Chromossome&lt;/strong&gt;: has a list of 10 &lt;strong&gt;Genes&lt;/strong&gt;. One for each different asset we want to analyse. We made sure that the initialized sum of the 10 assets was under 100 (we can't allocate more than 100% of our portfolio).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Population&lt;/strong&gt;: 100 different &lt;strong&gt;Chromossomes&lt;/strong&gt;. After each &lt;strong&gt;evolution&lt;/strong&gt; round, we classify each &lt;strong&gt;Chromossome&lt;/strong&gt; with the &lt;strong&gt;Fitness Function&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fitness Function:&lt;/strong&gt; For this first approach, the fitness of a given &lt;strong&gt;Chromossome&lt;/strong&gt; is just multiplying the algorithm-predicted allocation with the Expected Return for that respective asset, and summing everything at the end. That would give us the global expected return for our portfolio. Example:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="nv"&gt;@expected_returns&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;0.04&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;0.000054&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;0.000017&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;0.000038&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;0.00011&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;genes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;fitness&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 
 &lt;span class="n"&gt;expected_returns&lt;/span&gt;
 &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;zip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;genes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
 &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;g&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
 &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Termination Criteria:&lt;/strong&gt; When the population age reaches 10000. There were other possibilities for termination criteria, but you should definitely read the book to understand more about this. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Well, after running everything a couple of times the results were just random (yeah, I ran a couple of times just to make sure the results wouldn't be different). What was wrong with it, then?&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;The culprit was the &lt;strong&gt;mutation&lt;/strong&gt; function. I didn't talk about that in the previous paragraphs because I was relying on the function from the framework to run our algorithm. Big mistake. That function simply shuffled &lt;strong&gt;Genes&lt;/strong&gt; around inside the same &lt;strong&gt;Chromossome&lt;/strong&gt;, meaning that every time a mutation happened to a &lt;strong&gt;Chromossome&lt;/strong&gt; in the &lt;strong&gt;evolution&lt;/strong&gt; process, values from the initialization would just be shuffled, and not adding any entropy to the values themselves. That's why we always saw random values allocated for each Asset, it was just the random initialization.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The solution for this required updating the &lt;strong&gt;mutation&lt;/strong&gt; function. Instead of shuffling around the genes, the new mutation function should increase or decrease the current value randomly, so that values change throughout evolution. The code below solved that issue.
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="n"&gt;new_genes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 
  &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chromosome&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;genes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;gene&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; 
    &lt;span class="n"&gt;range&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gene&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;updated_value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gene&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;range&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="n"&gt;range&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;updated_value&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;do&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="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;updated_value&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;However, problems didn't stop here. Now, we were having the best solution presented with &lt;code&gt;0&lt;/code&gt; at almost every gene, including the ETH Staking one, which is the go-to asset. This one was more difficult to find out the root cause because there were two different reasons.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Penalizing too much the very good &lt;strong&gt;Chromossomes&lt;/strong&gt;. What's this about? Since that in the new &lt;strong&gt;mutation&lt;/strong&gt; function, we're increasing the value randomly, sometimes the sum of all &lt;strong&gt;genes&lt;/strong&gt; would be higher than 100 (something that we only account for in the initialization). Our &lt;strong&gt;fitness function&lt;/strong&gt; had a small clause that if the sum of all &lt;strong&gt;genes&lt;/strong&gt; was higher than 100, it would return &lt;code&gt;0&lt;/code&gt; for that &lt;strong&gt;Chromossome's&lt;/strong&gt; fitness, because it would be an invalid individual. With this, we were penalizing too much the &lt;strong&gt;Chromossomes&lt;/strong&gt; reaching close to 100% allocation, effectively killing all of them until only smaller values remain in the population. The solution was to remove that clause from the &lt;strong&gt;fitness function&lt;/strong&gt; and normalise the values if the overall sum went over 100.&lt;/li&gt;
&lt;li&gt;Penalizing too much the very bad &lt;strong&gt;Chromossomes&lt;/strong&gt;. Looking at the &lt;strong&gt;mutation&lt;/strong&gt; function there is the following line &lt;code&gt;if updated_value &amp;lt;= 0, do: 0, else: updated_value&lt;/code&gt;. The problem with this was that if a gene reached 0 or below (because of randomly decreasing the old value), the gene would never "recover" from that &lt;code&gt;0&lt;/code&gt; value, effectively locking most of the assets' allocations to 0. 
Updating the line to something like: &lt;code&gt;if updated_value &amp;lt;= 0, do: Enum.random(0..2), else: updated_value&lt;/code&gt; fixed this problem, because it gives a small chance for that &lt;strong&gt;gene&lt;/strong&gt; to have a different allocation value, and not just 0.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;After these changes, we're getting pretty acceptable results where the Genetic Algorithm's best solution, presents ETH Staking with &amp;gt;90% allocations, and the other assets take home the rest 10%.&lt;/p&gt;

&lt;h3&gt;
  
  
  Using Sharpe Ratio as the Fitness Function
&lt;/h3&gt;

&lt;p&gt;I've already explained what Sharpe Ratio is and why it's the final approach for this problem. TLDR, it also takes into account the inherent variation of Assets (associated risk) and not just their expected returns.&lt;/p&gt;

&lt;p&gt;Recalling the &lt;strong&gt;Sharpe Ratio&lt;/strong&gt; function from one of the images above, we need to know the &lt;code&gt;portfolio expected returns&lt;/code&gt;, &lt;code&gt;risk-free rate&lt;/code&gt; and the &lt;code&gt;portfolio's standard deviation&lt;/code&gt;. We already know how to calculate the first two, we just need to calculate the standard deviation.&lt;/p&gt;

&lt;p&gt;According to &lt;a href="https://www.wallstreetmojo.com/portfolio-standard-deviation/" rel="noopener noreferrer"&gt;WallStreetMojo&lt;/a&gt;, the following formula is how you do it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.sanity.io%2Fimages%2F5aprln8a%2Fproduction%2F0be7aa171ba2c4879b2771f5ea946c818d552a15-1024x461.webp%3Fw%3D450" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.sanity.io%2Fimages%2F5aprln8a%2Fproduction%2F0be7aa171ba2c4879b2771f5ea946c818d552a15-1024x461.webp%3Fw%3D450" alt="portfolio-standard-deviation"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Where:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;wX&lt;/code&gt;: allocated "weight" to asset &lt;code&gt;X&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;R(kX, kY)&lt;/code&gt;: the correlation between asset &lt;code&gt;X&lt;/code&gt; and &lt;code&gt;Y&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;σX&lt;/code&gt;: Standard Deviation for asset &lt;code&gt;X&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We pre-calculated all of the correlations between Assets, and the Standard Deviation for each one. Implemented the function to calculate the full portfolio's Standard Deviation, and replaced the &lt;strong&gt;fitness function&lt;/strong&gt; above with the complete formula for &lt;strong&gt;Sharpe Ratio&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The results were just bad, and nonsense all over again... The problem this time was that the time until the end of the Hackathon was running out, and there were other things in the project that needed to be done, so after a couple of hours of debugging it, we decided to move over.&lt;/p&gt;

&lt;p&gt;It's a bit of a bummer finishing things this way, but at this point, the issue was probably in the pre-calculated values and not in the Genetic Algorithm itself, as we just changed the fitness calculation. The main thing for this blog post is the algorithms, and not &lt;em&gt;Hackathon rushed statistics&lt;/em&gt;...&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;Looking back at how things went, I should have finished reading the book before the Hackathon 😅, to reduce some of the inherent stress that comes with participating in one, instead of going insane debugging why my population doesn't evolve properly. &lt;/p&gt;

&lt;p&gt;Despite not reaching a perfect or even a "working" solution, I learned a lot about tweaking these algorithms (after all, evolution is not that simple). We also ended up winning a prize of 1500$ awarded by &lt;a href="https://protocol.ai/" rel="noopener noreferrer"&gt;Protocol Labs&lt;/a&gt; for the third-best project of the hackathon using one of their products (&lt;a href="https://docs.bacalhau.org/" rel="noopener noreferrer"&gt;Bacalhau&lt;/a&gt; - cod in Portuguese, which comes from the extended name of &lt;code&gt;Computing over Data&lt;/code&gt;). We used &lt;code&gt;Bacalhau&lt;/code&gt; to run our genetic algorithms simulation in a decentralized network of servers, that automatically stores its results in &lt;a href="https://ipfs.tech/" rel="noopener noreferrer"&gt;IPFS&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.sanity.io%2Fimages%2F5aprln8a%2Fproduction%2Ff990ab149d51b87abff80c7b61f209fe7edd4f9a-746x193.png%3Fw%3D450" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.sanity.io%2Fimages%2F5aprln8a%2Fproduction%2Ff990ab149d51b87abff80c7b61f209fe7edd4f9a-746x193.png%3Fw%3D450" alt="protocol-labs-prize"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Have a look at the code written during the Hackathon in our &lt;a href="https://github.com/finiam/matusalem" rel="noopener noreferrer"&gt;Github repo&lt;/a&gt; (not just the Genetic Algorithms code), and feel free to reach out if you have any questions. A small disclaimer, remember that it is all Hackathon code, and it gets a bit messy...&lt;/p&gt;

&lt;p&gt;Thanks for reading, and see you in the next one 👋 &lt;/p&gt;

</description>
      <category>elixir</category>
      <category>geneticalgorithms</category>
      <category>portfolio</category>
      <category>optimization</category>
    </item>
    <item>
      <title>NFT Attribute Types: A rarity system (but with Maths)</title>
      <dc:creator>José Diogo Viana</dc:creator>
      <pubDate>Fri, 18 Mar 2022 10:12:04 +0000</pubDate>
      <link>https://dev.to/finiam/nft-attribute-types-a-rarity-system-but-with-maths-2moi</link>
      <guid>https://dev.to/finiam/nft-attribute-types-a-rarity-system-but-with-maths-2moi</guid>
      <description>&lt;p&gt;At this point in time, almost everyone has heard about NFTs. Even if you don't really understand how they work, you associate them with images of Apes or Cats. Check a couple of them, just for reference: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://opensea.io/collection/boredapeyachtclub" rel="noopener noreferrer"&gt;Bored Ape Yacht Club&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://opensea.io/collection/cryptokitties" rel="noopener noreferrer"&gt;CryptoKitties&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://opensea.io/collection/cryptopunks" rel="noopener noreferrer"&gt;CryptoPunks&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Technically, and also theoretically, NFTs are not just that, but for this blog post, we'll just stick with profile pictures that have different attributes. If you want to know a bit more in-depth about NFTs in general and other possible applications, go check &lt;a href="https://blog.finiam.com/blog/a-pragmatic-nft-analysis/" rel="noopener noreferrer"&gt;Francisco's post&lt;/a&gt;, also for the initiates in the area.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What are these attributes, you ask?&lt;/strong&gt; Well, they are associated with the metadata of the Asset, and in the case of the profile pics, these attributes will define what your final image looks like and create a perceived sense of scarcity (or rarity).&lt;/p&gt;

&lt;p&gt;As an example, we will use the Bored Ape owned by our good friend &lt;a href="https://twitter.com/rmdmac" rel="noopener noreferrer"&gt;Roberto&lt;/a&gt; from Subvisual.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.sanity.io%2Fimages%2F5aprln8a%2Fproduction%2F47e7be666ce0ac80ed840349064dd8d9b6293d0a-600x600.png%3Fw%3D350" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.sanity.io%2Fimages%2F5aprln8a%2Fproduction%2F47e7be666ce0ac80ed840349064dd8d9b6293d0a-600x600.png%3Fw%3D350" alt="ape"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Checking on the metadata, provided by its &lt;a href="https://opensea.io/assets/0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d/7020" rel="noopener noreferrer"&gt;OpenSea page&lt;/a&gt;, this token has the following attributes, and respective rarities:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Background: blue (12%);&lt;/li&gt;
&lt;li&gt;Clothes: tweed suit (1%);&lt;/li&gt;
&lt;li&gt;Eyes: coins (5%);&lt;/li&gt;
&lt;li&gt;Fur: gray (5%);&lt;/li&gt;
&lt;li&gt;Hat: Faux Hawk (1%);&lt;/li&gt;
&lt;li&gt;Mouth: Phoneme Oh (2%);&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;How were these percentages calculated? We'll try to better understand them below, and try to come up with our own way of pre-calculating a rarity for an attribute.&lt;/p&gt;

&lt;p&gt;If this got your attention, and you want to know more about how overall rarities are calculated (how someone judges an NFT as rarer than another), go check &lt;a href="https://raritytools.medium.com/ranking-rarity-understanding-rarity-calculation-methods-86ceaeb9b98c" rel="noopener noreferrer"&gt;this post&lt;/a&gt; from &lt;a href="https://rarity.tools/" rel="noopener noreferrer"&gt;rarity.tools&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are we doing and why?
&lt;/h2&gt;

&lt;p&gt;We want to pre-generate the metadata for a set of NFTs that will have several attributes. This metadata has information on the traits of that specific NFT, in this case, each attribute type and the respective value.&lt;/p&gt;

&lt;p&gt;For example, if we want to generate the metadata for an NFT that has different types of &lt;strong&gt;glasses&lt;/strong&gt;, the plan is to calculate the total number of tokens that will have &lt;strong&gt;round&lt;/strong&gt;, &lt;strong&gt;square&lt;/strong&gt;, &lt;strong&gt;emoji&lt;/strong&gt; glasses, or even no glasses at all. This will specify the rarity of each attribute type.&lt;/p&gt;

&lt;p&gt;The question of how other &lt;em&gt;Buidlers&lt;/em&gt; are doing this came up in one of the projects we are currently working at, as Finiam. We assumed right away that they should obey some kind of mathematical rule, defined by the creators, distributing attribute values, for the final image to have a "real" sense of rarity and scarcity... But, there's also the chance that each attribute value is just licking the finger and sticking it up in the wind. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.sanity.io%2Fimages%2F5aprln8a%2Fproduction%2F010e8dc0679749a9044519ee0f9e75f311ba2d23-640x640.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.sanity.io%2Fimages%2F5aprln8a%2Fproduction%2F010e8dc0679749a9044519ee0f9e75f311ba2d23-640x640.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This way, Resende and I started looking for references and if someone had documented their journey of calculating rarities and how they had done it. We found no evidence that they did have used mathematical distributions, or at least they weren't open about it at all.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bored Ape Yacht Club - rarities breakdown
&lt;/h3&gt;

&lt;p&gt;Resende had developed a &lt;strong&gt;Jupyter notebook&lt;/strong&gt; where you can just introduce the URI of the metadata for a certain contract, and then the script creates a dictionary (map) with the overall information of each attribute type.&lt;/p&gt;

&lt;p&gt;We decided to inspect the &lt;strong&gt;BAYC&lt;/strong&gt; contract. Looking at their &lt;a href="https://opensea.io/collection/boredapeyachtclub" rel="noopener noreferrer"&gt;OpenSea collection page&lt;/a&gt;, you can see that they have 7 different attributes, and the number of types for each one varies from 6 to 43. For the sake of this blog post, we'll just show you two of the generated plots. If interested to get more information give us a nudge on &lt;a href="https://twitter.com/wearefiniam" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The following plots represent a histogram for each attribute type of &lt;strong&gt;Clothes&lt;/strong&gt; and &lt;strong&gt;Eyes&lt;/strong&gt;, respectively.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.sanity.io%2Fimages%2F5aprln8a%2Fproduction%2F820bcb3d4e2e972378bab2dae9000ca4d5f04e28-1800x720.png%3Fw%3D650" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.sanity.io%2Fimages%2F5aprln8a%2Fproduction%2F820bcb3d4e2e972378bab2dae9000ca4d5f04e28-1800x720.png%3Fw%3D650" title="Clothes attribute histogram." alt="Clothes"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.sanity.io%2Fimages%2F5aprln8a%2Fproduction%2F6552e5eb344e18f309229a2423abd6da7381be46-1800x720.png%3Fw%3D650" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.sanity.io%2Fimages%2F5aprln8a%2Fproduction%2F6552e5eb344e18f309229a2423abd6da7381be46-1800x720.png%3Fw%3D650" title="Eyes attribute histogram." alt="Eyes"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We won't discuss if they used some mathematical distribution to calculate each amount or if it was eyeballing, but you can try to estimate if this really uses any math as the base.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting our hands dirty
&lt;/h2&gt;

&lt;p&gt;After this, for us, it was very simple: &lt;strong&gt;"Let's do it ourselves!"&lt;/strong&gt; The perfect excuse to finally put in practice those Calculus and Statistics lessons in college that we never got to use, until now!&lt;/p&gt;

&lt;p&gt;This way, the goal to develop something interactive to calculate the number of NFTs that will have each type of attribute, was set.&lt;/p&gt;

&lt;p&gt;Note: &lt;a href="https://achekroud.substack.com/p/d8f13e0a-ae26-40e4-bff2-beacb2916ff0?utm_source=url" rel="noopener noreferrer"&gt;Here&lt;/a&gt; it's also possible to check a statistical analysis on a different type of projects (eg. generative art from &lt;a href="https://www.artblocks.io/" rel="noopener noreferrer"&gt;Artblocks.io&lt;/a&gt;. So if you're into statistics give it a look also.)&lt;/p&gt;

&lt;h2&gt;
  
  
  Looking at mathematical distributions and functions
&lt;/h2&gt;

&lt;p&gt;The first step was looking at the plots of some distributions that we already knew and seeing which ones could be adapted into defining a cool rarity system.&lt;/p&gt;

&lt;p&gt;We looked into a bunch of them, and to be honest, we don't remember anymore which ones were. Some weren't even a distribution, like the &lt;code&gt;sin&lt;/code&gt; function, that we also investigated, because of its malleability to have the 0's where we want them and also for the waving shape. So, as a summary, we'll only talk about the two that got selected.&lt;/p&gt;

&lt;h3&gt;
  
  
  Negative Exponential
&lt;/h3&gt;

&lt;p&gt;After our initial brainstorm session, we knew we wanted to use the negative exponential function. Just looking at the plot, it screams &lt;strong&gt;rarity system&lt;/strong&gt;. How? Let's have a look at the example below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.sanity.io%2Fimages%2F5aprln8a%2Fproduction%2F22c75480780aeb309a424f8b68e9d7e2f56f6797-475x207.png%3Fw%3D650" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.sanity.io%2Fimages%2F5aprln8a%2Fproduction%2F22c75480780aeb309a424f8b68e9d7e2f56f6797-475x207.png%3Fw%3D650" alt="negative exponential"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Imagine dividing the area of the negative exponential function (&lt;a href="https://en.wikipedia.org/wiki/Integral" rel="noopener noreferrer"&gt;integral in the Wikipedia&lt;/a&gt; if you're not familiar with it) by the number of total attributes we want to calculate a rarity for, just like it is in the image. In that case, we have 25 columns, that would represent 25 different attributes. We get each rarity by calculating the approximate area of each column and dividing it by the total area, thus getting a percentage. This percentage then represents the mathematical distribution and the respective percentage of occurrences for that attribute.&lt;/p&gt;

&lt;p&gt;I know I just described how distributions are calculated with Integrals, but the point here is that we get a clear decline of the area of each column, giving us the proportion for each attribute from the most common to the rarest.&lt;/p&gt;

&lt;h3&gt;
  
  
  Poisson Distribution
&lt;/h3&gt;

&lt;p&gt;Then, the other option that we also went with is the Poisson distribution, because it has a cool name. Well, not only that but because it offers a very different perspective of the negative exponential and enables more possible combinations of attributes rarity.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.sanity.io%2Fimages%2F5aprln8a%2Fproduction%2Fb944c1b10ed4feab0e8af57b165a662725938f17-752x362.png%3Fw%3D650" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.sanity.io%2Fimages%2F5aprln8a%2Fproduction%2Fb944c1b10ed4feab0e8af57b165a662725938f17-752x362.png%3Fw%3D650" alt="poisson"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Looking at the image above, you can see what's that difference I was mentioning. Just looking at the bars you might confuse the Poisson distribution with a Normal distribution, but they are slightly different, and that's the real reason we chose it.&lt;/p&gt;

&lt;p&gt;The Poisson Distribution has a lower bound at 0 and no upper bound, while the Normal Distribution has no bounds at all. Also, unlike a normal distribution, which is always symmetric, the basic shape of a Poisson distribution changes. To know a bit more about these differences check &lt;a href="https://www.theanalysisfactor.com/differences-between-normal-and-poisson-distributions/" rel="noopener noreferrer"&gt;this&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The same mathematical approach with the negative exponential to calculate areas and percentages, also applies here, as with other distributions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Taking advantage of Google Sheets
&lt;/h2&gt;

&lt;p&gt;We didn't want to implement these distributions ourselves, despite understanding the maths behind it. So we turn our heads to the good friend &lt;strong&gt;Google Sheets&lt;/strong&gt; that already has a bunch of distributions implemented, and can be used out of the box.&lt;/p&gt;

&lt;p&gt;Another good thing about Google Sheets, or any other famous spreadsheet, is that it's also easily programmable and interactive. We can define cells where we change the inputs, and others displaying results, change accordingly.&lt;/p&gt;

&lt;p&gt;And finally, plotting results and conclusions is also effortless, and pretty much necessary for this use case. It's kinda cool to visualize what different attribute rarities would look like.&lt;/p&gt;

&lt;h3&gt;
  
  
  Making it dynamic with configurable values
&lt;/h3&gt;

&lt;p&gt;As I hinted earlier, we wanted to do it configurable so we could test different combinations and options with ease.&lt;/p&gt;

&lt;p&gt;Two things that we need to be interactive are the &lt;code&gt;number of tokens&lt;/code&gt; to be emitted, or in other words, the amount of NFTs that will exist in this collection and the &lt;code&gt;number of different possibilities an attribute will have&lt;/code&gt;, so we can calculate the distribution only for those values.  &lt;/p&gt;

&lt;p&gt;Also, looking at the Poisson Distribution function, we see that it's also possible to make &lt;code&gt;λ&lt;/code&gt; vary. &lt;code&gt;λ&lt;/code&gt; must be greater than 0, and it is equal to the expected value of X and also to its variance (&lt;a href="https://en.wikipedia.org/wiki/Variance" rel="noopener noreferrer"&gt;variance in Wikipedia&lt;/a&gt;). This way, we can have even more combinations and possibilities.&lt;/p&gt;

&lt;h3&gt;
  
  
  Calculating rarities with Poisson
&lt;/h3&gt;

&lt;p&gt;To calculate rarities with the Poisson distribution we used the function &lt;code&gt;POISSON.DIST(x, mean, [cumulative])&lt;/code&gt; that &lt;strong&gt;Google Sheets&lt;/strong&gt; already provides. &lt;strong&gt;Sheets&lt;/strong&gt; provides more information on it, but basically, in our situation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;x&lt;/code&gt; will be the id of the attribute ranging from &lt;code&gt;0&lt;/code&gt; to &lt;code&gt;total attributes&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;f&lt;/code&gt; will be the mean of the Poisson distribution function (λ).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;[cumulative]&lt;/code&gt; is a boolean to identify if we want to use the cumulative distribution function rather than the distribution function (the sum of all columns until the &lt;code&gt;X&lt;/code&gt; we are using instead of just the column &lt;code&gt;X&lt;/code&gt;, using the same analogy as above).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However, just doing this we have a slight problem... The Poisson Distributed is not bounded to the right of the X-axis, so if we just want to calculate the distribution for a small number of attributes, there's the chance that the probabilities don't add up to 100%, because we're missing some x-values.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.sanity.io%2Fimages%2F5aprln8a%2Fproduction%2Fb68f8f510eca5c90ce8d9f0a7951a42a0163383a-821x511.png%3Fw%3D650" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.sanity.io%2Fimages%2F5aprln8a%2Fproduction%2Fb68f8f510eca5c90ce8d9f0a7951a42a0163383a-821x511.png%3Fw%3D650" alt="poisson-without-cumulative"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Looking at the generated plot above using only the distribution value for 15 different attributes of 10000 tokens (NFTs), and with a mean value of 10, we see that some values are missing to the right, and if we add all of the probabilities we get just 91.65%. The rest 8.35% are for values of &lt;code&gt;X&lt;/code&gt; above 15, which we don't want. The objective is if we have only 15 attributes, the sum of their probabilities must be 100%.&lt;/p&gt;

&lt;p&gt;So the solution we came up with is calculating the missing percentage to 100% and dividing it by the number of attributes, and adding this part to each attribute. Using the example above, we would divide the 8.35% that is missing by 15 (equating to approximately 0.56%), and add this value to each existing column, therefore spreading this exceed evenly.&lt;/p&gt;

&lt;p&gt;The final formula is this, using the cumulative version to actually obtain the exceeding probabilities to the right of the function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;POISSON.DIST(x, mean, false) + ((1 - POISSON.DIST(totalAttributes - 1, mean, true)) / totalAttributes)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Below, we have the updated version, and if we compare the two plots, we see that now the first attributes have a probability different than 0, because we are also taking into account the exceeding values, and the sum of all of them is equal to 100% or the total number of tokens to be created.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.sanity.io%2Fimages%2F5aprln8a%2Fproduction%2F8b0bc69fafc9ea91ba843d12aa47ed7942232562-824x511.png%3Fw%3D650" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.sanity.io%2Fimages%2F5aprln8a%2Fproduction%2F8b0bc69fafc9ea91ba843d12aa47ed7942232562-824x511.png%3Fw%3D650" alt="poisson-with-cumulative"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Calculating rarities with Negative Exponential
&lt;/h3&gt;

&lt;p&gt;For the negative exponential distribution, we used the function &lt;code&gt;EXPONDIST(x, lambda, [cumulative])&lt;/code&gt;. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;x&lt;/code&gt; will be the id of the attribute raging from &lt;code&gt;0&lt;/code&gt; to &lt;code&gt;total attributes&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;lambda&lt;/code&gt; is the parameter of the distribution, often called the rate parameter.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;[cumulative]&lt;/code&gt; represents the same as in the Poisson one.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this case, we are leaving the &lt;code&gt;lambda&lt;/code&gt; fixed as 1, for simplicity. This distribution was a bit more complicated to get around so we went with the shortest path to having anything providing correct results.&lt;/p&gt;

&lt;p&gt;The first problem arose from the idea of dividing the function into columns. This process was not that direct, as in the Poisson case. The formula we arrived at to have a proper result, is the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;EXPONDIST((4.60517 / totalAttributes) * X, 1, false)  - EXPONDIST((4.60517 / totalAttributes) * (X + 1), 1, false)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why the subtraction, and why that &lt;code&gt;4.60517&lt;/code&gt;?? First, let's have look at the "strange" value and we got it.&lt;/p&gt;

&lt;p&gt;The value (~4.6) comes from solving the following expression of &lt;code&gt;- (ln (1 - 0.99))&lt;/code&gt;. This is obtained from the integral of the negative exponential function &lt;code&gt;e^-x&lt;/code&gt; and trying to obtain the &lt;code&gt;X&lt;/code&gt; value where the area of the function is approximately 0.99. If you want to check the step-by-step solution, have a look at this &lt;a href="https://www.wolframalpha.com/input?i2d=true&amp;amp;i=solve+0.99+%3D+Integrate%5BPower%5Be%2C-x%5D%2C%7Bx%2C0%2Cx%7D%5D" rel="noopener noreferrer"&gt;Wolfram solution&lt;/a&gt; for it. Following the same approach, we can divide it into smaller columns and get the relative proportion. But why 0.99? As this function tends to 1 at the infinity, we chose to use 99% as the full area, otherwise, percentages for the rarest attributes would be basically 0.&lt;/p&gt;

&lt;p&gt;Returning to the expression above &lt;code&gt;(4.60517 / totalAttributes) * X&lt;/code&gt; we divide the area by the number of attributes and multiply it by the value of X we are calculating at the time, simulating the column divisions referenced above.&lt;/p&gt;

&lt;p&gt;The same issue with boundaries that happened in the Poisson Distribution also happens here, so we used the same solution. Calculate the exceeding values, and add them evenly to each attribute percentage.&lt;/p&gt;

&lt;p&gt;This way both distributions may not produce the values as they would in normal mathematical conditions, as they were adapted to fit this very specific problem with a discrete number of variables. Note: we are not mathematicians so we are sure that there is some obscure way of doing the same thing but &lt;em&gt;mathematically correct&lt;/em&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  How do we use this for tangible information?
&lt;/h3&gt;

&lt;p&gt;The final question is how we retrieve the actual number of tokens that will have each type of attribute. For that, we decide to do a quick demo.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.sanity.io%2Fimages%2F5aprln8a%2Fproduction%2Fdef29a253d27969b7b1f735ab1d96373a55d6f04-800x450.gif%3Fw%3D650" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.sanity.io%2Fimages%2F5aprln8a%2Fproduction%2Fdef29a253d27969b7b1f735ab1d96373a55d6f04-800x450.gif%3Fw%3D650" alt="demo gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the video above, we set the number of tokens to 1000 and 5 different attributes (where we set some fake attribute names just to help identify stuff in the long run), and then the mean value of the Poisson Distribution to 3 (basically setting the most common id). It's also possible to see how the cells and plots change when we change the different configurable values.&lt;/p&gt;

&lt;p&gt;Red columns represent the actual number of tokens that we want for a specific attribute, based on the predictions given by the distribution we choose, as they produce decimal values that can't be applied to our use case (a token must be a full unit).&lt;/p&gt;

&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;Looking back at this experience, there's a slight chance that the solution was a bit of over-engineering, but it was the perfect opportunity to put this knowledge to the test.&lt;/p&gt;

&lt;p&gt;We hope you have liked this approach to rarities in NFTs, and feel free to reach out if you want to know more about this spreadsheet. &lt;/p&gt;

&lt;p&gt;Have a nice one and see you in the next blogpost 👋&lt;/p&gt;

</description>
      <category>crypto</category>
      <category>web3</category>
      <category>nfts</category>
    </item>
    <item>
      <title>Developing a keyboard heatmap and customizing keys with Karabiner</title>
      <dc:creator>José Diogo Viana</dc:creator>
      <pubDate>Wed, 02 Jun 2021 12:58:10 +0000</pubDate>
      <link>https://dev.to/finiam/developing-a-keyboard-heatmap-and-customizing-keys-with-karabiner-59ai</link>
      <guid>https://dev.to/finiam/developing-a-keyboard-heatmap-and-customizing-keys-with-karabiner-59ai</guid>
      <description>&lt;p&gt;For the last 5 years, I've been using an Apple Magic Keyboard. There wasn't any major reason to be using it, except having the same layout of my laptop, but it did the job pretty nicely.&lt;/p&gt;

&lt;p&gt;After joining Finiam, I started looking more into how I used my keyboard, and how I could become more efficient with it. A thing that was bothering me for some time was the fact that my keyboard had a Portuguese layout, and every time I wanted to make &lt;code&gt;{&lt;/code&gt;, &lt;code&gt;]&lt;/code&gt; characters, &lt;strong&gt;Finger Gymnastics 101&lt;/strong&gt;, would be required. I know I could always change the input language, but it wasn't the same thing. This was just the excuse I needed to get a new keyboard and with a US layout. So I went by and bought a &lt;strong&gt;Keychron k2v2&lt;/strong&gt; and set myself up to start looking for more ways of having it optimized for me.&lt;/p&gt;

&lt;p&gt;The first thing that I did was installing &lt;a href="https://karabiner-elements.pqrs.org/" rel="noopener noreferrer"&gt;Karabiner-Elements&lt;/a&gt;. It's a keyboard customizer for macOS, where you can easily swap a key with another, use a base set of complex modifications developed by the community or create your own rules. I started investigating and trying new combinations... But then it came to my mind: &lt;/p&gt;

&lt;p&gt;"Wouldn't it be nice if I could make a heatmap of my keystrokes and then create aliases or easier configurations for things that I identify as the most used?" &lt;/p&gt;

&lt;p&gt;Well, of course, it would, and I can do it as a nice excuse to play with Elixir again. So let's get our hands dirty and get into some code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Developing the Heatmapper
&lt;/h2&gt;

&lt;p&gt;First, we need to collect our keystrokes. This would be a nice challenge to do, but I'll leave it on the side for now. So, I started looking into existing keyloggers in Github (Yeah, I know this sounds a bit weird because the chosen one could be malicious - I'm aware of that possibility). After a few possibilities, I found out &lt;a href="https://github.com/caseyscarborough/keylogger" rel="noopener noreferrer"&gt;caseyscarborough/keylogger&lt;/a&gt;, went through the code and it seemed simple to use and make changes to adjust it for my specific needs. Now let's dive into the heatmap and drawing part.&lt;/p&gt;

&lt;p&gt;From the beginning I wanted the heatmapper to draw the keyboard and not use a base SVG layout (or something similar). Zamith's &lt;a href="https://github.com/zamith/mogrify_draw" rel="noopener noreferrer"&gt;mogrify_draw&lt;/a&gt; enables me to draw keyboard keys in a simple way using &lt;code&gt;mogrify&lt;/code&gt; as the base.&lt;/p&gt;

&lt;p&gt;Another thing was that since the code will handle drawing a keyboard, it would be an even cooler solution to be able to draw any keyboard, given the provided structure of the keys. &lt;/p&gt;

&lt;p&gt;The first step is to parse the log file of keystrokes provided. As I mentioned earlier, I made some changes to the keylogger and this version can be found &lt;a href="https://github.com/zediogoviana/keylogger" rel="noopener noreferrer"&gt;here&lt;/a&gt;. You can then follow the instructions in the &lt;code&gt;README&lt;/code&gt; on how to use it, but it outputs to the file the following on each keystroke read:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;keycode&amp;gt;::&amp;lt;keyname&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I'll probably remove &lt;code&gt;keyname&lt;/code&gt; in the future, as I'm not using it in the application itself (just for debugging purposes), and therefore reduce the size of the log file.&lt;/p&gt;

&lt;p&gt;Looking, at the code, we first open the file and then parse its content to generate a map of frequencies. In the &lt;code&gt;parse_line/1&lt;/code&gt; function, it uses a regex to get the &lt;code&gt;keycode&lt;/code&gt; in each line.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;contents&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;frequencies&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;contents&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;contents&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;contents&lt;/span&gt;
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;trim:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;parse_line&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;&amp;amp;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;is_nil&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;&amp;amp;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;frequencies&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;normalize_frequencies&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;normalize_frequencies/1&lt;/code&gt; function, calculates the maximum value of keystrokes (the max frequency), and then for each value in the frequencies map, returns a normalized value: &lt;code&gt;value/max&lt;/code&gt;. See the example below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# log file contents
31::o
45::n
8::c
31::o

# frequencies map after parse
frequencies = %{ 31: 2, 45: 1, 8: 1 }

# frequencies normalized
max_frequency = 2
normalized = %{ 31: 2/2, 45: 1/2, 8: 1/2 }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that we have normalized values, we can jump to the drawing process. The first thing to do here is to implement the logic for several keyboard layouts to be drawn, so together with the path to the log file, it's also necessary to pass which keyboard type to draw.&lt;/p&gt;

&lt;p&gt;For organizational purposes, I decided to divide the layouts by keyboard brand first, and then by type. For example, below we have the types &lt;code&gt;:keychron&lt;/code&gt;, &lt;code&gt;:macbook&lt;/code&gt; and &lt;code&gt;:niz&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;get_keyboard_layout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;keyboard&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="ss"&gt;:keychron&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; 
      &lt;span class="n"&gt;keyboard_layout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Layouts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Keychron&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;keyboard&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="ss"&gt;:macbook&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; 
      &lt;span class="n"&gt;keyboard_layout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Layouts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Macbook&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;keyboard&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="ss"&gt;:niz&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; 
      &lt;span class="n"&gt;keyboard_layout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Layouts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Niz&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;keyboard&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:no_model&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;get_keyboard_layout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:keychron&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:k2v2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Calling the function with a valid model and type returns the keyboard layout. Each layout is under &lt;code&gt;layouts/&amp;lt;model&amp;gt;.ex&lt;/code&gt;, and consists of a function with the name of the keyboard type and the following structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;# file: layouts/keychron.ex&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;k2v2&lt;/span&gt; &lt;span class="k"&gt;do&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;span class="ss"&gt;size:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;keycode:&lt;/span&gt; &lt;span class="mi"&gt;53&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;name:&lt;/span&gt; &lt;span class="s2"&gt;"esc"&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="p"&gt;[&lt;/span&gt;
      &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;size:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;keycode:&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;name:&lt;/span&gt; &lt;span class="s2"&gt;"`~"&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="o"&gt;...&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's basically a list of rows of the keyboard, where each row, the list of keyboard keys is defined. A keyboard key can be defined with &lt;code&gt;keycode&lt;/code&gt;, &lt;code&gt;name&lt;/code&gt;, and &lt;code&gt;size&lt;/code&gt; (assuming that a size of 2, will draw a key with a width of &lt;strong&gt;2 * DEFAULT_KEY_PX_SIZE&lt;/strong&gt; and a fixed height of &lt;strong&gt;DEFAULT_KEY_PX_SIZE&lt;/strong&gt;). It is also possible to define a &lt;code&gt;height&lt;/code&gt; and &lt;code&gt;width&lt;/code&gt; instead of &lt;code&gt;size&lt;/code&gt; if we wish to draw keys with different heights.&lt;/p&gt;

&lt;p&gt;Now let's see how everything is drawn.&lt;/p&gt;

&lt;p&gt;The first step is using &lt;code&gt;mogrify_draw&lt;/code&gt; to paint the base image where everything will be laid next. It'll create a png with the respective width and height of the keyboard we want to draw.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;draw_base_image&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;keyboard&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="p"&gt;%&lt;/span&gt;&lt;span class="no"&gt;Mogrify&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;path:&lt;/span&gt; &lt;span class="s2"&gt;"heatmap.png"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;ext:&lt;/span&gt; &lt;span class="s2"&gt;"png"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;custom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"size"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="mi"&gt;95&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;keyboard_width&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;x&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="mi"&gt;95&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;keyboard_height&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"white"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To draw each keyboard key, we go through each row, and subsequently across all row's keys, keeping track of the &lt;code&gt;xx_position&lt;/code&gt; and &lt;code&gt;yy_position&lt;/code&gt; that we are at the moment. With this information, we know the exact place in pixels to start drawing the key in the base image. But before actually drawing, we get the respective frequency for that key and the RGB color calculated accordingly to the frequency passed. Then, we draw a rounded rectangle (the key) and a white text over it (the key name).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;draw_key&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;xx_position&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;yy_position&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;frequencies&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;freq&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;frequencies&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;to_string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;keycode&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;red&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;green&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;blue&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;get_rgb_color&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;freq&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;image&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;custom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"fill"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"rgb(&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;red&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;,&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;green&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;,&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;blue&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;)"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;rounded_rectangle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="n"&gt;xx_position&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nv"&gt;@key_size&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;yy_position&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nv"&gt;@key_size&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;xx_position&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nv"&gt;@key_size&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nv"&gt;@key_size&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;key_width&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="n"&gt;yy_position&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nv"&gt;@key_size&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nv"&gt;@key_size&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;key_height&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="mi"&gt;10&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;custom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"fill"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"white"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Mogrify&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Draw&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="n"&gt;xx_position&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nv"&gt;@key_size&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;45&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;yy_position&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nv"&gt;@key_size&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;45&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Looking at the function &lt;code&gt;rounded_rectangle&lt;/code&gt; it's derived from the ones &lt;a href="https://github.com/zamith/mogrify_draw/blob/master/lib/mogrify/draw.ex" rel="noopener noreferrer"&gt;enabled by mogrify_draw&lt;/a&gt;, but using the &lt;code&gt;roundRectangle&lt;/code&gt; primitive from the &lt;code&gt;-draw&lt;/code&gt; given by the &lt;code&gt;mogrify&lt;/code&gt; command-line tools (&lt;a href="https://imagemagick.org/script/command-line-options.php#draw" rel="noopener noreferrer"&gt;check here&lt;/a&gt; all the primitives from &lt;code&gt;mogrify&lt;/code&gt; if you need something more custom). For this primitive, it's necessary to pass the base image, the upper left and bottom right point, together with the border-radius information.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;rounded_rectangle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
       &lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="n"&gt;upper_left_x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="n"&gt;upper_left_y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="n"&gt;lower_right_x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="n"&gt;lower_right_y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="n"&gt;border_w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="n"&gt;border_h&lt;/span&gt;
     &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;image&lt;/span&gt;
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;custom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s2"&gt;"draw"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"roundRectangle &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;
      &lt;span class="n"&gt;to_string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="ss"&gt;:io_lib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"~g,~g ~g,~g ~g,~g"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
          &lt;span class="n"&gt;upper_left_x&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="n"&gt;upper_left_y&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="n"&gt;lower_right_x&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="n"&gt;lower_right_y&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="n"&gt;border_w&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="n"&gt;border_h&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
        &lt;span class="p"&gt;])&lt;/span&gt;
      &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After recursively going through all the rows and keys, the image &lt;code&gt;heatmap.png&lt;/code&gt; is created. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Grey keys are keys that weren't used (or the keycode is not being detected by the keylogger.)&lt;/li&gt;
&lt;li&gt;Stronger blue keys are the ones used with less frequency.&lt;/li&gt;
&lt;li&gt;Mix of blue and red are the keys with mid-frequency.&lt;/li&gt;
&lt;li&gt;Red keys the most used ones.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.sanity.io%2Fimages%2F5aprln8a%2Fproduction%2F130f6dba27df6f6eb178e33d6c16e946315a460f-1520x570.png%3Fw%3D840" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.sanity.io%2Fimages%2F5aprln8a%2Fproduction%2F130f6dba27df6f6eb178e33d6c16e946315a460f-1520x570.png%3Fw%3D840" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can check the complete code and more detailed instructions on how to run it, in this &lt;a href="https://github.com/zediogoviana/keyboard_heatmap" rel="noopener noreferrer"&gt;Github repo&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Looking at the final result of a week of work we can identify some keys that are heavily used, such as the arrow keys, left command, left shift, left control, and even the backspace. It's somewhat a good representation of my usage as the referred keys take part in most of the keybindings that I use for work (except the backspace - not sure of what I delete so much 😅).&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating custom key modifications with &lt;strong&gt;Karabiner-Elements&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;As I mentioned earlier, initially I made some simple modifications with &lt;strong&gt;Karabiner&lt;/strong&gt;, but now we are in the condition of making some more complex ones, that are not provided by the community. &lt;/p&gt;

&lt;p&gt;To create custom modification rules, we need to create a file under &lt;code&gt;~/.config/karabiner/assets/complex_modifications/&lt;/code&gt; where you can have only one file with all the rules or group them in different files. After having valid rules they will appear as available to enable in the &lt;strong&gt;Complex modifications&lt;/strong&gt; tab.&lt;/p&gt;

&lt;p&gt;As an example, below, I'm creating a simple rule to change the &lt;code&gt;caps_lock&lt;/code&gt; key to be a &lt;code&gt;control&lt;/code&gt; key and just be a &lt;code&gt;caps_lock&lt;/code&gt; when pressed together with &lt;code&gt;shift&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;karabiner/assets/complex_modifications/capsToControl.json&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Change caps key"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"rules"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Change caps_lock key to control. (Use shift+caps_lock as caps_lock)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"manipulators"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"basic"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"from"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"key_code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"caps_lock"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"modifiers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="nl"&gt;"mandatory"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"shift"&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="nl"&gt;"optional"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"caps_lock"&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"to"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="nl"&gt;"key_code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"caps_lock"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"basic"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"from"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"key_code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"caps_lock"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"modifiers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="nl"&gt;"optional"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"any"&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"to"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="nl"&gt;"key_code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"right_control"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To see more on how to write these rules, you can the &lt;a href="https://karabiner-elements.pqrs.org/docs/json/" rel="noopener noreferrer"&gt;Karabiner Configuration Reference Manual&lt;/a&gt; or use this &lt;a href="https://genesy.github.io/karabiner-complex-rules-generator/" rel="noopener noreferrer"&gt;online editor&lt;/a&gt; to generate them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;There's still some stuff to do to make the heatmap more accurate and robust, such as making it work for more complex keyboard layouts, like split keyboards or with vertical gaps between keys. But I'll leave it for later when I have the time.&lt;/p&gt;

&lt;p&gt;This was a fun and simple project to try some ideas and make something generic that could be used by other people. The experiments with &lt;strong&gt;Karabiner-Elements&lt;/strong&gt; weren't all described here, but they were about trying more multiple key combinations, using only keys that I don't find necessary for my daily use, such as the &lt;code&gt;home&lt;/code&gt;, &lt;code&gt;end&lt;/code&gt;, &lt;code&gt;page down&lt;/code&gt; and &lt;code&gt;page up&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Hope you also liked reading it and that you give it a try.&lt;/p&gt;

&lt;p&gt;Have a nice one and see you in the next post 👋&lt;/p&gt;

</description>
      <category>heatmap</category>
      <category>keyboard</category>
      <category>karabiner</category>
      <category>elixir</category>
    </item>
    <item>
      <title>Quantum computing in the financial world</title>
      <dc:creator>José Diogo Viana</dc:creator>
      <pubDate>Wed, 24 Feb 2021 15:16:09 +0000</pubDate>
      <link>https://dev.to/finiam/quantum-computing-in-the-financial-world-36jh</link>
      <guid>https://dev.to/finiam/quantum-computing-in-the-financial-world-36jh</guid>
      <description>&lt;h2&gt;
  
  
  Introduction to Quantum computing
&lt;/h2&gt;

&lt;p&gt;When opening &lt;a href="https://www.ibm.com/quantum-computing/"&gt;IBM's Quantum Computing page&lt;/a&gt; we see &lt;strong&gt;"Tomorrow’s computing, today"&lt;/strong&gt;. For me, this is a great way to show newcomers what quantum computing really means today. I'm no expert in quantum mechanics, I don't even know enough to the extent of explaining how it works to someone. But one thing I know is that we are in a similar phase as Engineers and Computer Scientists were in the '40s or '50s, developing the first classical computers. I don't believe that quantum computers can fully replace our classical ones, but they surely will have a major role in our lives in the future, and we are just at the beginning.&lt;/p&gt;

&lt;p&gt;I won't explain how quantum computers work, but I recommend watching the video below, from &lt;strong&gt;Kurzgesagt – In a Nutshell&lt;/strong&gt;. It's a 7-minute video and does a great job comparing quantum computers with classical ones, so if you are completely new to this matter, you should take the time to watch it, also.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/JhHMJCUmq28"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;You might have heard about &lt;strong&gt;NPC (NP-Complete)&lt;/strong&gt; problems, if not, the &lt;a href="https://en.wikipedia.org/wiki/NP-completeness"&gt;Wikipedia page&lt;/a&gt; makes a good summary with some examples. Why am I talking about these problems? A &lt;strong&gt;NP&lt;/strong&gt; problem is very hard to answer with our current technology and could take years if not centuries to reach an answer.&lt;/p&gt;

&lt;p&gt;That's where the &lt;strong&gt;Monte Carlo algorithm&lt;/strong&gt; comes in! It is a computation process that uses random numbers to produce an outcome. So, if there is a procedure for verifying whether the answer given by a Monte Carlo algorithm is correct, and the probability of a correct answer is bounded above zero, then with probability one running the algorithm repeatedly while testing the answers will eventually give a correct answer.&lt;/p&gt;

&lt;p&gt;At the moment of writing this blog post, we only achieved quantum supremacy two times. Quantum supremacy is when a quantum computer outperforms a classical one. The goal of this blog post is not to enter into details, but you can read more &lt;a href="https://www.scientificamerican.com/article/light-based-quantum-computer-exceeds-fastest-classical-supercomputers/"&gt;here&lt;/a&gt; about the last time this has been achieved. And even more recently, Quantum Algorithms cracked nonlinear equations, by first "disguising" them as linear ones (more &lt;a href="https://www.quantamagazine.org/new-quantum-algorithms-finally-crack-nonlinear-equations-20210105/"&gt;here&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;In finance, problems like portfolio evaluation, personal finance planning, risk evaluation, and derivatives pricing are good examples of applications to Monte Carlo methods.&lt;/p&gt;

&lt;p&gt;Nevertheless, Monte Carlo methods have a problem. If we want to obtain the most probable outcome of a wide distribution or obtain a result with a very small associated error, the required number of simulations can be stratospheric.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Quantum Amplitude Estimation (QAE) algorithm&lt;/strong&gt; is a quantum-accelerated &lt;strong&gt;Monte Carlo&lt;/strong&gt; algorithm. &lt;strong&gt;QAE&lt;/strong&gt; can sample a probabilistic distribution quadratically faster than the next best classical method, allowing it to estimate expectation values extremely efficiently.&lt;/p&gt;

&lt;p&gt;To know more about these particular methods and how to use them in financial problems, check &lt;a href="https://medium.com/@quantum_wa/quantum-computing-and-finance-f7839c894979"&gt;this post&lt;/a&gt; from the &lt;strong&gt;Quantum World Association&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Financial Businesses and Quantum
&lt;/h2&gt;

&lt;p&gt;According to IBM, &lt;a href="https://www.ibm.com/quantum-computing/technology/quantum-in-finance/?cm_sp=ThinkDigitalResources-_-Infrastructure-_-Quantum%20finance"&gt;here&lt;/a&gt;, &lt;em&gt;"25% of small- and medium-sized financial institutions lose customers due to offerings that don’t prioritize the customer experience."&lt;/em&gt; and &lt;em&gt;"It is estimated that financial institutions are losing between USD 10 billion and 40 billion in revenue a year due to fraud and poor data management practices."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Quantum computers can run whole-market simulations better in finding patterns, performing classifications, and making predictions that are not possible today with classical computers.&lt;/p&gt;

&lt;p&gt;JPMorgan Chase wants to be ready for the quantum leap. The company has an unofficial leader, with the task to build a “quantum culture”, trying to discover how quantum computing can change the financial industry. &lt;/p&gt;

&lt;p&gt;Barclays first started to explore quantum computing in 2017 and concluded that quantum computing’s potential was so great that they should commit to an initial program of research and development.&lt;/p&gt;

&lt;p&gt;And we have many other cases to add to these ones.&lt;/p&gt;

&lt;h2&gt;
  
  
  Programming Quantum Computers
&lt;/h2&gt;

&lt;p&gt;There are various approaches at the moment, to program a quantum computer. Microsoft has developed &lt;a href="https://docs.microsoft.com/en-us/quantum/overview/what-is-qsharp-and-qdk"&gt;Q#&lt;/a&gt; programming language, IBM has &lt;a href="https://qiskit.org/documentation/"&gt;Qiskit&lt;/a&gt;, a Python package, etc.&lt;/p&gt;

&lt;p&gt;These are still in an early stage compared with what we can achieve with classical programming languages. Nevertheless, the road ahead seems promising.&lt;/p&gt;

&lt;h2&gt;
  
  
  Coding the first quantum circuit
&lt;/h2&gt;

&lt;p&gt;IBM offers a &lt;strong&gt;Circuit Composer&lt;/strong&gt;. It's a graphical quantum programming tool that lets you drag and drop operations to build quantum circuits and run them on real quantum hardware. You can check some instructions on how to use it &lt;a href="https://quantum-computing.ibm.com/docs/iqx/overview"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This &lt;strong&gt;Circuit Composer&lt;/strong&gt; should look like the following screenshot.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ew4ugHDz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zzb6zg0l2glzxpcxufb4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ew4ugHDz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zzb6zg0l2glzxpcxufb4.png" alt="quantum-circuit-1" width="800" height="451"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;In this blog post, we will follow the IBM tutorial and develop a &lt;strong&gt;Bell State&lt;/strong&gt; as a "Hello World" circuit.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;Bell State&lt;/strong&gt; is defined as a maximally entangled quantum state of two qubits. This means that if Alice and Bob held an entangled qubit, and Alice measured her qubit the outcome would be perfectly random, with either possibility having a probability of 1/2. But if Bob then measured his qubit, the outcome would be the same as the one Alice got. So, to Bob, at first sight, he would also get a random outcome, but if Alice and Bob communicated they would find out that, although the outcomes seemed random, they were correlated.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1 - Add an &lt;strong&gt;H&lt;/strong&gt; gate (Hadamard gate) to your circuit &lt;code&gt;q[0]&lt;/code&gt;.
&lt;/h3&gt;

&lt;p&gt;The Hadamard gate acts on a single qubit. It maps the basis state of the qubit to have equal probabilities to become 1 or 0 (i.e. creates a superposition).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bHdEfqfR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/20sgd9tjkurbhkicaoez.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bHdEfqfR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/20sgd9tjkurbhkicaoez.png" alt="quantum-circuit-2" width="800" height="452"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;To add a gate to your circuit, drag and drop the operation from the palette of quantum operations to the top qubit, q[0].&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2 - Add a &lt;strong&gt;controlled-NOT&lt;/strong&gt; gate to your circuit.
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RvtobVMG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cifimim30e157eds1hc8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RvtobVMG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cifimim30e157eds1hc8.png" alt="quantum-circuit-4" width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Controlled gates, such as &lt;strong&gt;controlled-NOT&lt;/strong&gt; gate (or &lt;strong&gt;CNOT&lt;/strong&gt; or &lt;strong&gt;CX&lt;/strong&gt;) act on 2 or more qubits, where one or more qubits act as a control for some operation. For example, the &lt;strong&gt;CX&lt;/strong&gt; acts on 2 qubits and performs the &lt;strong&gt;NOT&lt;/strong&gt; operation on the second qubit only when the first qubit is |1⟩, otherwise leaves it unchanged.&lt;/p&gt;

&lt;p&gt;To add a &lt;strong&gt;CX&lt;/strong&gt; gate to your circuit, drag and drop the operation from the palette of quantum operations to the right of the gate. This operation acts on two qubits.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3 - Add a measurement operation.
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ZfypYmjE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r7nuc3yfn8ditm7g0lcf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ZfypYmjE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r7nuc3yfn8ditm7g0lcf.png" alt="quantum-circuit-3" width="800" height="451"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;To add a measurement to your circuit, drag and drop the measurement operation from the palette of quantum operations to the right of the &lt;strong&gt;CX&lt;/strong&gt; operation.&lt;/p&gt;

&lt;p&gt;The measurement result is recorded as a classical bit on the classical register. The vertical wire connecting the measurement operation to the bottom wire depicts information flowing from the qubit down to the classical register.&lt;/p&gt;

&lt;h3&gt;
  
  
  Run the job and analyze results
&lt;/h3&gt;

&lt;p&gt;You have now built your first quantum circuit. The visualization panels below your circuit give a simulated result that updates automatically as you add and remove operations. But you can also run the job in one real quantum computer, by clicking the top right corner button. It is possible to configure some settings, like system, provider, or shots (the number of times to run the code). Running jobs can take some time, depending on the number of jobs in the queue, so be prepared for that.&lt;/p&gt;

&lt;p&gt;Therefore, most of the time is sufficient to just observe the simulation results. By looking at &lt;strong&gt;Measurement Probabilities&lt;/strong&gt;, we can conclude that the final state of our little circuit has a 50% chance to be &lt;strong&gt;|000&amp;gt;&lt;/strong&gt; or &lt;strong&gt;|001&amp;gt;&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;However, looking at the real result, the probabilities are not 50%. This is caused by noise and all sorts of technology limitations at the moment.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fDTzCsT6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6kzj7ey6vhhcvn2l10so.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fDTzCsT6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6kzj7ey6vhhcvn2l10so.png" alt="quantum-results-2" width="800" height="451"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;It is also possible to check the code version of the circuit we created.&lt;/p&gt;

&lt;h2&gt;
  
  
  More complex tutorials
&lt;/h2&gt;

&lt;p&gt;There are more complex circuits as tutorials, such as the &lt;a href="https://arxiv.org/abs/quant-ph/9605043"&gt;Grover's algorithm&lt;/a&gt;. It is a search algorithm, that can speed up an unstructured search problem quadratically. &lt;a href="https://quantum-computing.ibm.com/docs/iqx/guide/grovers-algorithm"&gt;Here&lt;/a&gt; you can find a brief explanation and the respective final circuit.&lt;/p&gt;

&lt;p&gt;In the same guide from IBM, there is also a link to some &lt;strong&gt;Jupyter Notebooks&lt;/strong&gt;, including Financial Tutorials. Continuing on the thread of increasing effort from classical Banks and Financial Institutions on the theme, you may want to experiment with the &lt;a href="https://qiskit.org/documentation/tutorials/finance/09_credit_risk_analysis.html"&gt;Credit Risk Analysis&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;Quantum computing is a very interesting and promising topic, and we at Finiam are going to be attentive to new signs of progress that can impact the world.&lt;/p&gt;

</description>
      <category>quantumcomputing</category>
      <category>financial</category>
      <category>montecarlo</category>
      <category>circuitcomposer</category>
    </item>
    <item>
      <title>Simulations with Elixir and the Actor Model</title>
      <dc:creator>José Diogo Viana</dc:creator>
      <pubDate>Thu, 21 Jan 2021 14:29:52 +0000</pubDate>
      <link>https://dev.to/finiam/simulations-with-elixir-and-the-actor-model-2lmf</link>
      <guid>https://dev.to/finiam/simulations-with-elixir-and-the-actor-model-2lmf</guid>
      <description>&lt;p&gt;Is there anyone else about to read this, as fascinated as I am by simulations? A simulation of a game, weather, aerodynamic behavior, or any other action, has intrinsically the same goal - take a peek into the future and see how things will perform in real life. &lt;/p&gt;

&lt;p&gt;These simulations all require an extent of calculations and variables to take into account, but also a model that will elegantly run through them.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"Aren't you describing Machine Learning? Isn't it also predicting the future with complicated maths and a model that no one really understands?&lt;/em&gt;", you ask. Yeah, I guess that ML fits into this description, but that's not the kind of predictions that I will be writing here.&lt;/p&gt;

&lt;p&gt;As an Engineer, I like to think that I build things. Some digital, some physical. Some work, some don't. So, for this problem, I'll use a carpentry workshop as my example (because, you know, carpenters build things that mostly work).&lt;/p&gt;

&lt;p&gt;Let's say that in our imaginary carpentry we have the following working stations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cut wood&lt;/li&gt;
&lt;li&gt;Polish wood&lt;/li&gt;
&lt;li&gt;Paint wood&lt;/li&gt;
&lt;li&gt;Varnish and protective coating&lt;/li&gt;
&lt;li&gt;Assembly&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this workshop, not all orders have the same processing. A chair may not need a painting or protective coating, but a kitchen table might. Or it can be a supplier for that Swedish company that doesn't assemble their products &lt;strong&gt;&lt;em&gt;cough cough&lt;/em&gt;&lt;/strong&gt;. Also, a given workstation can receive orders from various different stations. Imagine a directed graph like the one below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F2s05812yzrnau1i4iy3n.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F2s05812yzrnau1i4iy3n.jpg" alt="elixir-simulations-2"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;If we were about to score a big deal with a major client, but we don't know if we can handle the request in time, given that we have already so many orders in the shop, how can we decide on that? Simulation Time! &lt;/p&gt;

&lt;p&gt;Assuming that we know how much time each process takes, and the types of processing each order needs, we can verify when all of our registered orders, together with the new one, will be completed. I know these calculations could be done by hand, (yeah yeah) but bear with me on this one.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note that I'm not a Production Engineer, don't take my advice on production management. It's just for the sake of the blog post and the use for simulations in our lives.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Looking at workstations as if they were picking an order from the pile/queue, "doing their thing" and sending it to the next step, we can think of them as completely individual and independent actors from each other, inside the simulation engine. They simply pick an order from the queue and put it in the next one after the work is done. If nothing is waiting in line, the workstation stops until a new one appears. It can also be the starting or finishing point of an order.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fnlhpqfy3h1rt724nugpq.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fnlhpqfy3h1rt724nugpq.jpg" alt="elixir-simulations-1"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Quick intro to Elixir and Actors
&lt;/h2&gt;

&lt;p&gt;Continuing with the same thought, we identify some Actor Model programming characteristics. In response to a message it receives, an actor can: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;make local decisions;&lt;/li&gt;
&lt;li&gt;create more actors;&lt;/li&gt;
&lt;li&gt;send more messages;&lt;/li&gt;
&lt;li&gt;determine how to respond to the received message.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Actors may modify their private state, but can only affect each other indirectly through messaging. An actor is also a lightweight entity, unlike Operating System processes or threads.&lt;/p&gt;

&lt;p&gt;One of the selling points of &lt;em&gt;Elixir&lt;/em&gt; is its support for concurrency. The concurrency model relies on Actors. So, implementing the initial idea, where each workstation is an actor part of the simulation, should not be a problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  Different types of simulations
&lt;/h2&gt;

&lt;p&gt;There are two different types of simulation, Discrete Event Simulation (DES) and Continuous Simulation (CS).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;DES&lt;/strong&gt;: It models the operation of a system as a (discrete) sequence of events in time.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;CES&lt;/strong&gt;: the system state is changed continuously over time based on a set of differential equations defining the rates of change of state variables.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In our carpentry workshop, events can be treated as discrete. So in our simulation, time "hops" because events are instantaneous (jump straight to finish processing time) and do not occur in a continuous form. This way, the clock skips to the next event moment, each time an event is completed, as the simulation proceeds;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step by step
&lt;/h2&gt;

&lt;p&gt;Guess the boring talk is over and it's now time to put the ideas into work. &lt;/p&gt;

&lt;p&gt;Here, I'll use &lt;a href="https://hexdocs.pm/elixir/GenServer.html" rel="noopener noreferrer"&gt;GenServers&lt;/a&gt;, as workstations. With the &lt;em&gt;Erlang&lt;/em&gt; and &lt;em&gt;GenServer&lt;/em&gt; characteristics, a process has a FIFO "mailbox", ensuring the ordering of the messages received by each workstation. If &lt;strong&gt;process A&lt;/strong&gt; sends messages &lt;strong&gt;&lt;em&gt;x&lt;/em&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;em&gt;y&lt;/em&gt;&lt;/strong&gt;, by this order, to &lt;strong&gt;process B&lt;/strong&gt;, we know that it'll receive them by the same order.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Process A&lt;/span&gt;
&lt;span class="n"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;B&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;B&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Process B &lt;/span&gt;
&lt;span class="k"&gt;receive&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; x&lt;/span&gt;
&lt;span class="k"&gt;receive&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Though, if we have a &lt;strong&gt;process C&lt;/strong&gt; that also sends a message &lt;strong&gt;&lt;em&gt;w&lt;/em&gt;&lt;/strong&gt; to &lt;strong&gt;B&lt;/strong&gt; in the meantime, we don't have guarantees in what order it'll be received. Only that &lt;strong&gt;&lt;em&gt;x&lt;/em&gt;&lt;/strong&gt; will be first then &lt;strong&gt;&lt;em&gt;y&lt;/em&gt;&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Process A&lt;/span&gt;
&lt;span class="n"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;B&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;B&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Process C&lt;/span&gt;
&lt;span class="n"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;B&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Process B &lt;/span&gt;
&lt;span class="k"&gt;receive&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; w || x&lt;/span&gt;
&lt;span class="k"&gt;receive&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; w || x || y&lt;/span&gt;
&lt;span class="k"&gt;receive&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; w || y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Everyone that has already dealt with concurrency problems like this one, with several actors swapping messages, can smell a problem here... &lt;strong&gt;We need to have some kind of synchronization between processes&lt;/strong&gt;. Order of messages from different actors/workstations matters in our simulation. That's why I'm introducing the &lt;strong&gt;Simulation Manager&lt;/strong&gt;. We must ensure that the Manager only fast forwards the clock when it has all the updated values from the actors affected by some event in the past, keeping "timed events" from overlapping.&lt;/p&gt;

&lt;p&gt;This process will ensure synchronization and message order. The existence of a centralized actor simplifies this problem and potentially increases efficiency due to less metadata and extra messages in a peer-to-peer case.&lt;/p&gt;

&lt;h3&gt;
  
  
  A bit of code
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;1.&lt;/strong&gt; To start our simulation, we start a new process (actor). This will be the &lt;strong&gt;Simulation Manager&lt;/strong&gt; and is responsible for spawning an actor for each workstation that composes our workshop's pipeline;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Simulation Manager code&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;start_link&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;actors_pids&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="no"&gt;CarpentryWorkshop&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Workstations&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_all&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;place&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;start_place_actor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;place&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="no"&gt;GenServer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start_link&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="bp"&gt;__MODULE__&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;%{&lt;/span&gt;
      &lt;span class="ss"&gt;pids:&lt;/span&gt; &lt;span class="n"&gt;actors_pids&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="ss"&gt;clock:&lt;/span&gt; &lt;span class="no"&gt;Timex&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
      &lt;span class="ss"&gt;events:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
      &lt;span class="ss"&gt;awaiting:&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="ss"&gt;name:&lt;/span&gt; &lt;span class="no"&gt;SimManager&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;start_place_actor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;place&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pid&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Pipe&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;SimPlace&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start_link&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;place&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;place&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pid&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the code above, we have the Simulation Manager starting all the other actors and storing their &lt;em&gt;pids&lt;/em&gt; to identify each one in the rest of the distributed algorithm. Note that there were other alternatives to this in &lt;em&gt;Elixir&lt;/em&gt;, but this one is probably the easiest.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Events&lt;/em&gt; represent messages received from each place and &lt;em&gt;awaiting&lt;/em&gt; are actors that the &lt;strong&gt;Manager&lt;/strong&gt; should wait for before advancing the simulation time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2.&lt;/strong&gt; Each of these actors will collect the list of orders in their queue, and sort them by the delivery date. Announcing to the manager when the next event will occur. The next event is calculated by the processing time of the first package in the queue;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Simulation Place code&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;start_link&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;place_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;events&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;get_events_list&lt;/span&gt;
  &lt;span class="no"&gt;GenServer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start_link&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="bp"&gt;__MODULE__&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;%{&lt;/span&gt;
      &lt;span class="ss"&gt;self_info:&lt;/span&gt; &lt;span class="n"&gt;place_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="ss"&gt;pids:&lt;/span&gt; &lt;span class="p"&gt;%{},&lt;/span&gt;
      &lt;span class="ss"&gt;events:&lt;/span&gt; &lt;span class="n"&gt;events&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;span class="n"&gt;next&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;hd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;events&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;events&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;hd&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;finish_processing_timestamp&lt;/span&gt;
  &lt;span class="n"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;SimManager&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:next_event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;place_id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; 
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;get_events_list&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;place_id&lt;/span&gt;
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;CarpentryWorkshop&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
      &lt;span class="no"&gt;Orders&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;list_for_place&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;place_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;CarpentryWorkhop&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
       &lt;span class="no"&gt;Orders&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sort_by_delivery_time&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;events&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;finish_processing_timestamp&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="c1"&gt;# Based on the type of order&lt;/span&gt;
    &lt;span class="c1"&gt;# Calculate end processing time&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3.&lt;/strong&gt; When the manager gets all announcements, orders them, and advances clock time to the next event, warning the actor where the event will occur;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;handle_info&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="ss"&gt;:next_event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;ordered&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;insert_ordered&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;events&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;awaiting&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;awaiting&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;rest_events&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;next_step&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 
    &lt;span class="n"&gt;send_next_event&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ordered&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;awaiting&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# we have all answers&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;send_next_event&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;events&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[])&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;next_event&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;get_first_from_queue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;events&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;next_event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;place_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:advance&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# missing answers from actors&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;send_next_event&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;events&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;awaiting&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;events&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;4.&lt;/strong&gt; Then, the respective workstation Actor receives a message from the manager and completes the "event" (package processed). If the package is concluded, it will update the database value for the expected delivery time. Else, it will send a message with the package to the next workstation (actor). It also warns the manager, that it needs to wait for the next event update from itself and the next workstation;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;handle_info&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="ss"&gt;:advance&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="c1"&gt;# check if this is the last place for this order&lt;/span&gt;
  &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;tl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rest_path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
      &lt;span class="c1"&gt;# Update DB Value&lt;/span&gt;
      &lt;span class="n"&gt;update_prediction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
      &lt;span class="n"&gt;warn_next_workstation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="n"&gt;warn_manager&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;5.&lt;/strong&gt; The intervening workstation actor will recalculate the next event time and announce it to the simulation manager (&lt;code&gt;nil&lt;/code&gt; in case that there is no package in the queue), to continue the simulation; This part is analogous to &lt;strong&gt;Step 2&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6.&lt;/strong&gt; The simulation stops when the manager doesn’t have more "next events" in the queue.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;rest_events&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;next_step&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="c1"&gt;# Finished Simulation&lt;/span&gt;
  &lt;span class="n"&gt;stop_workstation_actors&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pids&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:stop&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:normal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[]}&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the code snippets above, the parts for calculating timestamps and the next events are omitted, but they account for a major part of this simulation and synchronization between actors.&lt;/p&gt;

&lt;p&gt;After glueing every missing part of this simulation, our workshop is now ready to answer when an order (newly placed or not) will be ready.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;We demonstrated some of the advantages of using &lt;em&gt;Elixir&lt;/em&gt; for distributed algorithms/problems. However, use this kind of distributed approach with caution, as it can introduce all sorts of bugs. And believe me, you won't like debugging distributed stuff...  &lt;/p&gt;

&lt;p&gt;Hope I got you a little bit more interested in simulations in general and taking advantage of the actor model to solve exquisite problems.&lt;/p&gt;

</description>
      <category>elixir</category>
      <category>simulations</category>
      <category>actors</category>
    </item>
  </channel>
</rss>
