<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>D3Portillo</title>
        <link>https://paragraph.com/@d3portillo</link>
        <description>Frontend Developer / 42 Madrid Student / Taquitos 🌮</description>
        <lastBuildDate>Wed, 22 Apr 2026 00:01:53 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>en</language>
        <image>
            <title>D3Portillo</title>
            <url>https://storage.googleapis.com/papyrus_images/2f1c5e1b55c88e5fb9352bbb10a15a04d6b490a795eb6140f085ad5f8ef04e2a.png</url>
            <link>https://paragraph.com/@d3portillo</link>
        </image>
        <copyright>All rights reserved</copyright>
        <item>
            <title><![CDATA[Web3: Creando tu primer App Descentralizada]]></title>
            <link>https://paragraph.com/@d3portillo/web3-creando-tu-primer-app-descentralizada</link>
            <guid>n88kSpmrgO62PJ0yhGii</guid>
            <pubDate>Thu, 15 Sep 2022 12:19:02 GMT</pubDate>
            <description><![CDATA[El hype por las Aplicaciones Descentralizadas(DApps) no para. Esto genera que muchos desarrolladores tengan la necesidad de experimentar este maravilloso mundo llamado Web3. Todo sobre la Web3 suena maravilloso hasta que, buscas un tutorial, y el resultado es completa desesperación, una alarma a 30 minutos de sonar y mucho café con Korn a todo volumen. Puedes tomar el texto anterior como un relato personal. El ecosistema Web3 es muy cambiante e involucra mucha adaptación. Despiertas un lunes ...]]></description>
            <content:encoded><![CDATA[<p>El hype por las Aplicaciones Descentralizadas(DApps) no para. Esto genera que muchos desarrolladores tengan la necesidad de experimentar este maravilloso mundo llamado <em>Web3</em>.</p><p>Todo sobre la Web3 suena maravilloso hasta que, buscas un tutorial, y el resultado es completa desesperación, una alarma a 30 minutos de sonar y mucho café con <em><s>Korn</s></em> a todo volumen.</p><p>Puedes tomar el texto anterior como un relato personal. El ecosistema Web3 es muy cambiante e involucra mucha adaptación. Despiertas un lunes por la mañana y descubres que se han lanzado docenas librerías, conceptos nuevos que estudiar, Tokens, The Merge<code>(1)</code>, y personas tirando hate en Twitter porque <strong>Solana</strong> no sube a $40 USD.</p><p>En resumen, Web3 puede generar muchísimo FOMO<code>(2)</code> sin importar la experiencia que tengas como desarrollador, tu background profesional, y mucho menos seniority.</p><p>Dando finiquito a la introducción anterior. A continuación podrás leer una guía detallada y elaborada con cariño para todos los interesados en adentrarse a este mundo. Tú puedes, no estás sólo en esto 🤗.</p><h2 id="h-que-demonios-es-web3" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">¿Qué demonios es Web3?</h2><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/9b8699b3a05477703de0af070b8250d13a5e8d2d1813c4d6bf704e8464b4bbe1.png" alt="Lain del Anime &quot;Serial Experiments Lain&quot; intentando conectarse a “The Wired&quot;. Imágen de https://sabukaru.online/articles/serial-experiments-lain-coding-for-divinity" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">Lain del Anime &quot;Serial Experiments Lain&quot; intentando conectarse a “The Wired&quot;. Imágen de https://sabukaru.online/articles/serial-experiments-lain-coding-for-divinity</figcaption></figure><p>Al inicio de los tiempos <em>dios</em> creó la Web 1.0, sitios estáticos, contenido estático, y mucho texto con hipervínculos a más contenido estático.</p><p>La Web 2.0 es la Web que todos conocemos y consumimos. Esa popular y llena de memes “Internet”. Contenido dinámico y aplicaciones para consumir servicios, productos o interactuar con tus amigos de Facebook y Discord.</p><p><strong>Web 3.0</strong> es un concepto de descentralización de estos servicios, productos y aplicaciones. Un lugar dónde no existen intermediarios, y mucho menos empresas que se alimenten de tu información.</p><h2 id="h-ethereum-network" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Ethereum Network</h2><p>Ethereum<code>(3)</code> es una red de computadores o <em>“nodos”</em> distribuidos globalmente*.*</p><p>Cada nodo en esta red comparte una réplica o “estado” de la información disponible en la red. Este <em>“estado”</em> es definido por un cómputo único llamado <strong><em>“Ethereum Virtual Machine”</em></strong> <code>(4)</code><strong><em>.</em></strong></p><p>En Ethereum, cada nodo es partícipe en un consenso para cada evento que intente <em>modificar</em> el “estado” de la EVM. Ya que esto requiere poder de cómputo, a los nodos participantes se les aporta ETH(Ether) como incentivo.</p><blockquote><p>Podemos imaginar “Ethereum” como una gigantesca “Máquina de estados finitos” (Finite State Machine ó FSM) <code>(5)</code>.</p></blockquote><p>Con la EVM podemos manipular/condicionar el estado de la red usando <em>“Contratos Inteligentes” (Smart Contracts)</em>.</p><blockquote><p><strong>IMPORTANTE</strong>: Para la fecha de lanzamiento de esta guía, Ethereum migró de <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://ethereum.org/en/developers/docs/consensus-mechanisms/pow/">Proof of Work</a> a <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://ethereum.org/en/developers/docs/consensus-mechanisms/pos/">Proof of Stake</a>, <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://vitalik.ca/general/2017/12/31/pos_faq.html">https://vitalik.ca/general/2017/12/31/pos_faq.html</a></p></blockquote><h2 id="h-smart-contracts-y-sistemas-distribuidos" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Smart Contracts y Sistemas Distribuidos</h2><p>Los <em>“Smart Contracts”</em> son programas/herramientas para acceder a la EVM, con ellos podemos leer, actualizar y escribir información a la red Ethereum.</p><p>En pocas palabras los desarrolladores tienen la posibilidad de crear aplicaciones <em>“Semi-Turing Complete”</em> usando lenguajes como Vyper y Solidity.</p><p>Solidity y Vyper son lenguajes de alto nivel para desarrollar Smart Contracts en la EVM. Usamos estos lenguajes porque la EVM sólo comprende <em>“EVM Bytecode”</em> <code>(6)</code><em>.</em></p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/6e0aa813e6fe02ff02384d783fe228f53b8798afe0a944bac7cf3e1e06e5fbb8.png" alt="Ejemplo de cómputo distribuido en una red global, en esta red, cada nodo comparte información entre sí y en tiempo real. Los sistemas distribuidos se caracterizan por la alta disponibilidad de información, ya que la malfunción de uno de estos nodos no afectará en la distribución de información de dicha red. Si quieres saber más del tema, recomiendo leer &quot;Falacias de los Sistemas Distribuidos&quot;, https://architecturenotes.co/fallacies-of-distributed-systems " blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">Ejemplo de cómputo distribuido en una red global, en esta red, cada nodo comparte información entre sí y en tiempo real. Los sistemas distribuidos se caracterizan por la alta disponibilidad de información, ya que la malfunción de uno de estos nodos no afectará en la distribución de información de dicha red. Si quieres saber más del tema, recomiendo leer &quot;Falacias de los Sistemas Distribuidos&quot;, https://architecturenotes.co/fallacies-of-distributed-systems</figcaption></figure><h2 id="h-talk-is-cheap-show-me-the-code" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Talk is cheap. Show me the code</h2><p>Antes de iniciar a tirar código debes considerar la siguiente lista de elementos necesarios para esta guía:</p><ol><li><p>Firefox o Chrome e instalar la extensión de <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://metamask.io/download/">Metamask</a></p></li><li><p>Se recomienda crear una cuenta en Metamask sólamente para pruebas</p></li><li><p>Visual Studio Code o un Editor de texto</p></li><li><p>Si usas Windows tener WSL (<em>Windows Subsystem for Linux</em>) configurado</p></li><li><p>NodeJS (Versión &gt;= 16. Puedes usar <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/nvm-sh/nvm"><em>nvm</em></a> para una instalación sencilla)</p></li><li><p>Crear una cuenta en <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://auth.alchemyapi.io">Alchemy</a>. Lo usaremos para lanzar nuestro Smart Contract en Goerli Testnet.</p></li></ol><p>Si usas Visual Studio Code puedes instalar estos plugins:</p><ul><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://marketplace.visualstudio.com/items?itemName=tintinweb.solidity-visual-auditor">Solidity Visual Developer</a></p></li><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://marketplace.visualstudio.com/items?itemName=NomicFoundation.hardhat-solidity">Solidity + Hardhat</a></p></li></ul><h2 id="h-stack-de-desarrollo" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Stack de Desarrollo</h2><ul><li><p><strong>NextJs:</strong> Un framework de React muy popular que se vende como <em>“El Framework de React para producción”</em>. Personalmente es mi favorito del Ecosistema React y me agrada que sea de los más usados en Web3.</p></li><li><p><strong>Wagmi:</strong> Colección de <em>React hooks</em> con lo requerido para trabajar con Ethereum. Peticiones, conectividad, interacción con Smart Contracts, firmas — TODO <code>(7)</code>.</p></li><li><p><strong>RainbowKit:</strong> Conectividad sencilla para React Devs. Un proyecto de los creadores de Rainbow Wallet.</p></li><li><p><strong>TailwindCSS:</strong> Un framework de utilidad que expone una set de configuración consistente la cúal agiliza el desarrollo de componentes personalizados.</p></li><li><p><strong>Alchemy:</strong> RPC Provider<code>(8)</code>. Plataforma que nos hace la vida sencilla para la arquitectura de DApps. Sus clientes incluyen, OpenSea, Chainlink y Meta. <strong>NOTA:</strong> Existen 2 plataformas similares e igual de populares que Alchemy, hablamos de <em>Moralis</em> e <em>Infura</em> <code>(9)</code>.</p></li><li><p><strong>Hardhat:</strong> Entorno de desarrollo para Ethereum. Smart Contracts, Testing, Depuración y Tooling para Solidity.</p></li><li><p>Por último, pero no menos importante, <strong>Typescript</strong>.</p></li></ul><h2 id="h-cuentame-que-vamos-a-crear" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Cuéntame, ¿ Qué vamos a crear ?</h2><p>Sí, ya sé que tu café se está enfriando, rellenalo que ahora entramos al objetivo de este documento; crear un pequeño proyecto, que lo extiendas y juegues con él mientras nos movemos en el Stack más popular para crear DApps. Y que por cierto, luego puedes incluir en tu portafolio ☺️.</p><p>La idea final es desarrollar un <strong>“Libro de Notas”</strong>.</p><p>Proyecto <em>“sencillo”</em> de codear para la Web2, pero que aportará mucho jugar con él en un enfoque Web3. <em>¿ Por qué ?</em> , tanto desarrollar la  interfaz, creación e integración del Smart Contract con Solidity requieren una atención/investigación muy similar, y así cualquier desarrollador puede aprovechar este documento 💛.</p><p>Al terminar aprenderemos cómo consumir información de Goerli, pintar esta información en un frontend y crear un Smart Contract que gestione este contenido :)</p><p>Crear este <em>“GuestBook en Ethereum”</em> estará dividido en 5 etapas, y una etapa completamente opcional. Estas son:</p><ol><li><p><strong>Genesis:</strong> RainbowKit y NextJS</p></li><li><p><strong>Hardhat:</strong> Solidity Hello World</p></li><li><p><strong>Goerli Testnet:</strong> Distribuyendo nuestro Smart Contract</p></li><li><p><strong>Solidity Cardio:</strong> Eventos, Funciones y Variables de estado</p></li><li><p><strong>Wagmi React:</strong> Interacción con el Frontend y finalización</p></li><li><p>Opcional, <strong>Plus Ultra:</strong> Lanzando nuestra DApp en Vercel</p></li></ol><p>Iniciamos,</p><h2 id="h-genesis-rainbowkit-y-nextjs" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Genesis: RainbowKit y NextJS</h2><p>Primero necesitamos un proyecto <strong><em>NextJs</em></strong>, agregar <strong><em>RainbowKit</em></strong> y <strong><em>Wagmi</em></strong> como dependencias a este proyecto. El equipo de RainbowKit ya nos expone un comando para crear el boilerplate e incluir estas dependencias. Ejecutamos:</p><pre data-type="codeBlock" text="npm init @rainbow-me/rainbowkit@latest -y kort
"><code>npm <span class="hljs-keyword">init</span> <span class="hljs-meta">@rainbow</span>-me/<span class="hljs-symbol">rainbowkit@</span>latest -y kort
</code></pre><p>Puedes cambiar el argumento <code>”kort”</code> con el texto que gustes, este será el nombre de nuestro proyecto.</p><p>Ya creado nuestro proyecto, nos ubicamos en el directorio creado. Si dejaste como nombre de proyecto <code>“kort”</code>, haz <code>cd kort</code> y ejecutas <code>npm run dev</code>.</p><p>Hacer <code>npm run dev</code> lanza un servidor de desarrollo en NextJs, este refrescará el contenido servido cada vez que hagamos cambios en el árbol de archivos de nuestro espacio de trabajo.</p><p>Si visitamos nuestro local en <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="http://localhost:3000">http://localhost:3000</a> veremos este Frontend:</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/74067761524fbba1ef4f810e0ac172d862af99a537dee1d2e1dad54d4827d6f2.png" alt="La imágen muestra la página inicial de NextJS y RainbowKit en modo desarrollo. Se visualiza un widget de conexión a distintas redes  enlaces a documentación de RainbowKit, Wagmi y NextJs." blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">La imágen muestra la página inicial de NextJS y RainbowKit en modo desarrollo. Se visualiza un widget de conexión a distintas redes enlaces a documentación de RainbowKit, Wagmi y NextJs.</figcaption></figure><p>Podemos conectarnos con una Wallet en este frontend…, pero sólamente a redes Mainnet<code>(10)</code>, nosotros queremos, por pruebas, conectarnos a una Testnet, <strong><em>Goerli</em></strong>.</p><p>Si visualizas el contenido en <code>pages/_app.tsx</code> y te ubicas en la línea #15 verás esto:</p><pre data-type="codeBlock" text="15  ...(process.env.NEXT_PUBLIC_ENABLE_TESTNETS === &apos;true&apos;
"><code><span class="hljs-number">15</span>  ...(process.env.NEXT_PUBLIC_ENABLE_TESTNETS <span class="hljs-operator">=</span><span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-string">'true'</span>
</code></pre><p>La línea #15 evalúa que el valor de la “Variable de Entorno <code>(11)</code>” <code>NEXT_PUBLIC_ENABLE_TESTNETS</code> tiene como contenido <code>“true”</code>, esta bandera define si permitimos <em>Testnets</em> en nuestro proyecto.</p><p>Para habilitarlas vamos a crear un archivo que tenga las variables de entorno para usar en nuestro proyecto. Ejecutamos:</p><pre data-type="codeBlock" text="echo &quot;NEXT_PUBLIC_ENABLE_TESTNETS=true&quot; &gt; .env
"><code>echo <span class="hljs-string">"NEXT_PUBLIC_ENABLE_TESTNETS=true"</span> <span class="hljs-operator">></span> .env
</code></pre><p>Se creará un archivo <code>.env</code> con el contenido <code>NEXT_PUBLIC_ENABLE_TESTNETS=true</code></p><p>Para cargar las definiciones del archivo <code>.env</code> a nuestro proyecto, cerramos el proceso dónde hicimos <code>npm run dev</code> al comienzo de la guía, <em><s>matando</s> el proceso</em> con <code>CTRL + C</code>, luego ejecutamos <code>npm run dev</code> por una vez más. Hacemos esto porque las definiciones en el archivo <code>.env</code> se cargan en el arranque del servidor de desarrollo.</p><p>Y listo, ahora podemos conectarnos a Goerli Testnet con RainbowKit.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/2793dbf6c99200ce6488d3433d32d38e56d3b4119d67f7b12680c31ed78b1f97.png" alt="La imágen muestra un ejemplo de cuenta enlazada con RainbowKit en Goerli Testnet. Además se visualiza un widget de información de la cuenta con acciones para COPIAR y DESCONECTAR dicha cuenta enlazada." blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">La imágen muestra un ejemplo de cuenta enlazada con RainbowKit en Goerli Testnet. Además se visualiza un widget de información de la cuenta con acciones para COPIAR y DESCONECTAR dicha cuenta enlazada.</figcaption></figure><p>¡Felicidades!, acabamos de enlazar Metamask con el Frontend de <code>“kort”</code>.</p><hr><p>Continuemos,</p><pre data-type="codeBlock" text="pages/
|-- _app.tsx
|-- index.tsx
.env
package.json
"><code>pages<span class="hljs-operator">/</span>
<span class="hljs-operator">|</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span> _app.tsx
<span class="hljs-operator">|</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span> index.tsx
.env
package.json
</code></pre><p>Del árbol de archivos en nuestro proyecto nos enfocamos en cuatro elementos.</p><ol><li><p><code>page/index.tsx</code> define la ruta inicial de nuestra DApp, el <code>index.html</code>.</p></li><li><p><code>_app.tsx</code> es un archivo reservado de NextJs para personalizar las páginas dentro de <code>/pages</code>.</p></li><li><p><code>.env</code> archivo para configurar Variables de entorno y configuración definida por el desarrollador. <strong>NOTA:</strong> No agregues este archivo en tu repositorio, los <em>.env files</em> guardan información privada de nuestros proyectos.</p></li><li><p><code>package.json</code> contiene metadatos y configuración para NodeJs. Acá se definen las <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://docs.npmjs.com/cli/v8/configuring-npm/package-json">dependencias, scripts y mucho más</a>.</p></li></ol><p>NextJs tiene el concepto de <code>“fichero dentro de /pages”</code> = <code>“una página”</code>. Estas <em>“páginas”</em> son por defecto un componente React.</p><blockquote><p>A este concepto de enrutamiento <code>“directorio”</code> → <code>“fichero template”</code>, se le conoce como <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://nextjs.org/docs/routing/introduction">File based routing system</a>.</p></blockquote><h3 id="h-la-configuracion-de-rainbowkit" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">La configuración de RainbowKit</h3><p>Con <code>_app.tsx</code> podemos modificar cada página del proyecto, agregar estado persistente, layouts compartidas, y más. Es acá dónde inicializamos RainbowKit.</p><pre data-type="codeBlock" text="07  // _app.tsx
08
09  const { chains, provider, webSocketProvider } = configureChains(
10    [chain.mainnet, chain.polygon, chain.optimism],
11    [
12      alchemyProvider({
13        // Obten tu APIKey en https://dashboard.alchemyapi.io
14      }),
15      publicProvider(),
16    ]
17  )
18
"><code>07  <span class="hljs-comment">// _app.tsx</span>
08
09  const { chains, provider, webSocketProvider } <span class="hljs-operator">=</span> configureChains(
<span class="hljs-number">10</span>    [chain.mainnet, chain.polygon, chain.optimism],
<span class="hljs-number">11</span>    [
<span class="hljs-number">12</span>      alchemyProvider({
<span class="hljs-number">13</span>        <span class="hljs-comment">// Obten tu APIKey en https://dashboard.alchemyapi.io</span>
<span class="hljs-number">14</span>      }),
<span class="hljs-number">15</span>      publicProvider(),
<span class="hljs-number">16</span>    ]
<span class="hljs-number">17</span>  )
<span class="hljs-number">18</span>
</code></pre><p>La línea #10 define las redes en las que funcionará nuestra DApp. Cada elemento en este arreglo contiene el <code>id</code> de la red, nombre, URLs de conexión RPC y URLs para los <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.criptonoticias.com/criptopedia/anatomia-exploradores-blockchain-cadena-bloques/">Exploradores de bloques</a> de la red.</p><p>Líneas #11 y #15 definen los proveedores(<code>providers</code>) de la red Ethereum. En el fragmento se usa Alchemy como proveedor RPC inicial para las redes configuradas la línea #10.</p><p><code>publicProvider</code> será un Fallback si en una red específica(Ejemplo si el usuario cambia <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://chainlist.org/chain/100">Gnosis</a>) dicho <code>provider</code> no está disponible. Tener en cuenta que <code>publicProvider</code> intentará interactuar con Ethereum Mainnet.</p><blockquote><p>Llamamos <code>provider</code> a una abstracción consistente para una red. Básicamente es un cliente con una API estándar para interactuar con la chain.</p></blockquote><pre data-type="codeBlock" text="24  const wagmiClient = createClient({
25    autoConnect: true,
26    connectors,
27    provider,
28    webSocketProvider,
29  })
"><code><span class="hljs-number">24</span>  <span class="hljs-keyword">const</span> <span class="hljs-variable constant_">wagmiClient</span> = <span class="hljs-title function_ invoke__">createClient</span>({
<span class="hljs-number">25</span>    <span class="hljs-attr">autoConnect</span>: <span class="hljs-literal">true</span>,
<span class="hljs-number">26</span>    connectors,
<span class="hljs-number">27</span>    provider,
<span class="hljs-number">28</span>    webSocketProvider,
<span class="hljs-number">29</span>  })
</code></pre><h3 id="h-configurando-wagmi" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Configurando Wagmi</h3><p>RainbowKit es una herramienta para conexión, su funcionalidad vive gracias a Wagmi y sus <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://reactjs.org/docs/hooks-intro.html">React Hooks</a>. Ver más información para configurar Wagmi acá: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://wagmi.sh/docs/client#configuration">https://wagmi.sh/docs/client</a></p><p><strong>Configurando #createClient</strong></p><ul><li><p><code>autoConnect: true</code> indica que Wagmi puede(por defecto) tomar la última Wallet enlazada a nuestro Frontend.</p></li><li><p><code>connectors</code> configuración de proveedores de Wallets de nuestra DApp. Por defecto son Metamask, Coinbase, Rainbow Wallet y WalletConnect.</p></li><li><p><code>provider</code> es el cliente obtenido de ejecutar <code>configureChains</code> en el fragmento de la Línea #9.</p></li><li><p><code>webSocketProvider</code> si la ejecución de <code>configureChains</code> resuelve con un cliente WebSockets, Wagmi realizará la conexión por WebSockets en vez de HTTP.</p></li></ul><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/136f5036359e0aecfbf4e5cb65d3de330dd559b8dc6bddf8c2d871e90c70809d.gif" alt="Yaaay, Felicidades. Estamos listos para la siguiente etapa." blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">Yaaay, Felicidades. Estamos listos para la siguiente etapa.</figcaption></figure><h2 id="h-hardhat-solidity-hello-world" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Hardhat: Solidity Hello World</h2><p>Ahora, vamos a crear nuestro primer <strong>Smart Contract</strong> 😍.</p><blockquote><p><strong>NOTA:</strong> Esta guía es para desarrollar Smart Contracts con Solidity y Hardhat como entorno de desarrollo. Existe un editor llamado <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://remix.ethereum.org/">Remix</a>, dónde puedes probar cositas en la EVM antes de moverlas a tu codebase.</p></blockquote><p>Primero, dependencias. Hardhat y <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://hardhat.org/hardhat-runner/plugins/nomicfoundation-hardhat-toolbox">hardhat-toolbox</a>,</p><pre data-type="codeBlock" text="npm i -D hardhat @nomicfoundation/hardhat-toolbox
"><code>npm i <span class="hljs-operator">-</span>D hardhat @nomicfoundation<span class="hljs-operator">/</span>hardhat<span class="hljs-operator">-</span>toolbox
</code></pre><p>Ahora necesitamos un <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://hardhat.org/hardhat-runner/docs/config#available-config-options">archivo de configuración para Hardhat</a>. En la raíz de nuestro proyecto creamos el archivo <code>hardhat.config.ts</code> y pegamos esto:</p><pre data-type="codeBlock" text="// hardhat.config.ts
import { HardhatUserConfig } from &quot;hardhat/config&quot;
import &quot;@nomicfoundation/hardhat-toolbox&quot;

const config: HardhatUserConfig = {
  solidity: &quot;0.8.9&quot;,
}

export default config
"><code><span class="hljs-comment">// hardhat.config.ts</span>
<span class="hljs-keyword">import</span> { HardhatUserConfig } from <span class="hljs-string">"hardhat/config"</span>
<span class="hljs-keyword">import</span> <span class="hljs-string">"@nomicfoundation/hardhat-toolbox"</span>

<span class="hljs-type">const</span> config: HardhatUserConfig = {
  solidity: <span class="hljs-string">"0.8.9"</span>,
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> config
</code></pre><h3 id="h-tu-primer-smart-contract" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Tu primer Smart Contract</h3><p>Para tener más ordenado nuestro código y seguir la convención de archivos en hardhat, vamos a crear una carpeta dónde vivirán nuestros Smart Contracts y otra para definir scripts/tareas que consumen estos Smart Contracts.</p><p>En consola, <code>mkdir contracts scripts</code>.</p><p>Creadas las carpetas, dentro de <code>contracts/</code> creamos un archivo llamado <code>HolaMundo.sol</code> y pegamos el siguiente contenido:</p><pre data-type="codeBlock" text="// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;

contract HolaMundo {
    string hola = &quot;Hola&quot;;
    string mundo = &quot;Mundo!!&quot;;

    function saludar() external view returns (string memory) {
        return string(abi.encodePacked(hola, &quot; &quot;, mundo));
    }
}
"><code><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.8.9;</span>

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">HolaMundo</span> </span>{
    <span class="hljs-keyword">string</span> hola <span class="hljs-operator">=</span> <span class="hljs-string">"Hola"</span>;
    <span class="hljs-keyword">string</span> mundo <span class="hljs-operator">=</span> <span class="hljs-string">"Mundo!!"</span>;

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">saludar</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">view</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">string</span> <span class="hljs-keyword">memory</span></span>) </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">string</span>(<span class="hljs-built_in">abi</span>.<span class="hljs-built_in">encodePacked</span>(hola, <span class="hljs-string">" "</span>, mundo));
    }
}
</code></pre><h3 id="h-ejecutando-holamundosol" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Ejecutando HolaMundo.sol</h3><p>Dentro de <code>scripts/</code> creamos un archivo <code>deploy.ts</code> y pegaremos el siguiente contenido:</p><pre data-type="codeBlock" text="import { ethers } from &quot;hardhat&quot;

async function main() {
  const factory = await ethers.getContractFactory(&quot;HolaMundo&quot;)
  const contract = await factory.deploy()
  await contract.deployed()
  console.log(await contract.saludar())
}

main().catch((error) =&gt; {
  console.error(error)
  process.exitCode = 1
})
"><code><span class="hljs-keyword">import</span> { ethers } <span class="hljs-keyword">from</span> <span class="hljs-string">"hardhat"</span>

<span class="hljs-keyword">async</span> <span class="hljs-keyword">function</span> <span class="hljs-title function_">main</span>(<span class="hljs-params"></span>) {
  <span class="hljs-keyword">const</span> factory = <span class="hljs-keyword">await</span> ethers.<span class="hljs-title function_">getContractFactory</span>(<span class="hljs-string">"HolaMundo"</span>)
  <span class="hljs-keyword">const</span> contract = <span class="hljs-keyword">await</span> factory.<span class="hljs-title function_">deploy</span>()
  <span class="hljs-keyword">await</span> contract.<span class="hljs-title function_">deployed</span>()
  <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-keyword">await</span> contract.<span class="hljs-title function_">saludar</span>())
}

<span class="hljs-title function_">main</span>().<span class="hljs-title function_">catch</span>(<span class="hljs-function">(<span class="hljs-params">error</span>) =></span> {
  <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">error</span>(error)
  process.<span class="hljs-property">exitCode</span> = <span class="hljs-number">1</span>
})
</code></pre><p>Para ejecutar este script, hacemos:</p><pre data-type="codeBlock" text="npx hardhat run scripts/deploy.ts
"><code>npx hardhat run scripts<span class="hljs-operator">/</span>deploy.ts
</code></pre><p>Esto distribuye en local el Smart Contract <code>“HolaMundo.sol”</code> usando la <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://hardhat.org/hardhat-network/docs/overview#hardhat-network">Hardhat Network</a>.</p><hr><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/b9e1092b3818f753fbbaffc17dd5217a24b2d4ec1bd7cb48fe1f1c197e478b58.png" alt="En la imágen podemos observar un error por una mala configuración en tsconfig.json. Para solventarlo se modifica la configuración de &quot;module&quot; en tsconfig.json a &quot;commonjs&quot;." blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">En la imágen podemos observar un error por una mala configuración en tsconfig.json. Para solventarlo se modifica la configuración de &quot;module&quot; en tsconfig.json a &quot;commonjs&quot;.</figcaption></figure><p>Si visualizas este error, tranquilidad. NextJs ha definido que nuestro proyecto será un módulo <code>“esnext”</code> para poder hacer <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://nextjs.org/docs/advanced-features/dynamic-import">imports dinámicos</a>, causando este error. Para solventarlo cambiamos la propiedad <code>“module”</code> en <code>tsconfig.json</code> a <code>“commonjs”</code>.</p><pre data-type="codeBlock" text="{
  &quot;compilerOptions&quot;: {
    ...tu configuración acá,
    &quot;module&quot;: &quot;commonjs&quot;
  },
}
"><code>{
  <span class="hljs-string">"compilerOptions"</span>: {
    ...tu configuración acá,
    <span class="hljs-string">"module"</span>: <span class="hljs-string">"commonjs"</span>
  },
}
</code></pre><p>Ejecutamos de nuevo <code>npx hardhat run scripts/deploy.ts</code> y Voilà.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/d5542b2438a20312ce35605022e23be0f810d81aac63a43207a7e633188eeee9.png" alt="Yaaay. Hola Mundo 👋 " blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">Yaaay. Hola Mundo 👋</figcaption></figure><p><strong>¿Y si intentamos crear una función que espere un parámetro?</strong></p><p>Hagámoslo…, y por cierto, a este punto ya tienes una base para jugar con lo que se te ocurra con Solidity, mira <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/Uniswap/v2-core/tree/master/contracts">ejemplos de Uniswap</a> y tomalos de guía.</p><h3 id="h-saludarconnombre" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">SaludarConNombre()</h3><pre data-type="codeBlock" text="function saludarConNombre(string calldata nombre)
    external
    pure
    returns (string memory)
{
    return string(abi.encodePacked(&quot;Hola &quot;, nombre));
}
"><code><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">saludarConNombre</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> <span class="hljs-keyword">calldata</span> nombre</span>)
    <span class="hljs-title"><span class="hljs-keyword">external</span></span>
    <span class="hljs-title"><span class="hljs-keyword">pure</span></span>
    <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">string</span> <span class="hljs-keyword">memory</span></span>)
</span>{
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">string</span>(<span class="hljs-built_in">abi</span>.<span class="hljs-built_in">encodePacked</span>(<span class="hljs-string">"Hola "</span>, nombre));
}
</code></pre><p>Antes de invocar nuestra función en el script <code>deploy.ts</code>, una pequeña explicación de las palabras <em>“pure”</em>, <em>“external”</em> y <em>“calldata”</em> en este contexto.</p><ul><li><p><code>pure</code>, una <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://en.wikipedia.org/wiki/Pure_function">función <em>“pura”</em></a> es aquella que no modifica propiedades que están fuera de su scope. En pocas palabras, <code>saludarConNombre()</code> es una función que sólo manipula la data con la que se invocó dicha función, más nunca escribirá ni leerá fuera de su contexto.</p></li><li><p><code>external</code> describe la <em>“visibilidad”</em> que la función <code>saludarConNombre()</code> tendrá cuando se distribuya en la red. Existen <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://docs.soliditylang.org/en/v0.8.16/cheatsheet.html?highlight=visibility#function-visibility-specifiers">4 tipos de visibilidad</a>, public, private, internal y external.</p></li><li><p><code>calldata</code> representa el alojamiento de memoria de la función.</p></li></ul><p>Modificamos la función <code>main()</code> para agregar saludos a “Seth” y “Atzil”,</p><pre data-type="codeBlock" text="async function main() {
  const factory = await ethers.getContractFactory(&quot;HolaMundo&quot;)
  const contract = await factory.deploy()
  await contract.deployed()
  console.log(await contract.saludar())
  console.log(await contract.saludarConNombre(&quot;Seth&quot;))
  console.log(await contract.saludarConNombre(&quot;Atzil&quot;))
}
"><code>async <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">main</span>(<span class="hljs-params"></span>) </span>{
  const factory <span class="hljs-operator">=</span> await ethers.getContractFactory(<span class="hljs-string">"HolaMundo"</span>)
  const <span class="hljs-class"><span class="hljs-keyword">contract</span> = <span class="hljs-title">await</span> <span class="hljs-title">factory</span>.<span class="hljs-title">deploy</span>(<span class="hljs-params"></span>)
  <span class="hljs-title">await</span> <span class="hljs-title"><span class="hljs-keyword">contract</span></span>.<span class="hljs-title">deployed</span>(<span class="hljs-params"></span>)
  <span class="hljs-title">console</span>.<span class="hljs-title">log</span>(<span class="hljs-params">await <span class="hljs-keyword">contract</span>.saludar(<span class="hljs-params"></span>)</span>)
  <span class="hljs-title">console</span>.<span class="hljs-title">log</span>(<span class="hljs-params">await <span class="hljs-keyword">contract</span>.saludarConNombre(<span class="hljs-params"><span class="hljs-string">"Seth"</span></span>)</span>)
  <span class="hljs-title">console</span>.<span class="hljs-title">log</span>(<span class="hljs-params">await <span class="hljs-keyword">contract</span>.saludarConNombre(<span class="hljs-params"><span class="hljs-string">"Atzil"</span></span>)</span>)
}
</span></code></pre><p><code>npx hardhat run scripts/deploy.ts</code> una vez más,</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/e5e5b457a91ae9896069faabf50b4ca5b9c10b8505258396e47cf429b8a8e8d2.png" alt="El resultado de ejecutar el comando &quot;npx hardhat run scripts/deploy.ts&quot;" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">El resultado de ejecutar el comando &quot;npx hardhat run scripts/deploy.ts&quot;</figcaption></figure><blockquote><p><code>abi.encodePacked</code> es usado(en este caso) para concatenar strings. La función <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://docs.soliditylang.org/en/v0.8.13/abi-spec.html#non-standard-packed-mode">encodePacked</a> agrupa los bytes de una variable y retorna los bytes de toda esa agrupación, al final convertimos esos bytes a un string.</p></blockquote><h2 id="h-goerli-testnet-distribuyendo-nuestro-smart-contract" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Goerli Testnet: Distribuyendo nuestro Smart Contract</h2><p>Para esta sección necesitas tener creada una cuenta en <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.alchemy.com/">Alchemy</a>, esto para distribuir nuestro contrato en <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://goerli.net/">Goerli Testnet</a> : )</p><p>Como ya has notado, ejecutar los Smart Contracts requiere trabajo repetitivo, a medida que nuestro proyecto crece esto puede generar mucha distorsión.</p><p>La comunidad ha adoptado un plugin para agilizar este proceso — <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/wighawag/hardhat-deploy#hardhat-deploy-in-a-nutshell">hardhat-deploy</a>, el plugin de hardhat que permite definir scripts secuenciales e interactuar con el <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://hardhat.org/hardhat-runner/docs/advanced/hardhat-runtime-environment">Hardhat runtime environment</a>. Ya que esta guía intenta mostrarte lo más usado y adoptado por el ecosistema, vamos a instalarlo.</p><pre data-type="codeBlock" text="npm i -D hardhat-deploy dotenv
"><code>npm i <span class="hljs-operator">-</span>D hardhat<span class="hljs-operator">-</span>deploy dotenv
</code></pre><p>Ahora agregamos el plugin en <code>hardhat.config.ts</code>,</p><pre data-type="codeBlock" text="// hardhat.config.ts
import { HardhatUserConfig } from &quot;hardhat/config&quot;
import &quot;@nomicfoundation/hardhat-toolbox&quot;
import &quot;hardhat-deploy&quot; // Importamos el plugin
import &quot;dotenv/config&quot; // Paquete para cargar variables de entorno
"><code><span class="hljs-comment">// hardhat.config.ts</span>
<span class="hljs-keyword">import</span> { <span class="hljs-title class_">HardhatUserConfig</span> } <span class="hljs-keyword">from</span> <span class="hljs-string">"hardhat/config"</span>
<span class="hljs-keyword">import</span> <span class="hljs-string">"@nomicfoundation/hardhat-toolbox"</span>
<span class="hljs-keyword">import</span> <span class="hljs-string">"hardhat-deploy"</span> <span class="hljs-comment">// Importamos el plugin</span>
<span class="hljs-keyword">import</span> <span class="hljs-string">"dotenv/config"</span> <span class="hljs-comment">// Paquete para cargar variables de entorno</span>
</code></pre><h3 id="h-configurando-alchemy" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Configurando Alchemy</h3><p>Luego de registrarte en Alchemy, crea una nueva App con el nombre que quieras, la descripción que quieras, pero eso sí, la chain será <code>Ethereum</code> y en Network marcamos <code>Goerli</code>.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/a58dc48290bfa0018161eb13fcd9dfc4743c565c0457dfa3bc6362bbc57f63f6.png" alt="Configuración de una DApp en Alchemy." blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">Configuración de una DApp en Alchemy.</figcaption></figure><p>Luego de creado el proyecto, vamos al Dashboard y copiamos el valor de <code>“API KEY”</code></p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/b35de470806882f16fd4e7939a6227e7c07099d1ba37740a4c26117a1f26e781.png" alt="Dashboard del proyecto Kort. Se visualizan widgets para copiar los valores de la API KEY para conectarnos con Alchemy RPC." blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">Dashboard del proyecto Kort. Se visualizan widgets para copiar los valores de la API KEY para conectarnos con Alchemy RPC.</figcaption></figure><p>Agregamos el valor de <code>API KEY</code> en nuestro archivo <code>.env</code>,</p><pre data-type="codeBlock" text="NEXT_PUBLIC_ENABLE_TESTNETS=true
ALCHEMY_API_KEY=PEGA TU API KEY ACÁ
"><code><span class="hljs-attr">NEXT_PUBLIC_ENABLE_TESTNETS</span>=<span class="hljs-literal">true</span>
<span class="hljs-attr">ALCHEMY_API_KEY</span>=PEGA TU API KEY ACÁ
</code></pre><h3 id="h-distribuyendo-holamundosol" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Distribuyendo HolaMundo.sol</h3><p>Creamos un archivo en <code>deploy/00_HolaMundo.ts</code> y agregamos lo siguiente:</p><pre data-type="codeBlock" text="// deploy/00_HolaMundo.ts
import { HardhatRuntimeEnvironment } from &quot;hardhat/types&quot;
import { DeployFunction } from &quot;hardhat-deploy/types&quot;

const fn: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
  const { getNamedAccounts, deployments } = hre
  const { deployer } = await getNamedAccounts()
  // &quot;deployer&quot; es tomado de hardhat.config.ts#namedAccounts
  await deployments.deploy(&quot;HolaMundo&quot;, {
    from: deployer,
  })
}

export default fn
"><code><span class="hljs-comment">// deploy/00_HolaMundo.ts</span>
<span class="hljs-keyword">import</span> { <span class="hljs-title class_">HardhatRuntimeEnvironment</span> } <span class="hljs-keyword">from</span> <span class="hljs-string">"hardhat/types"</span>
<span class="hljs-keyword">import</span> { <span class="hljs-title class_">DeployFunction</span> } <span class="hljs-keyword">from</span> <span class="hljs-string">"hardhat-deploy/types"</span>

<span class="hljs-keyword">const</span> <span class="hljs-attr">fn</span>: <span class="hljs-title class_">DeployFunction</span> = <span class="hljs-keyword">async</span> <span class="hljs-keyword">function</span> (<span class="hljs-params">hre: HardhatRuntimeEnvironment</span>) {
  <span class="hljs-keyword">const</span> { getNamedAccounts, deployments } = hre
  <span class="hljs-keyword">const</span> { deployer } = <span class="hljs-keyword">await</span> <span class="hljs-title function_">getNamedAccounts</span>()
  <span class="hljs-comment">// "deployer" es tomado de hardhat.config.ts#namedAccounts</span>
  <span class="hljs-keyword">await</span> deployments.<span class="hljs-title function_">deploy</span>(<span class="hljs-string">"HolaMundo"</span>, {
    <span class="hljs-attr">from</span>: deployer,
  })
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> fn
</code></pre><blockquote><p>El plugin <em>hardhay-deploy</em> ejecutará los archivos dentro de /deploy en orden, podemos agregar tantos scripts queramos</p></blockquote><p><em>¿Deploy?</em>. Aún no, <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://youtu.be/djVWzPEm7Pg?t=51">espera un poco, un poquito más</a>. Tenemos que definir en hardhat quién será el “<em>deployer”</em> de nuestro Smart Contract.</p><p>Para ello necesitamos la “Llave privada” de una Wallet. Para Metamask puedes seguír este post: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="http://metamask.zendesk.com/hc/en-us/articles/360015289632">https://metamask.zendesk.com/hc/en-us/articles/360015289632</a></p><p>Ahora que tenemos nuestra “Llave privada” la agregamos a nuestro <code>.env</code></p><pre data-type="codeBlock" text="NEXT_PUBLIC_ENABLE_TESTNETS=true
ALCHEMY_API_KEY=PEGA TU API KEY ACÁ
PRIVATE_KEY=Y ACÁ TU LLAVE PRIVADA
"><code><span class="hljs-attr">NEXT_PUBLIC_ENABLE_TESTNETS</span>=<span class="hljs-literal">true</span>
<span class="hljs-attr">ALCHEMY_API_KEY</span>=PEGA TU API KEY ACÁ
<span class="hljs-attr">PRIVATE_KEY</span>=Y ACÁ TU LLAVE PRIVADA
</code></pre><p>Necesitamos agregar <code>PRIVATE_KEY</code> a la configuración de Hardhat para Goerli. <code>hardhat.config.ts</code> deberá quedar así:</p><pre data-type="codeBlock" text="// hardhat.config.ts
import { HardhatUserConfig } from &quot;hardhat/config&quot;
import &quot;@nomicfoundation/hardhat-toolbox&quot;
import &quot;hardhat-deploy&quot;
import &quot;dotenv/config&quot;

const ALCHEMY_API_KEY = process.env.ALCHEMY_API_KEY
const PRIVATE_KEY = process.env.PRIVATE_KEY!

const config: HardhatUserConfig = {
  solidity: &quot;0.8.9&quot;,
  networks: {
    goerli: {
      url: `https://eth-goerli.g.alchemy.com/v2/${ALCHEMY_API_KEY}`,
      accounts: [PRIVATE_KEY],
    },
  },
  namedAccounts: {
    deployer: 0, // Posición 0 en `networks.&lt;goerli&gt;.accounts[]`
  },
}

export default config
"><code><span class="hljs-comment">// hardhat.config.ts</span>
<span class="hljs-keyword">import</span> { HardhatUserConfig } from <span class="hljs-string">"hardhat/config"</span>
<span class="hljs-keyword">import</span> <span class="hljs-string">"@nomicfoundation/hardhat-toolbox"</span>
<span class="hljs-keyword">import</span> <span class="hljs-string">"hardhat-deploy"</span>
<span class="hljs-keyword">import</span> <span class="hljs-string">"dotenv/config"</span>

<span class="hljs-type">const</span> ALCHEMY_API_KEY = process.env.ALCHEMY_API_KEY
<span class="hljs-type">const</span> PRIVATE_KEY = process.env.PRIVATE_KEY!

<span class="hljs-type">const</span> config: HardhatUserConfig = {
  solidity: <span class="hljs-string">"0.8.9"</span>,
  networks: {
    goerli: {
      url: `https:<span class="hljs-comment">//eth-goerli.g.alchemy.com/v2/${ALCHEMY_API_KEY}`,</span>
      accounts: [PRIVATE_KEY],
    },
  },
  namedAccounts: {
    deployer: <span class="hljs-number">0</span>, <span class="hljs-comment">// Posición 0 en `networks.&#x3C;goerli>.accounts[]`</span>
  },
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> config
</code></pre><p>Un último comando,</p><pre data-type="codeBlock" text="npx hardhat deploy --network goerli
"><code>npx hardhat deploy <span class="hljs-operator">-</span><span class="hljs-operator">-</span>network goerli
</code></pre><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/a44cf9b0db3ef7f737f42018dd57dfd24f58fafcd5dfa6475c5c16f3768c6d95.png" alt="Resultado de ejecutar el lanzamiento de HolaMundo.sol" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">Resultado de ejecutar el lanzamiento de HolaMundo.sol</figcaption></figure><hr><p>Oye, espera un momento .</p><p><strong>¿ Sabes que acabas de crear y distribuir un Smart Contract en Goerli ?</strong> , te mereces una donita más para el café 💛.</p><p>Compartelo con tus amigos, publicalo en tus redes sociales :3</p><div data-type="youtube" videoId="gAjR4_CbPpQ">
      <div class="youtube-player" data-id="gAjR4_CbPpQ" style="background-image: url('https://i.ytimg.com/vi/gAjR4_CbPpQ/hqdefault.jpg'); background-size: cover; background-position: center">
        <a href="https://www.youtube.com/watch?v=gAjR4_CbPpQ">
          <img src="{{DOMAIN}}/editor/youtube/play.png" class="play"/>
        </a>
      </div></div><p>Hay algo más que podemos hacer para mejorar el deployment, si verificas tu <em>Smart Contract</em> aportas muchos beneficios.</p><p>Ejemplo, si visualizas este <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://goerli.etherscan.io/address/0xA1012F4B18badFd4fA9122fEc7e4de160aD0ffBB#readContract">Smart Contract</a> podrás ver su código fuente, ejecutar sus métodos de escritura/lectura, y obtener información sobre bugs. Todo esto gracias a que dicho contrato está verificado en Etherscan.</p><hr><h3 id="h-full-extras-verificando-nuestro-smart-contract-en-etherscan" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Full Extras: Verificando nuestro Smart Contract en Etherscan</h3><p>Al verificar nuestro Smart Contract el código fuente de este será visible, lo cúal genera transparencia a cualquier interesado en la lógica detrás de una DApp. Y además cualquier persona puede interactuar con el contrato desde el Explorador.</p><p>Para verificar, primero creamos una cuenta en <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="http://etherscan.io/apis">https://etherscan.io/apis</a>, copiamos la <code>API KEY</code> y agregamos la definición <code>ETHERSCAN_API_KEY=”TU API KEY”</code> en <code>.env</code></p><p>Configuramos el plugin <em>hardhat-etherscan</em> en <code>hardhat.config.ts</code></p><pre data-type="codeBlock" text="// hardhat.config.ts

// Sacamos la definición ETHERSCAN_API_KEY de .env
const ETHERSCAN_API_KEY = process.env.ETHERSCAN_API_KEY!
const config: HardhatUserConfig = {
  ...,
  etherscan: {
    apiKey: {
      goerli: ETHERSCAN_API_KEY, // https://goerli.etherscan.io
    },
  },
}

export default config
"><code><span class="hljs-comment">// hardhat.config.ts</span>

<span class="hljs-comment">// Sacamos la definición ETHERSCAN_API_KEY de .env</span>
<span class="hljs-type">const</span> ETHERSCAN_API_KEY = process.env.ETHERSCAN_API_KEY!
<span class="hljs-type">const</span> config: HardhatUserConfig = {
  ...,
  etherscan: {
    apiKey: {
      goerli: ETHERSCAN_API_KEY, <span class="hljs-comment">// https://goerli.etherscan.io</span>
    },
  },
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> config
</code></pre><blockquote><p>El plugin usado es <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.npmjs.com/package/@nomiclabs/hardhat-etherscan">@nomiclabs/hardhat-etherscan</a> y viene instalado junto a <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://hardhat.org/hardhat-runner/plugins/nomicfoundation-hardhat-toolbox">hardhat-toolbox</a></p></blockquote><p>Del paso anterior(<code>Distribuyendo HolaMundo.sol</code>) debió crearse una carpeta( <code>deployments/</code>) con la información del lanzamiento.</p><p>En la ruta <code>deployments/goerli/HolaMundo.json</code> observaras algo parecido a esto:</p><pre data-type="codeBlock" text="{
  &quot;address&quot;: &quot;0xA1012F4B18badFd4fA9122fEc7e4de160aD0ffBB&quot;,
  &quot;abi&quot;: [
    {
      &quot;inputs&quot;: [],
      &quot;name&quot;: &quot;saludar&quot;,
      &quot;stateMutability&quot;: &quot;view&quot;,
      &quot;type&quot;: &quot;function&quot;
    },
    {
      &quot;name&quot;: &quot;saludarConNombre&quot;,
      &quot;stateMutability&quot;: &quot;pure&quot;,
      &quot;type&quot;: &quot;function&quot;
    }
  ]
}
"><code>{
  "<span class="hljs-selector-tag">address</span>": <span class="hljs-string">"0xA1012F4B18badFd4fA9122fEc7e4de160aD0ffBB"</span>,
  <span class="hljs-string">"abi"</span>: [
    {
      "inputs": [],
      <span class="hljs-string">"name"</span>: <span class="hljs-string">"saludar"</span>,
      <span class="hljs-string">"stateMutability"</span>: <span class="hljs-string">"view"</span>,
      <span class="hljs-string">"type"</span>: <span class="hljs-string">"function"</span>
    },
    {
      "name": <span class="hljs-string">"saludarConNombre"</span>,
      <span class="hljs-string">"stateMutability"</span>: <span class="hljs-string">"pure"</span>,
      <span class="hljs-string">"type"</span>: <span class="hljs-string">"function"</span>
    }
  ]
}
</code></pre><p>Para verificar <code>HolaMundo.sol</code> en etherscan necesitamos la propiedad <code>address</code>, esta es la dirección dónde se alojó el contrato en la red.</p><p><strong>ABI</strong>(Application Binary Interface) define los métodos y propiedades para interactuar con <code>HolaMundo.sol</code>.</p><h3 id="h-quiero-verificar-holamundosol-ya" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">😋 Quiero verificar HolaMundo.sol ya</h3><p>Anda, para verificar <code>HolaMundo.sol</code> en Goerli ejecutamos:</p><pre data-type="codeBlock" text="npx hardhat verify --network goerli &lt;address&gt;
"><code>npx hardhat verify <span class="hljs-operator">-</span><span class="hljs-operator">-</span>network goerli <span class="hljs-operator">&#x3C;</span><span class="hljs-keyword">address</span><span class="hljs-operator">></span>
</code></pre><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/086f395da245f61d9bc07b7cdc9808a24e4c9d3eb953bf72e15047b47a703285.png" alt="Ahora si vamos a la ruta de nuestro contrato(address). Veremos una interfaz dónde puedes interactuar : )" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">Ahora si vamos a la ruta de nuestro contrato(address). Veremos una interfaz dónde puedes interactuar : )</figcaption></figure><h3 id="h-usando-hardhat-deploy" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">💎 Usando hardhat-deploy</h3><p>Para automatizar este proceso podemos crear un deploy script en <code>/deploy</code></p><pre data-type="codeBlock" text="// deploy/99_VerifyABIs.ts

import { HardhatRuntimeEnvironment } from &quot;hardhat/types&quot;
import { DeployFunction } from &quot;hardhat-deploy/types&quot;

// Agrega las chains que ejecutarán `verify`
const TO_VERIFY_NETWORKS = [&quot;goerli&quot;]
// Lista el nombre de los Smart Contracts a verificar en EtherScan
const VERIFY_CONTRACTS = [&quot;HolaMundo&quot;]

const fn: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
  const { name } = hre.network
  // Tomar todos los deployments hasta este momento
  const deployed = await hre.deployments.all()
  // Validar que estoy en una chain que puede ejecutar verify.
  // No vamos a verificar nuestro contrato en Hardhat localhost
  if (TO_VERIFY_NETWORKS.includes(name)) {
    for (let name of VERIFY_CONTRACTS) {
      const contract = deployed[name]
      if (contract) {
        await hre.run(&quot;verify:verify&quot;, {
          address: contract.address,
        })
      } else throw `Could&apos;t find deployment for ${name}`
    }
  }
}

// Forzar ejecutar esta función al final
fn.runAtTheEnd = true

export default fn
"><code><span class="hljs-comment">// deploy/99_VerifyABIs.ts</span>

<span class="hljs-keyword">import</span> { <span class="hljs-title class_">HardhatRuntimeEnvironment</span> } <span class="hljs-keyword">from</span> <span class="hljs-string">"hardhat/types"</span>
<span class="hljs-keyword">import</span> { <span class="hljs-title class_">DeployFunction</span> } <span class="hljs-keyword">from</span> <span class="hljs-string">"hardhat-deploy/types"</span>

<span class="hljs-comment">// Agrega las chains que ejecutarán `verify`</span>
<span class="hljs-keyword">const</span> <span class="hljs-variable constant_">TO_VERIFY_NETWORKS</span> = [<span class="hljs-string">"goerli"</span>]
<span class="hljs-comment">// Lista el nombre de los Smart Contracts a verificar en EtherScan</span>
<span class="hljs-keyword">const</span> <span class="hljs-variable constant_">VERIFY_CONTRACTS</span> = [<span class="hljs-string">"HolaMundo"</span>]

<span class="hljs-keyword">const</span> <span class="hljs-attr">fn</span>: <span class="hljs-title class_">DeployFunction</span> = <span class="hljs-keyword">async</span> <span class="hljs-keyword">function</span> (<span class="hljs-params">hre: HardhatRuntimeEnvironment</span>) {
  <span class="hljs-keyword">const</span> { name } = hre.<span class="hljs-property">network</span>
  <span class="hljs-comment">// Tomar todos los deployments hasta este momento</span>
  <span class="hljs-keyword">const</span> deployed = <span class="hljs-keyword">await</span> hre.<span class="hljs-property">deployments</span>.<span class="hljs-title function_">all</span>()
  <span class="hljs-comment">// Validar que estoy en una chain que puede ejecutar verify.</span>
  <span class="hljs-comment">// No vamos a verificar nuestro contrato en Hardhat localhost</span>
  <span class="hljs-keyword">if</span> (<span class="hljs-variable constant_">TO_VERIFY_NETWORKS</span>.<span class="hljs-title function_">includes</span>(name)) {
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> name <span class="hljs-keyword">of</span> <span class="hljs-variable constant_">VERIFY_CONTRACTS</span>) {
      <span class="hljs-keyword">const</span> contract = deployed[name]
      <span class="hljs-keyword">if</span> (contract) {
        <span class="hljs-keyword">await</span> hre.<span class="hljs-title function_">run</span>(<span class="hljs-string">"verify:verify"</span>, {
          <span class="hljs-attr">address</span>: contract.<span class="hljs-property">address</span>,
        })
      } <span class="hljs-keyword">else</span> <span class="hljs-keyword">throw</span> <span class="hljs-string">`Could't find deployment for <span class="hljs-subst">${name}</span>`</span>
    }
  }
}

<span class="hljs-comment">// Forzar ejecutar esta función al final</span>
fn.<span class="hljs-property">runAtTheEnd</span> = <span class="hljs-literal">true</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> fn
</code></pre><p>Este script se ejecutará cada cuando hagamos <code>npx hardhat deploy</code> : )</p><h2 id="h-solidity-cardio-eventos-y-variables-de-estado" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Solidity Cardio: Eventos y Variables de estado</h2><p>En esta sección aprenderemos un poco de los primitivos en Solidity. De antemano comento que no será un tutorial de condicionales, bucles y basis de otros lenguajes de programación.</p><p>Tu mayor fuente de información es la <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://docs.soliditylang.org/en/v0.8.16/structure-of-a-contract.html">documentación oficial de Solidity</a>, Google y amigos en comunidades Web3 : )</p><h3 id="h-eventos" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Eventos</h3><p>Los eventos en Solidity tienen muchos usos, exponer información, para por ejemplo comunicarnos con servicios externos de la red y además guardar data.</p><pre data-type="codeBlock" text="// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;

contract NFTLogger {
    // Declaramos un evento con el nombre `NuevaCompra`.
    // En los eventos podemos &quot;emitir&quot; información.
    // Esta puede ser filtrada al marcarse como `indexed`.
    // * NOTA: A estas propiedades indexadas se les llama topics
    event NuevaCompra(address indexed owner, string nft_id);

    function comprarNFT() public {
        // Emitimos el evento NuevaCompra
        emit NuevaCompra(msg.sender, &quot;NFT-004&quot;);
    }
}
"><code><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.8.9;</span>

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">NFTLogger</span> </span>{
    <span class="hljs-comment">// Declaramos un evento con el nombre `NuevaCompra`.</span>
    <span class="hljs-comment">// En los eventos podemos "emitir" información.</span>
    <span class="hljs-comment">// Esta puede ser filtrada al marcarse como `indexed`.</span>
    <span class="hljs-comment">// * NOTA: A estas propiedades indexadas se les llama topics</span>
    <span class="hljs-function"><span class="hljs-keyword">event</span> <span class="hljs-title">NuevaCompra</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> <span class="hljs-keyword">indexed</span> owner, <span class="hljs-keyword">string</span> nft_id</span>)</span>;

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">comprarNFT</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> </span>{
        <span class="hljs-comment">// Emitimos el evento NuevaCompra</span>
        <span class="hljs-keyword">emit</span> NuevaCompra(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>, <span class="hljs-string">"NFT-004"</span>);
    }
}
</code></pre><p>Ver <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://etherscan.io/tx/0x70aef10945b623c025118aae09ff5ac767c12c2db9f484ec3f166d36cdba596b#eventlog">ejemplo en Etherscan</a>.</p><h3 id="h-estructuras" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Estructuras</h3><p>Las estructuras(<code>structs</code>) en Solidity son un <code>tipo de dato</code> que aloja propiedades primitivas, dónde estas propiedades se agrupan como una tupla. <em>“Objetos”</em></p><pre data-type="codeBlock" text="struct UnaLLama {
    bool guapa;
    string nombre;
    uint edad;
}
"><code><span class="hljs-keyword">struct</span> UnaLLama {
    <span class="hljs-built_in">bool</span> guapa;
    <span class="hljs-built_in">string</span> nombre;
    <span class="hljs-built_in">uint</span> edad;
}
</code></pre><p>Para crear una “Llama”, hacemos:</p><pre data-type="codeBlock" text="LLama llama = LLama(true, &quot;Juanita&quot;, 33);
// Creación por posición, LLama(guapa, nombre, edad)
"><code>LLama <span class="hljs-attr">llama</span> = LLama(<span class="hljs-literal">true</span>, <span class="hljs-string">"Juanita"</span>, <span class="hljs-number">33</span>)<span class="hljs-comment">;</span>
// Creación por posición, LLama(guapa, nombre, edad)
</code></pre><p><strong>Un pequeño ejemplo con Deploy scripts:</strong></p><pre data-type="codeBlock" text="// contracts/Llama.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;

contract Llama {
    struct UnaLLama {
        bool guapa;
        string nombre;
        uint edad;
    }

    function crearLLama(
        bool _guapa,
        string calldata _nombre,
        uint _edad
    ) public pure returns (UnaLLama memory) {
        return UnaLLama(_guapa, _nombre, _edad);
    }
}
"><code><span class="hljs-comment">// contracts/Llama.sol</span>
<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.8.9;</span>

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">Llama</span> </span>{
    <span class="hljs-keyword">struct</span> <span class="hljs-title">UnaLLama</span> {
        <span class="hljs-keyword">bool</span> guapa;
        <span class="hljs-keyword">string</span> nombre;
        <span class="hljs-keyword">uint</span> edad;
    }

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">crearLLama</span>(<span class="hljs-params">
        <span class="hljs-keyword">bool</span> _guapa,
        <span class="hljs-keyword">string</span> <span class="hljs-keyword">calldata</span> _nombre,
        <span class="hljs-keyword">uint</span> _edad
    </span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title"><span class="hljs-keyword">pure</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params">UnaLLama <span class="hljs-keyword">memory</span></span>) </span>{
        <span class="hljs-keyword">return</span> UnaLLama(_guapa, _nombre, _edad);
    }
}
</code></pre><pre data-type="codeBlock" text="// scripts/deploy.ts
import { ethers } from &quot;hardhat&quot;

async function main() {
  const factory = await ethers.getContractFactory(&quot;Llama&quot;)
  const contract = await factory.deploy()
  await contract.deployed()
  console.log(await contract.crearLLama(true, &quot;Juanita 2&quot;, 42))
}

main()
"><code><span class="hljs-comment">// scripts/deploy.ts</span>
<span class="hljs-keyword">import</span> { ethers } <span class="hljs-keyword">from</span> <span class="hljs-string">"hardhat"</span>

<span class="hljs-keyword">async</span> <span class="hljs-keyword">function</span> <span class="hljs-title function_">main</span>(<span class="hljs-params"></span>) {
  <span class="hljs-keyword">const</span> factory = <span class="hljs-keyword">await</span> ethers.<span class="hljs-title function_">getContractFactory</span>(<span class="hljs-string">"Llama"</span>)
  <span class="hljs-keyword">const</span> contract = <span class="hljs-keyword">await</span> factory.<span class="hljs-title function_">deploy</span>()
  <span class="hljs-keyword">await</span> contract.<span class="hljs-title function_">deployed</span>()
  <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-keyword">await</span> contract.<span class="hljs-title function_">crearLLama</span>(<span class="hljs-literal">true</span>, <span class="hljs-string">"Juanita 2"</span>, <span class="hljs-number">42</span>))
}

<span class="hljs-title function_">main</span>()
</code></pre><h3 id="h-mappings" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Mappings</h3><p>Los <code>mappings</code> son en pocas palabras una tabla “<em>clave-valor”</em>.</p><pre data-type="codeBlock" text="mapping(string =&gt; UnaLLama) corralito;

function guardarLlamaEnCorral(
    bool _guapa,
    string calldata _nombre,
    uint _edad
) external {
    corralito[_nombre] = crearLLama(_guapa, _nombre, _edad);
}

function sacarLlamaDeCorral(string calldata _nombre)
    external
    view
    returns (UnaLLama memory)
{
    return corralito[_nombre];
}
"><code><span class="hljs-keyword">mapping</span>(<span class="hljs-keyword">string</span> <span class="hljs-operator">=</span><span class="hljs-operator">></span> UnaLLama) corralito;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">guardarLlamaEnCorral</span>(<span class="hljs-params">
    <span class="hljs-keyword">bool</span> _guapa,
    <span class="hljs-keyword">string</span> <span class="hljs-keyword">calldata</span> _nombre,
    <span class="hljs-keyword">uint</span> _edad
</span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> </span>{
    corralito[_nombre] <span class="hljs-operator">=</span> crearLLama(_guapa, _nombre, _edad);
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">sacarLlamaDeCorral</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> <span class="hljs-keyword">calldata</span> _nombre</span>)
    <span class="hljs-title"><span class="hljs-keyword">external</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">UnaLLama <span class="hljs-keyword">memory</span></span>)
</span>{
    <span class="hljs-keyword">return</span> corralito[_nombre];
}
</code></pre><p>Ejemplo de deploy script,</p><pre data-type="codeBlock" text="async function main() {
  const factory = await ethers.getContractFactory(&quot;Llama&quot;)
  const ct = await factory.deploy()
  await ct.deployed()
  console.log(await ct.crearLLama(true, &quot;Juanita 2&quot;, 42))
  const tx = await ct.guardarLlamaEnCorral(true, &quot;Juanita&quot;, 42)
  await tx.wait()
  console.log(await ct.sacarLlamaDeCorral(&quot;Juanita&quot;))
}
"><code>async <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">main</span>(<span class="hljs-params"></span>) </span>{
  const factory <span class="hljs-operator">=</span> await ethers.getContractFactory(<span class="hljs-string">"Llama"</span>)
  const ct <span class="hljs-operator">=</span> await factory.deploy()
  await ct.deployed()
  console.log(await ct.crearLLama(<span class="hljs-literal">true</span>, <span class="hljs-string">"Juanita 2"</span>, <span class="hljs-number">42</span>))
  const <span class="hljs-built_in">tx</span> <span class="hljs-operator">=</span> await ct.guardarLlamaEnCorral(<span class="hljs-literal">true</span>, <span class="hljs-string">"Juanita"</span>, <span class="hljs-number">42</span>)
  await <span class="hljs-built_in">tx</span>.wait()
  console.log(await ct.sacarLlamaDeCorral(<span class="hljs-string">"Juanita"</span>))
}
</code></pre><h3 id="h-ints-strings-arrays" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">¿ ints, strings, arrays ?</h3><p>Estos son primitivos en muchos lenguajes de programación y apuesto que ya tienes idea de como usarlos. Vamos, modifica <code>Llama.sol</code> y prueba : )</p><p>Lista de <em>“tipos de datos”</em> en Solidity: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://docs.soliditylang.org/en/v0.8.16/types.html">https://docs.soliditylang.org/en/v0.8.16/types.html</a></p><hr><h2 id="h-wagmi-react-interaccion-con-el-frontend-y-finalizacion" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Wagmi React: Interacción con el Frontend y finalización</h2><p>Sí <em>NO</em> has llevado la guía a la ligera, hasta este punto ya tienes lo suficiente conocimiento para crear tus contratos e integrarlos con el Frontend.</p><p>Mi enfoque no es enseñarte React, mucho menos Javascript. Del Frontend, NextJs es importante ya que se usa muchísimo en el Ecosistema, saber el enrutamiento y la estructura de archivos y cómo configurar Wagmi &amp; Rainbowkit es suficiente para arrancar.</p><blockquote><p>La documentación de estas herramientas es tu fuente de la verdad.</p></blockquote><p>Para esta etapa vamos a necesitar un template que trae todo lo que vimos en la guía. La plantilla ya trae un set de componentes React y una interfaz básica para modificar y jugar con el código.</p><h3 id="h-la-plantilla-nextjs-rainbow-hh" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">La plantilla: NextJS-Rainbow-HH</h3><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/e4dbfd0ddc5b69f0e23bff5edd4ffa4a3b6e9dc97122eafd4832658139950354.png" alt="https://github.com/D3Portillo/nextjs-rainbow-hh" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">https://github.com/D3Portillo/nextjs-rainbow-hh</figcaption></figure><p>Para usar la plantilla, vamos a <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/D3Portillo/nextjs-rainbow-hh">https://github.com/D3Portillo/nextjs-rainbow-hh</a> y clickeamos en <em>“Use this template”</em>, agregamos un nombre que deseemos asignar para este repositorio a crear.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/d472ca816f6463b248afad495caf18773e3123ebdcd45f992b5acff26c424bc3.png" alt="La imágen muestra la interfaz de creación de un repositorio usando la plantilla en https://github.com/D3Portillo/nextjs-rainbow-hh " blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">La imágen muestra la interfaz de creación de un repositorio usando la plantilla en https://github.com/D3Portillo/nextjs-rainbow-hh</figcaption></figure><h3 id="h-estructura-del-proyecto" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Estructura del proyecto</h3><p>La estructura del proyecto es muy similar a nuestra experimentación anterior. La diferencia es que ahora hay una nueva carpeta(<code>components/</code>) que contiene los trozos de interfaz que pintamos en nuestra DApp.</p><p>También ha cambiado el nombre de algunas variables de entorno. Unas llevan el prefijo <code>NEXT_PUBLIC</code>, esto es porque NextJs tomara las definiciones de entorno sólo al ejecutarse en NodeJs más no en el navegador, <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://nextjs.org/docs/basic-features/environment-variables#exposing-environment-variables-to-the-browser">para “permitir” acceder a estas definiciones se antepone NEXT_PUBLIC por convención y consistencia</a>.</p><h3 id="h-guestbooksol" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">GuestBook.sol</h3><pre data-type="codeBlock" text="// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;

contract GuestBook {
    event NewNote(address indexed persona, string contenido);

    function addNote(string calldata _contenido) external {
        emit NewNote(msg.sender, _contenido);
    }
}
"><code><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.8.9;</span>

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">GuestBook</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">event</span> <span class="hljs-title">NewNote</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> <span class="hljs-keyword">indexed</span> persona, <span class="hljs-keyword">string</span> contenido</span>)</span>;

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">addNote</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> <span class="hljs-keyword">calldata</span> _contenido</span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> </span>{
        <span class="hljs-keyword">emit</span> NewNote(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>, _contenido);
    }
}
</code></pre><p>Nuestro proyecto sólamente envía logs al invocar la función <code>addNote</code>. Para acceder a los logs desde el frontend, filtramos los registros de la chain con el <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://reactjs.org/docs/hooks-intro.html">React Hook</a> ubicado en la ruta <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/D3Portillo/nextjs-rainbow-hh/blob/master/lib/hooks/useNotesList.ts#L24">lib/hooks/useNotesList.tsx</a></p><pre data-type="codeBlock" text="import { useEffect, useState } from &quot;react&quot;

import getContract from &quot;@/lib/getContract&quot;
import { noOp } from &quot;@/lib/helpers&quot;

const GuestBook = getContract(&quot;GuestBook&quot;)
function useNotesList() {
  const [list, setList] = useState([] as Note[])

  useEffect(() =&gt; {
    GuestBook.queryFilter(GuestBook.filters.NewNote())
      .then((list) =&gt; {
        return list.map((item) =&gt; {
          const {
            args: { persona, contenido },
            transactionHash,
          } = item
          return {
            transactionHash,
            persona,
            contenido,
          }
        })
      })
      .then(setList)
      .catch(noOp)
  }, [])

  return list
}

export default useNotesList
"><code><span class="hljs-keyword">import</span> { useEffect, useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>

<span class="hljs-keyword">import</span> getContract <span class="hljs-keyword">from</span> <span class="hljs-string">"@/lib/getContract"</span>
<span class="hljs-keyword">import</span> { noOp } <span class="hljs-keyword">from</span> <span class="hljs-string">"@/lib/helpers"</span>

<span class="hljs-keyword">const</span> <span class="hljs-title class_">GuestBook</span> = <span class="hljs-title function_">getContract</span>(<span class="hljs-string">"GuestBook"</span>)
<span class="hljs-keyword">function</span> <span class="hljs-title function_">useNotesList</span>(<span class="hljs-params"></span>) {
  <span class="hljs-keyword">const</span> [list, setList] = <span class="hljs-title function_">useState</span>([] <span class="hljs-keyword">as</span> <span class="hljs-title class_">Note</span>[])

  <span class="hljs-title function_">useEffect</span>(<span class="hljs-function">() =></span> {
    <span class="hljs-title class_">GuestBook</span>.<span class="hljs-title function_">queryFilter</span>(<span class="hljs-title class_">GuestBook</span>.<span class="hljs-property">filters</span>.<span class="hljs-title class_">NewNote</span>())
      .<span class="hljs-title function_">then</span>(<span class="hljs-function">(<span class="hljs-params">list</span>) =></span> {
        <span class="hljs-keyword">return</span> list.<span class="hljs-title function_">map</span>(<span class="hljs-function">(<span class="hljs-params">item</span>) =></span> {
          <span class="hljs-keyword">const</span> {
            <span class="hljs-attr">args</span>: { persona, contenido },
            transactionHash,
          } = item
          <span class="hljs-keyword">return</span> {
            transactionHash,
            persona,
            contenido,
          }
        })
      })
      .<span class="hljs-title function_">then</span>(setList)
      .<span class="hljs-title function_">catch</span>(noOp)
  }, [])

  <span class="hljs-keyword">return</span> list
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> useNotesList
</code></pre><h3 id="h-deploymentsgoerliguestbookjson" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">deployments/goerli/GuestBook.json</h3><p>Esta es la información de los deployments que hagamos (espejo de los deploy scripts en <code>/deploy</code>). Por lo que te invito a modificar <code>/contracts/GuestBook.json</code> con una feature, agregar condicionales, o por ejemplo:</p><ul><li><p>¿Qué sucede sí mi string está vacío ?, validación de errores.</p></li><li><p>Agregar un deploy a Ethereum Mainnet, Solana o Polygon.</p></li><li><p>¿No usar logs para obtener las notas dejadas en la DApp y usar una variable de estado ?</p></li><li><p>Convertir cada nota en un <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://academy.binance.com/en/articles/a-guide-to-crypto-collectibles-and-non-fungible-tokens-nfts">NFT</a> ó <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://academy.binance.com/en/articles/what-are-soulbound-tokens-sbt">SBT</a></p></li><li><p>¿ Limitar la cantidad de Notas que puede dejar una persona ?</p></li></ul><p>Lo que gustes, vos podes hacer lo que querrás 😋</p><h3 id="h-tu-proyecto" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Tu Proyecto</h3><p>Luego de modificar el proyecto ejecuta <code>npx hardhat run deploy</code>, levanta nodos locales con <code>npx hardhat run</code> y lo más importante, juega, modifica, pregunta : )</p><p>Haz deploy de tus cambios porque la información en <code>/deployments</code> es mía, de mi cuenta de pruebas. Haz el proyecto tuyo.</p><p>Ya habrás notado que la guía es un tutorial de cómo crear el template que acabas de usar, Felicidades!! 🦄. Te invito a leer un poco la documentación de <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://reactjs.org/">React</a> y <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://nextjs.org/">NextJs</a>, no vendrá mal, y además no debe faltar leer sobre <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://hardhat.org/">Hardhat</a> y <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://docs.soliditylang.org">Solidity</a>.</p><p>Sugerencias, comentarios, quejas; lo que se te ocurra 🥴, más que bienvenid@s :)</p><h2 id="h-plus-ultra-lanzando-nuestra-dapp-en-vercel" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Plus Ultra: Lanzando nuestra DApp en Vercel</h2><p><strong>Vercel</strong> es una compañía amada por los Frontend devs para lanzar sus proyectos. <em>“Develop, Preview, Ship”</em> es su eslogan y les pega a la perfección.</p><blockquote><p>Nota <s>random</s> personal: Vercel es una de las empresas dónde quiero trabajar y tirar código. Tengo un crush con su CEO — Guillermo Rauch<code>(12)</code>, un <em>crack</em>.</p></blockquote><p>Para esta sección necesitamos crear una cuenta en <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://vercel.com/new">https://vercel.com/new</a>, y luego inicias sesión con tu GitHub.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/a7efb74b792a90a71e720bbebd39184acb0ef3c7087e72fbd8263b112d53ee27.png" alt="La imágen muestra la pantalla de inicio de sesión de vercel.com" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">La imágen muestra la pantalla de inicio de sesión de vercel.com</figcaption></figure><p>Ahora buscamos el proyecto que vamos a lanzar en Vercel de la lista de repositorios(<em>en mi caso es “mi-proyecto-guapo”</em>). Damos a <em>“Import” y</em> configuramos variables de entorno.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/079bc76ed650d9f74b14a0ee06ca59a718cbdb922f66ee3fbd4be14ed8e6af4a.png" alt="Seleccionando el repositorio dónde vive nuestro proyecto NextJS" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">Seleccionando el repositorio dónde vive nuestro proyecto NextJS</figcaption></figure><p>Configuramos las variables de entorno. Recuerda que para forzar Goerli seteamos <code>NEXT_PUBLIC_FORCE_GOERLI_PROVIDER=true</code> y reemplazas <code>NEXT_PUBLIC_ALCHEMY_API_KEY</code> por tu API Key de Alchemy 😛.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/b6179e3bf88a287a3625c3cbede605a872f9e64422f5a83b60396d9d0d6ec4ca.png" alt="La imágen muestra la configuración de Variables de entorno en el Dashboard de Vecel" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">La imágen muestra la configuración de Variables de entorno en el Dashboard de Vecel</figcaption></figure><p>Esperamos un momento, y tendremos nuestro DApp con url para compartir 😍</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/e6e83b6f2ddbe5327c52b82d1245885e99d29a997f3772587b3eeadfc7df565e.png" alt="https://bukrr.vercel.app" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">https://bukrr.vercel.app</figcaption></figure><hr><p>🤘Genial, hemos aprendido mucho. Ahora tú tienes conocimientos sobre el Ecosistema Web3, Ethereum, Sistemas Distribuidos y puntualmente <em>“Cómo desarrollar Aplicaciones Descentralizadas”</em> :)</p><p>Recuerda, la idea de esta guía es demostrar lo más posible cómo desarrollar DApps con un set de herramientas populares y validadas por los desarrolladores. Faltaron un par de cositas que espero con mucha inquietud presentar en otra Guía. Una de ellas es mejorar el consumo de información en el Frontend con <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://thegraph.com">Subgraphs</a>.</p><p>Algo más, si te preguntas, ¿Cómo se interconecta la información de Ethereum con servicios externos a la red ?, la respuesta, <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://ethereum.org/en/developers/docs/oracles/">Oracles</a>.</p><hr><p>Si llegaste hasta este punto de la lectura, y bueno; sí cualquier trozo de texto te ayudó para aprendizaje, espero y te sientas orgulloso. Sé que tienes muchas preguntas, pero ahora te será más sencillo buscar lo que no sabes y reforzar lo que sabes.</p><p>También, si este fue tu primer bailecito con la Web3, Bienvenido 🥰.</p><h2 id="h-notas-finales-y-un-poco-sobre-mi" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Notas finales y un poco sobre mí</h2><p>Me llamo <strong>Denny Portillo</strong>, Salvadoreño y estudiante de <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://42madrid.com">42 Madrid</a>. Trabajo como desarrollador Frontend Web3 en <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://daoism.systems">Daoism Systems</a>. Quiero comentarte con mucha honestidad que en este ecosistema nunca paras de encontrar contenido que aprender. Muchas ocasiones te desesperas por TODO; agrego que esto me divierte, me gusta. No es aburrido y la Web3 tiene mucha vida por delante.</p><p>Si te interesa desarrollar DApps, hazlo. Inténtalo, equivócate, práctica, práctica, práctica. No dejes de dudar y preguntar. Únete a comunidades de desarrolladores y crea lo que se te ocurra, : )</p><p>¿No sabes a qué comunidad unirte ?, puedes iniciar en <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://buildspace.so/">https://buildspace.so</a>. En Buildspace aprendí a crear Smart Contracts y lanzarlos en una Testnet <code>(13)</code>.</p><p>Para terminar. No sabes lo que me gustó crear este documento, espero compartas la guía con tus amigos y si tienes comentarios, dudas; arrojalas que estamos para apoyar.</p><p>Antes de irte, si gustas, sigueme en Twitter 🚀: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/d3portillo">https://twitter.com/d3portillo</a></p><h2 id="h-referencias" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Referencias</h2><ol><li><p>The Merge: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://ethereum.org/en/upgrades/merge">https://ethereum.org/en/upgrades/merge</a></p></li><li><p>FOMO: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://blog.orange.es/consejos-y-trucos/que-es-fomo/">https://blog.orange.es/consejos-y-trucos/que-es-fomo/</a></p></li><li><p>Intro to Ethereum: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://ethereum.org/en/developers/docs/intro-to-ethereum/">https://ethereum.org/en/developers/docs/intro-to-ethereum</a></p></li><li><p>Ethereum Virtual Machine: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://ethereum.org/es/developers/docs/evm/">https://ethereum.org/es/developers/docs/evm</a></p></li><li><p>Maquina de Estados: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://es.wikipedia.org/wiki/M%C3%A1quina_de_estados">https://es.wikipedia.org/wiki/Máquina_de_estados</a></p></li><li><p><em>“Turing Completeness”</em> y Modelo de ejecución en la EVM</p><ol><li><p>Turing Complete Blockchain: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://academy.binance.com/en/glossary/turing-complete">https://academy.binance.com/en/glossary/turing-complete</a></p></li><li><p>Ethereum Yellow Paper #8fea825, Cap. 9 — Execution Model: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://ethereum.github.io/yellowpaper/paper.pdf">https://ethereum.github.io/yellowpaper/paper.pdf</a></p></li></ol></li><li><p>Linkedin post <em>“5 Paquetes de React para Frontend Devs en Web3”</em>: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.linkedin.com/posts/d3portillo_5-paquetes-de-react-para-frontends-en-web3-activity-6948890361192722432-nXGU">https://www.linkedin.com/posts/d3portillo_5-paquetes-de-react-para-frontends-en-web3-activity-6948890361192722432-nXGU</a></p></li><li><p>Ethereum RPC: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="http://ethereum.org/en/developers/docs/apis/json-rpc/">https://ethereum.org/en/developers/docs/apis/json-rpc</a></p></li><li><p>Moralis vs Infura vs Alchemy: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://moralis.io/whats-the-difference-between-moralis-alchemy-and-infura">https://moralis.io/whats-the-difference-between-moralis-alchemy-and-infura</a></p></li><li><p>Mainnet Network: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://academy.binance.com/es/glossary/mainnet">https://academy.binance.com/es/glossary/mainnet</a></p></li><li><p>Variables de Entorno: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://es.wikipedia.org/wiki/Variable_de_entorno">https://es.wikipedia.org/wiki/Variable_de_entorno</a></p></li><li><p>Guillermo es el creador de Socket.io, Mongoose y otras herramientas populares del ecosistema NodeJS. Hay contenido en este documento de su charla <em>“Merging Design and Development”</em>, dónde habla sobre <em>“Consistent UI”</em> y Sistemas distribuidos, mirala acá: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.youtube.com/watch?v=3hccXiXI0u8">https://www.youtube.com/watch?v=3hccXiXI0u8</a></p></li><li><p>Repositorios usados en la guía</p><ol><li><p>Jeshejojo: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/D3Portillo/jeshejojo">https://github.com/D3Portillo/jeshejojo</a></p></li><li><p>Plantilla Bukrr: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/D3Portillo/nextjs-rainbow-hh">https://github.com/D3Portillo/nextjs-rainbow-hh</a></p></li></ol></li></ol><h2 id="h-glosario" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Glosario</h2><ul><li><p><strong>Blockend:</strong> El Desarrollo Backend, Frontend y de Smart Contracts para una DApp.</p></li><li><p><strong>DApp:</strong> Aplicación Descentralizada (Decentralized App).</p></li><li><p><strong>ETH:</strong> Ether(Ξ). Token principal y nativo de la red Ethereum.</p></li><li><p><strong>EVM:</strong> Ethereum Virtual Machine.</p></li><li><p><strong>Solidity:</strong> Lenguaje de programación parecido a Javascript para crear Smart Contracts en la EVM.</p></li><li><p><strong>Testnet:</strong> Una copia/instancia para pruebas de una red.</p></li><li><p><strong>WAGMI:</strong> We’re all gonna make it.</p></li><li><p><strong>Vyper:</strong> Lenguaje de programación parecido a Python para crear Smart Contracts en la EVM.</p></li></ul><pre data-type="codeBlock" text="Gracias Ana por la sugerencia en crear este documento :)
"><code></code></pre>]]></content:encoded>
            <author>d3portillo@newsletter.paragraph.com (D3Portillo)</author>
        </item>
    </channel>
</rss>