<?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>maxeuwe.eth</title>
        <link>https://paragraph.com/@maxeuwe</link>
        <description>undefined</description>
        <lastBuildDate>Fri, 24 Apr 2026 18:24:50 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>en</language>
        <copyright>All rights reserved</copyright>
        <item>
            <title><![CDATA[La resistencia pionera de Shardeum con el modo de seguridad de red]]></title>
            <link>https://paragraph.com/@maxeuwe/la-resistencia-pionera-de-shardeum-con-el-modo-de-seguridad-de-red</link>
            <guid>5xycIifF6JJzIXTxw3Jz</guid>
            <pubDate>Fri, 05 Apr 2024 10:37:13 GMT</pubDate>
            <description><![CDATA[Shardeum & #ShardeumIsBorderlessDescubra cómo Shardeum está redefiniendo la resiliencia de blockchain con su Modo de Seguridad para garantizar el funcionamiento continuo y la seguridad, incluso en… Promoviendo la innovación y la educación en Web3 En nombre del equipo de ingeniería de Shardeum, estamos encantados de desvelar gradualmente una serie de entradas de blog que revelan los esfuerzos entre bastidores para construir la primera plataforma autoescalable de contratos inteligentes del mund...]]></description>
            <content:encoded><![CDATA[<p>Shardeum &amp; #ShardeumIsBorderless</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/96f3512414b8d8b93764bcf7450606db83e7126b85918fb1b6764b5ece522984.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>Descubra cómo Shardeum está redefiniendo la resiliencia de blockchain con su Modo de Seguridad para garantizar el funcionamiento continuo y la seguridad, incluso en…</p><p><strong>Promoviendo la innovación y la educación en Web3</strong></p><p>En nombre del equipo de ingeniería de Shardeum, estamos encantados de desvelar gradualmente una serie de entradas de blog que revelan los esfuerzos entre bastidores para construir la primera plataforma autoescalable de contratos inteligentes del mundo que escala horizontalmente. A través de estas revelaciones, nuestro objetivo es inspirar tanto a la comunidad como al ecosistema Web3 en general y fomentar futuras innovaciones. Muchas de las características que estamos introduciendo con Shardeum son revolucionarias y establecen nuevos estándares en la tecnología blockchain. Conseguir que Shardeum tenga todas las funcionalidades completas no es sólo tachar elementos de una lista, sino afrontar los mayores retos del sector, hacer que la cadena de bloques sea accesible y asequible, y generalizar su uso. Permanezca atento, no querrá perderse estas actualizaciones.</p><p>En esta entrada del blog, nos centraremos en uno de los últimos avances de Shardeum, ya que hemos completado la implementación de los modos de red, especialmente el “Modo Seguridad” a finales de 2023. Al igual que una respuesta inmune biológica, el modo de seguridad garantiza que las transacciones de las aplicaciones se puedan pausar temporalmente si surgen condiciones de red subóptimas y que Shardeum continúe prosperando y palpitando con vida, procesando transacciones y sincronizando datos mientras tengamos nodos activos. Este hito marca otro paso significativo en nuestro viaje para llevar la descentralización a las masas, subrayando la tecnología avanzada y la preparación minuciosa que lo hacen posible.</p><p><code>Recientemente publicamos un artículo sobre los modos de red, centrándonos en el &quot;Modo Recuperación&quot;, que permitió a Shardeum superar fácilmente una importante caída de la betanet, convirtiéndola en la primera red blockchain fragmentada en autorrestaurar todos sus datos. ¡Échale un vistazo aquí! https://shardeum.org/blog/shardeum-resilience-restoring-sharded-network/</code></p><p><strong>Entendiendo los Modos de Red en Shardeum</strong></p><p>Con esta actualización de Shardeum, los modos de red (de los cuales el modo de seguridad es uno de los principales) se han integrado con éxito en la red Shardus. Los modos de red, en esencia, son los diferentes estados de la red que garantizan colectivamente que la red pueda gestionar su ciclo de vida con eficacia, desde la formación y el funcionamiento a través de posibles crisis e incluso en un modo de recuperación, garantizando así la estabilidad de la red en el caso de que surjan circunstancias de red subóptimas.</p><p><em>Es importante subrayar que, incluso con las ventajas que aportan los modos de red, algunos de ellos, como el modo de reinicio o apagado, puede que nunca lleguen a surgir en Shardeum. Por ejemplo, sería necesario que todos (o casi todos) los validadores se perdieran para activar el modo reinicio. Pero Shardeum tiene modos como el reinicio para </em><strong><em>prepararse</em></strong><em> incluso para los escenarios más improbables.</em></p><p><strong>Los siete (¡maravillosos!) modos de red de Shardeum</strong></p><p>De forma similar a los semáforos que dirigen el flujo de vehículos, estos modos guían el comportamiento de nuestra red en respuesta al número de validadores activos y otros umbrales clave. Desde un punto de vista técnico, los modos de red de Shardeum están diseñados para responder dinámicamente a las necesidades y condiciones de la red. Guían la forma en que interactúan los validadores, garantizando tanto el rendimiento como la resistencia. Veamos qué significa cada modo para Shardeum:</p><p><strong>Formación</strong>: Esta fase inicial permite a los nuevos nodos unirse y sincronizar sus datos de estado hasta alcanzar un número mínimo especificado de nodos activos, preparando la red para su fase operativa.</p><p><strong>Procesamiento:</strong> En este modo, la red está plenamente operativa, procesando transacciones de aplicaciones. Los nodos pueden unirse, salir o ser sustituidos según sea necesario, garantizando la funcionalidad continua de la red. Este es el modo de funcionamiento por defecto en Shardeum.</p><p><strong>Seguridad</strong>: Se activa cuando se cuestiona la estabilidad operativa de la red. Este modo restringe la actividad a las transacciones de protocolo, deteniendo las transacciones de aplicación para salvaguardar la integridad de la red.</p><p><strong>Recuperación</strong>: Se inicia cuando el recuento de nodos activos cae por debajo de un determinado umbral. Este modo detiene el procesamiento de transacciones de aplicaciones y la sincronización de datos de aplicaciones. Su objetivo es añadir rápidamente nodos de reserva para restaurar los nodos mínimos necesarios de la red, centrándose en la sincronización de datos de protocolo y la creación de nuevos registros de ciclo.</p><p><strong>Reinicio</strong>: Este modo se activa cuando es necesario reiniciar la red, a menudo tras un apagado completo o cuando se pierden demasiados nodos. Los nodos se unen a la red sin sincronizar los datos de la aplicación, confiando en los Archivers para obtener la información esencial de la red. El objetivo es alcanzar rápidamente el mínimo de nodos necesarios para pasar al modo de restauración.</p><p><strong>Restauración</strong>: Los nodos se centran en sincronizar los datos de estado de los Archivadores y otros nodos para pasar a estar activos. Este modo es fundamental para pasar de un estado de recuperación o reinicio a plenamente operativo, garantizando que todos los nodos estén sincronizados y activos.</p><p><strong>Apagado</strong>: Este modo final puede activarse por una acción administrativa o una caída significativa de los nodos activos. Detiene todas las transacciones y prepara a los nodos para salir de la red, garantizando que los Archiver tengan un registro del cierre para posibles reinicios futuros de la red.</p><p>Cada modo tiene su momento y su lugar, incluso en caso de que las condiciones de la red no sean óptimas, y los modos en su conjunto garantizan que la red sea resistente, fuerte y pueda seguir siempre viva. En primer lugar, vamos a explorar el modo de seguridad, antes de centrar nuestra atención en los beneficios generales de tener este nivel de preparación en el contexto de la tecnología distribuida y descentralizada. Ten en cuenta que exploraremos los modos restantes en detalle en los próximos posts.</p><p><strong>Características y ventajas del modo Seguridad</strong></p><p><strong>1. La seguridad ante todo</strong></p><p>El Modo de Seguridad garantiza que si hay una caída significativa de validadores activos, Shardeum pasará a un estado de protección, priorizando la sincronización de datos sobre el procesamiento de transacciones de la aplicación.</p><p><strong>2. Estabilidad e integridad de la red</strong></p><p>El modo de seguridad está diseñado para mantener la estabilidad de la red cuando el número de nodos activos cae por debajo de un determinado umbral. Al limitar la red al procesamiento exclusivo de transacciones de protocolo, reduce la carga y la complejidad de las operaciones, ayudando a garantizar que las funciones centrales de la red permanezcan intactas y seguras.</p><p><strong>3. Prevención de la corrupción o pérdida de datos</strong></p><p>En los sistemas basados en fragmentos, la pérdida de un número significativo de nodos puede poner en riesgo la integridad de los datos, especialmente si estos nodos son responsables de fragmentos específicos. Al entrar en modo seguro, el sistema puede prevenir escenarios en los que las transacciones podrían procesarse incorrectamente o en los que los datos podrían perderse debido a una cobertura insuficiente de nodos.</p><p><strong>4. Respuesta automática al estrés de la red</strong></p><p>El modo de seguridad actúa como mecanismo de respuesta automática ante caídas repentinas de la participación de los nodos. Este cambio automático puede ser crucial para evitar fallos en cascada que podrían producirse si la red siguiera funcionando en condiciones normales a pesar de una reducción significativa de los nodos activos.5. Facilita la recuperación de la red</p><p>Al centrarse únicamente en las transacciones del protocolo, el modo de seguridad permite que la red funcione con una capacidad reducida, lo que resulta más fácil de mantener y gestionar. Este funcionamiento simplificado facilita que los nodos nuevos o en recuperación se sincronicen y participen en la red, ayudando en el proceso general de recuperación.</p><p><strong>5. Garantiza la integridad del consenso</strong></p><p>En los sistemas descentralizados, mantener el consenso es vital. El modo de seguridad ayuda a preservar la integridad del proceso de consenso reduciendo la complejidad operativa de la red y garantizando que los nodos restantes puedan seguir acordando el estado de la red.</p><p><strong>6. Protege frente a posibles ataques</strong></p><p>En algunos escenarios, una caída repentina de los nodos activos podría deberse a un ataque coordinado. Al cambiar al modo de seguridad, la red reduce su vulnerabilidad, ya que sólo se procesan las transacciones esenciales del protocolo, dejando menos espacio para que las actividades maliciosas exploten un estado debilitado de la red.</p><p><strong>7. Mantiene las operaciones esenciales</strong></p><p>Incluso en una capacidad reducida, el modo de seguridad garantiza que las operaciones esenciales de la red continúen. Esto significa que se conservan las actualizaciones críticas, las tareas de mantenimiento necesarias y las funcionalidades básicas de la red, garantizando que ésta no se detiene por completo.</p><p>En resumen, el modo de seguridad en un sistema como Sharduem proporciona una red de seguridad crítica que garantiza la estabilidad de la red, evita la pérdida de datos, ayuda a la recuperación y mantiene la integridad de los mecanismos de consenso durante periodos de estrés o de actividad reducida de los nodos. Este modo es esencial para la resistencia y la sostenibilidad a largo plazo de una red descentralizada basada en fragmentos.</p><p><strong>Ventajas de los modos de red en Shardeum: Una visión.</strong></p><p>Así que ahora que tenemos una comprensión global de las ventajas del modo de seguridad, ¿qué ventajas aportan los otros modos principales a Shardeum?</p><p>⚡<strong>Formación rápida:</strong> Durante la fase de formación, la red crece a un ritmo impresionante, alcanzando rápidamente la capacidad operativa.</p><p>🔄 <strong>Rotación eficiente</strong>: Durante la fase de procesamiento, los validadores rotan de forma eficiente, equilibrando la demanda de la red y la disponibilidad de los validadores a la perfección.</p><p>🚦 <strong>Adaptabilidad dinámica</strong>: También durante la fase de procesamiento, la red puede crecer o decrecer en función de la demanda, garantizando un rendimiento óptimo.</p><p>🔒 <strong>Recuperación robusta</strong>: Incluso si la cantidad total de validadores activos necesarios disminuye considerablemente, el modo de recuperación de Shardeum entra en acción para estabilizar, reagrupar y reconstruir.</p><p>🤝 <strong>Colaboración sin fisuras</strong>: En la fase de reinicio, gracias al papel de los archivadores, la red puede recuperarse incluso en el caso de que se pierdan todos los validadores activos</p><p>🚀 <strong>Reinicios rápidos</strong>: También durante la fase de reinicio, en el improbable escenario de pérdida total de validadores, el modo de reinicio asegura una rápida resurrección de la red — esto significa que Shardeum siempre será capaz de recuperarse, incluso en escenarios extremadamente improbables.</p><p>🔄 <strong>Sincronización rápida</strong>: Al pasar de un modo a otro, los procesos de sincronización se aceleran para que los nodos se pongan al día.</p><p>💡 <strong>Aprendizaje continuo</strong>: La aplicación nos enseña a adaptarnos y evolucionar, lo que nos lleva a futuras innovaciones. A los Shardianes estelares A nuestros apasionados Shardians, dedicados operadores de nodos, colaboradores del ecosistema y socios inestimables: ¡GRACIAS! Vuestro inquebrantable apoyo, energía y compromiso hacen que cada línea de código y cada función implementada merezcan la pena. Sois el corazón de Shardeum, y juntos, ¡estamos dando forma al futuro!</p><p><strong>Conclusión</strong></p><p>¿Qué hemos descubierto hoy? La última implementación de los modos de red de Shardeum, con especial atención al Modo Seguridad, dota a nuestra red de resistencia, adaptabilidad y la capacidad de prosperar en medio de los desafíos. Se trata tanto de salvaguardar las operaciones y los activos como de garantizar que la experiencia de cada shardiano siga siendo de primera categoría. A medida que avanzamos, sabemos que Shardeum es más robusto, resistente y está en constante evolución, todo gracias a nuestros esfuerzos colectivos. Brindemos por una plataforma de contratos inteligentes más segura, rápida y sólida. 🚀</p><p>Fuente de la traducción (4 de abril de 2024): <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://shardeum.org/blog/shardeum-network-safety-mode-resilience/">https://shardeum.org/blog/shardeum-network-safety-mode-resilience/</a></p><p>@Shardeum #ShardeumIsBorderless</p>]]></content:encoded>
            <author>maxeuwe@newsletter.paragraph.com (maxeuwe.eth)</author>
        </item>
        <item>
            <title><![CDATA[Shardeum completa la integración de métodos RPC compatibles con Ethereum]]></title>
            <link>https://paragraph.com/@maxeuwe/shardeum-completa-la-integraci-n-de-m-todos-rpc-compatibles-con-ethereum</link>
            <guid>3bxFnpgFIWXeM0FYXVBq</guid>
            <pubDate>Wed, 20 Mar 2024 14:28:29 GMT</pubDate>
            <description><![CDATA[@Shardeum and #ShardeumIsBorderless Al incorporar métodos RPC compatibles con Ethereum junto con sus innovadores RPC personalizados, Shardeum impulsa la accesibilidad de los desarrolladores y la tecnología…Estamos muy contentos de compartir un hito importante en nuestro viaje hacia la mainnet — la integración exitosa de todos los métodos RPC compatibles con Ethereum necesarios en Shardeum a finales de 2023. Esto llega tras nuestros esfuerzos iniciales del año pasado, comenzando con la impleme...]]></description>
            <content:encoded><![CDATA[<p><strong>@Shardeum and #ShardeumIsBorderless</strong></p><p>Al incorporar métodos RPC compatibles con Ethereum junto con sus innovadores RPC personalizados, Shardeum impulsa la accesibilidad de los desarrolladores y la tecnología…</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/6eec8bbdaf6ad489bbeea2cb036448b01197a08fbf3ab115d4acd5d04bc919d6.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>Estamos muy contentos de compartir un hito importante en nuestro viaje hacia la mainnet — la integración exitosa de todos los métodos RPC compatibles con Ethereum necesarios en <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://shardeum.org/">Shardeum</a> a finales de 2023. Esto llega tras nuestros esfuerzos iniciales del año pasado, comenzando con la implementación de métodos RPC como <em>WSS eth_subscribe</em>. Esta optimización es una parte crucial de la mejora de la funcionalidad de Shardeum. Cabe destacar que hemos introducido métodos RPC Shardeum especializados. Estos están diseñados para complementar los RPCs estándar de Ethereum, capturando las diferencias únicas que Shardeum pone sobre la mesa promoviendo una experiencia de desarrollador sin fisuras y la educación de las innovaciones de vanguardia que ofrece. Esta configuración mejora aún más la plataforma de contratos inteligentes de Shardeum, reduciendo la barrera de entrada no sólo para los desarrolladores basados en EVM, sino para todos los desarrolladores en el ecosistema de ledger/blockchain.</p><p>Antes de sumergirnos en los detalles de nuestra implementación de métodos RPC compatibles con Ethereum, tomemos un momento para explorar por qué Shardeum se destaca como la plataforma de elección para desarrollar o migrar sus dApps, especialmente en un paisaje poblado de blockchains L1 más recientes, soluciones modulares y cadenas L2.</p><p><strong>¿Por qué debería construir en Shardeum?</strong></p><p>Shardeum se dedica a mejorar la escalabilidad de <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://shardeum.org/blog/what-is-layer-1-blockchain/">la capa uno</a> y la descentralización, optando por dar prioridad a estas áreas en lugar de reinventar los componentes clave de cara al usuario, como el lenguaje de <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://shardeum.org/blog/smart-contracts/">contratos inteligentes</a>, la máquina virtual y el explorador de bloques. Este enfoque estratégico se basa en la creencia de que Ethereum ya ofrece un robusto conjunto de herramientas para el desarrollo de contratos inteligentes y dApps, complementado por lenguajes de programación fáciles de desarrollar como Solidity y Vyper. Al aprovechar estos recursos establecidos, queremos ayudar a acelerar los procesos de desarrollo y aprovechar todo el potencial de la tecnología blockchain. Sin embargo, con la introducción de una plataforma independiente de contratos inteligentes a nivel de protocolo, Shardeum se concentra en construir un producto que solucione las auténticas deficiencias de Ethereum y otras cadenas L1: una cadena fragmentada que se autoescala linealmente para mantener altos niveles de escalabilidad, descentralización y seguridad, con el fin de garantizar que las comisiones por transacción sigan siendo muy bajas de forma permanente, independientemente de la demanda en la red.</p><p>La guinda del pastel es la capacidad de Shardeum para procesar transacciones y alcanzar el consenso de forma individual, lo que permite la composabilidad atómica y entre fragmentos con la ejecución de transacciones en paralelo. Este desarrollo elimina eficazmente los cuellos de botella habituales a los que se enfrentan los desarrolladores con llamadas a contratos inteligentes complejos en blockchains contemporáneos y redes fragmentadas que buscan una alta escalabilidad. Aunque Shardeum es naturalmente atractiva para los desarrolladores de EVM como una red de capa 1 basada en EVM, estamos igualmente comprometidos a dar la bienvenida a nuestro redil a aquellos que trabajan fuera del ecosistema EVM.</p><p>El espacio blockchain se nutre de la diversidad, con numerosos protocolos dedicados a fomentar la interoperabilidad entre blockchains variados. Shardeum destaca por ofrecer una solución de capa 1 que aborda de forma decisiva el <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://shardeum.org/blog/shardeum-solves-blockchain-trilemma/">trilema de la escalabilidad</a>, un paso crucial para permitir una interoperabilidad fluida entre plataformas. Nuestro compromiso se extiende a la <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://shardeum.org/blog/shardeum-open-source/">apertura</a> del protocolo en breve, para inspirar y elevar el ecosistema en general. Para los desarrolladores que buscan tener un impacto significativo, independientemente de su plataforma actual, Shardeum ofrece una oportunidad única e indispensable para construir sobre una base que no sólo es escalable, sino también amigable para los desarrolladores con una comunidad masiva de <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="http://discord.gg/shardeum">más de 1 millón de miembros de la comunidad</a> ya en 2 años de lanzamiento.</p><p><strong>¿Qué son los métodos JSON-RPC de Ethereum?</strong></p><p>Los métodos JSON-RPC de Ethereum son un conjunto de llamadas a procedimientos remotos (RPC) codificadas en formato JSON, que permiten interactuar con la red Ethereum. Estos métodos permiten la ejecución de una amplia gama de operaciones, como la consulta de datos de blockchain, el envío de transacciones y el seguimiento de los cambios en la red. Esencialmente, actúan como puente entre aplicaciones o clientes externos y la blockchain de Ethereum, facilitando un flujo fluido de información y comandos. <em>Este conjunto de métodos forma una API que agiliza el acceso y la interacción de los desarrolladores con la red Ethereum.</em></p><p>La incorporación de los métodos JSON-RPC de Ethereum a Shardeum supone una mejora significativa de las capacidades de su plataforma. Estos métodos, que van desde <em>eth_feeHistory</em> hasta <em>eth_chainId</em>, son fundamentales para permitir un seguimiento preciso de las transacciones, la monitorización en tiempo real y una interacción eficiente con la red. Al adoptar estos métodos, Shardeum no sólo facilita una transición más suave para los desarrolladores de Ethereum, sino que también enriquece su ecosistema con funcionalidades avanzadas y posibilidades más amplias. Estos métodos simbolizan el compromiso de Shardeum con la construcción de una plataforma sólida y centrada en el usuario, preparada para la innovación y la colaboración en el amplio espacio Web3. Para aquellos que no estén familiarizados con estos métodos, veamos qué hace cada uno de ellos.</p><p><strong>Métodos RPC populares de Ethereum</strong></p><p>Los siguientes métodos son especialmente populares entre los desarrolladores y proyectos de terceros para extraer información de las redes blockchain permitiéndoles crear una serie de productos y servicios valiosos.</p><ul><li><p><strong>eth_feeHistory:</strong> Este método recupera un rango de tarifas históricas de la red que es útil para analizar los precios del gas a lo largo del tiempo.</p></li><li><p><strong>eth_getBlockReceipts</strong>: Este método proporciona una lista de recibos de todas las transacciones de un bloque determinado y es útil para la confirmación de transacciones y el seguimiento del estado.</p></li><li><p><strong>eth_getBlockTransactionCountByHash</strong>: Este método devuelve el número de transacciones de un bloque, identificadas por su hash, útil para el análisis de bloques.</p></li><li><p><strong>eth_getBlockTransactionCountByNumber</strong>: Este método devuelve el número de transacciones en un bloque, pero identifica el bloque por su número en lugar de por su hash.</p></li><li><p><strong>eth_getTransactionByBlockHashAndIndex</strong>: Este método obtiene una transacción basándose en el hash del bloque y la posición del índice dentro del bloque.</p></li><li><p><strong>eth_getTransactionByBlockNumberAndIndex</strong>: Este método recupera una transacción por su número de bloque e índice dentro de ese bloque.</p></li><li><p><strong>eth_newPendingTransactionFilter</strong>: Este método crea un filtro para notificar sobre nuevas transacciones pendientes. Es útil para rastrear transacciones emitidas pero aún no confirmadas.</p></li><li><p><strong>eth_chainId</strong>: Esto devuelve el ID de cadena actual de la red, una pieza importante de información para asegurar la integridad de la transacción en la red Ethereum correcta.</p></li></ul><p><strong>Los métodos PRC de Ethereum complementan los requisitos personalizados de Shardeum</strong></p><p>Shardeum no sólo garantiza la compatibilidad con los métodos JSON-RPC de Ethereum mencionados anteriormente, sino que también se esfuerza por asegurar que nuestros métodos RPC existentes proporcionen respuestas estrechamente alineadas con las de Ethereum. Este enfoque garantiza una integración perfecta para los desarrolladores familiarizados con Ethereum, mejorando la facilidad de adopción y la interoperabilidad. Y como se ha mencionado, esto también minimiza la cantidad de tiempo que los desarrolladores tienen que dedicar al aprendizaje, lo que permite una transición eficiente y la utilización de nuestra plataforma en proyectos basados en Ethereum.</p><p>Por ejemplo, en el contexto de la implementación de Shardeum del método <em>eth_feeHistory</em> JSON-RPC, existe una diferencia notable en comparación con Ethereum. En lugar de devolver el <em>baseFeePerGas</em>, que es un elemento estándar en Ethereum, Shardeum proporciona una matriz de precios del gas para los bloques especificados. Esta desviación se debe a la estructura de transacción única de Shardeum, que no incorpora <em>baseFeePerGas</em> y es impermeable a <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://shardeum.org/blog/shardeum-time-based-ordering-high-fairness/">MEV</a>. La matriz de precios del gas proporcionada ofrece una visión histórica de los costes de transacción en Shardeum, lo que permite a los usuarios analizar y comprender las tendencias del precio del gas a lo largo del tiempo dentro de la red.</p><p>Otro ejemplo es la notable diferencia que encontraríamos con nuestra implementación de consultas estándar relacionadas con bloques como <em>eth_getBlockReceipts</em> y <em>eth_getBlockTransactionCountByHash</em>. La diferencia se debe al hecho de que Shardeum técnicamente tiene una arquitectura sin bloques. En lugar de bloques, Shardeum tiene ciclos, dado que las transacciones se procesan individualmente en la red, tras lo cual las transacciones procesadas se agrupan en grupos o bloques a intervalos predeterminados antes de ser transferidas a los nodos de archivo. Se calcula que un ciclo dura 60 segundos en Shardeum y que se forma un bloque cada 6 segundos.</p><p><strong>¿Por qué Shardeum necesita métodos JSON-RPC de Ethereum?</strong></p><p>Dado que Shardeum técnicamente no es una blockchain sino que también incorpora el EVM, la integración de sus tecnologías principales presenta desafíos técnicos únicos. Sin embargo, integrar los métodos JSON-RPC de Ethereum en Shardeum es crítico por varias razones:</p><p><strong>1. Compatibilidad y familiaridad</strong></p><p>Al implementar los métodos RPC de Ethereum, Shardeum ofrece un entorno familiar para los desarrolladores ya expertos en el ecosistema de Ethereum. Esto reduce la curva de aprendizaje y acelera la adopción para la comunidad basada en Ethereum que representa más del 85% de todo el ecosistema de contratos inteligentes.</p><p><strong>2. Interoperabilidad</strong></p><p>Los métodos RPC de Ethereum son un estándar en el amplio mundo de los desarrolladores. La adopción de estos métodos por parte de Shardeum garantiza la interoperabilidad con las herramientas y aplicaciones existentes diseñadas para Ethereum, mejorando sus capacidades de integración.</p><p><strong>3.Funcionalidad completa</strong></p><p>La implementación de una gama completa de métodos RPC permite a Shardeum ofrecer una experiencia de servidor RPC más completa y robusta. Garantiza que todas las funcionalidades necesarias estén disponibles para diversas interacciones.</p><p><strong>4.Personalización para la Arquitectura de Shardeum</strong></p><p>Mientras Shardeum se esfuerza por igualar las especificaciones RPC de Ethereum, también adapta u omite ciertos métodos para ajustarse a su estructura única de libro mayor. Esta personalización asegura que los métodos RPC se alinean bien con la arquitectura de Shardeum, mejorando la eficiencia y el rendimiento.</p><p><strong>Ventajas de implementar métodos RPC de Ethereum en Shardeum</strong></p><p>A medida que nos embarcamos en una exploración exhaustiva de los beneficios aportados por la integración de los métodos JSON-RPC de Ethereum en Shardeum, es crucial comprender la profundidad y amplitud de estas ventajas. Esta inmersión en profundidad arrojará luz sobre cómo estos métodos no sólo mejoran la destreza técnica de Shardeum, sino que también afectan significativamente a su red, a la comunidad de desarrolladores y al ecosistema en general.</p><p><strong>1.Beneficios para la red Shardeum</strong></p><p>🧑‍ <strong>Experiencia mejorada para desarrolladores:</strong> Un servidor RPC más completo con métodos similares a Ethereum mejora la experiencia general del desarrollador, haciendo que sea más fácil y eficiente construir en Shardeum.</p><p>📈 <strong>Crecimiento y adopción de la red:</strong> La familiaridad y la facilidad de uso pueden atraer a más desarrolladores del ecosistema Ethereum, contribuyendo al crecimiento y la diversidad de la red Shardeum.</p><p>🏎️ <strong>Rendimiento mejorado:</strong> Con un conjunto robusto de métodos RPC, Shardeum puede manejar una gama más amplia de consultas y comandos de manera más eficiente, lo que lleva a un mejor rendimiento de la red.</p><p><strong>2.Ventajas para los desarrolladores</strong></p><p>🛠️ <strong>Facilidad de transición:</strong> Los desarrolladores experimentados con Ethereum pueden hacer fácilmente la transición a Shardeum, aprovechando sus conocimientos y herramientas existentes.</p><p>🔧 <strong>Riqueza de herramientas e integración:</strong> El acceso a un amplio conjunto de métodos RPC permite la creación de aplicaciones sofisticadas y una integración perfecta con las herramientas existentes basadas en Ethereum.</p><p>💡 <strong>Oportunidades innovadoras:</strong> Las adaptaciones únicas en los métodos RPC de Shardeum ofrecen a los desarrolladores la oportunidad de explorar nuevas funcionalidades e innovaciones que no son posibles en la red Ethereum.</p><p><strong>3.Beneficios para la comunidad</strong></p><p>🌱 <strong>Desarrollo de un ecosistema más amplio:</strong> A medida que más desarrolladores se unen a la red Shardeum, el ecosistema se enriquece, ofreciendo aplicaciones más diversas y sofisticadas a la comunidad.</p><p>🛡️ <strong>Mayor seguridad e integridad de la red:</strong> Con métodos como <em>eth_chainId</em>, Shardeum garantiza transacciones seguras y fiables, fomentando la confianza dentro de la comunidad.</p><p>📊 <strong>Información y análisis en tiempo real:</strong> Métodos como <em>eth_feeHistory</em> y <em>eth_getBlockReceipts</em> proporcionan a la comunidad información valiosa sobre la actividad de la red, mejorando la transparencia y la toma de decisiones informadas.</p><p>En conclusión, la integración de los métodos JSON-RPC de Ethereum en Shardeum representa un paso estratégico hacia la compatibilidad, la funcionalidad mejorada y un mayor atractivo dentro de la comunidad Web3 más amplia. Sienta las bases de un ecosistema vibrante que es a la vez innovador y accesible, beneficiando a la red, a sus desarrolladores y a la comunidad en general.</p><p><strong>Para terminar: Para llevar</strong></p><p>En resumen, el reciente logro de Shardeum en la implantación de los métodos RPC de EVM marca un avance fundamental en la evolución de nuestra red. Mejora nuestras capacidades y garantiza que Shardeum se mantenga a la vanguardia de la innovación. Esta actualización no sólo optimiza nuestro sistema, sino que también significa nuestro compromiso inquebrantable de ofrecer soluciones de vanguardia en el amplio mundo de Web3.</p><p>Shardians, ¡celebremos juntos este hito! 🎉Vuestra pasión y apoyo son las piedras angulares del creciente éxito de Shardeum. ¡Por muchos más hitos y continuos avances en nuestro viaje colectivo!</p><p>Fuente de la traducción (20 de marzo de 2024): <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://shardeum.org/blog/shardeum-integrates-ethereum-rpc/">https://shardeum.org/blog/shardeum-integrates-ethereum-rpc/</a></p>]]></content:encoded>
            <author>maxeuwe@newsletter.paragraph.com (maxeuwe.eth)</author>
        </item>
        <item>
            <title><![CDATA[Hito de Shardeum: Restauración de la red dinámicamente fragmentada]]></title>
            <link>https://paragraph.com/@maxeuwe/hito-de-shardeum-restauraci-n-de-la-red-din-micamente-fragmentada-2</link>
            <guid>VWgYgglmm1t86KApMVTJ</guid>
            <pubDate>Fri, 15 Mar 2024 07:39:47 GMT</pubDate>
            <description><![CDATA[#ShardeumIsBorderless and @ShardeumShardeum’s Blast Off: un logro revolucionarioEl lunes 27 de enero de 2024 se produjo un acontecimiento sin precedentes en el mundo de la web3 que puede compararse a la hazaña histórica de una nave espacial que regresa sin problemas a su plataforma de lanzamiento tras su primera misión de vuelo de prueba. En este extraordinario escenario, Shardeum no sólo se enfrentó a un reto formidable, sino que también salió triunfal, con la capacidad de recuperación de su...]]></description>
            <content:encoded><![CDATA[<p><strong>#ShardeumIsBorderless and @Shardeum</strong></p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/26fa456891d0894477408ff3fca6c165d4671c7af6327fab8737fbcda47a1617.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><h1 id="h-shardeums-blast-off-un-logro-revolucionario" class="text-4xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0"><strong>Shardeum’s Blast Off: un logro revolucionario</strong></h1><p>El lunes 27 de enero de 2024 se produjo un acontecimiento sin precedentes en el mundo de la web3 que puede compararse a la hazaña histórica de una nave espacial que regresa sin problemas a su plataforma de lanzamiento tras su primera misión de vuelo de prueba. En este extraordinario escenario, <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://shardeum.org/">Shardeum</a> no sólo se enfrentó a un reto formidable, sino que también salió triunfal, con la capacidad de recuperación de su red marcando la primera vez que una red fragmentada se ha auto-restaurado en el ámbito de la tecnología de ledger distribuido.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/155bcae6f3d5f07533b56d8dc7fc38e1aaf4b7ab173b8440721aaf266d76caa6.png" alt="Imagen generada por IA" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">Imagen generada por IA</figcaption></figure><p>Al igual que el viaje de una nave espacial implica una planificación meticulosa, ingeniería de precisión y la ejecución perfecta de maniobras complejas, la restauración por Shardeum de su <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://shardeum.org/betanet/">betanet Sphinx</a>, que había sufrido un accidente crítico, requirió un nivel equivalente de dominio tecnológico e innovación. La capacidad de preservar todos los datos de una red, sobre todo de una que funciona con fragmentación dinámica de estados, no tiene nada de innovador.</p><p>Al embarcarnos en esta exploración, no sólo celebramos el trascendental aterrizaje de Shardeum, sino que lo reconocemos como un momento crucial en la evolución de la tecnología web3, un salto que podría redefinir los límites de la resistencia de las redes informáticas y la integridad de los datos.</p><h1 id="h-primera-red-fragmentada-que-se-autorrestaura-y-conserva-los-datos" class="text-4xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0"><strong>Primera red fragmentada que se autorrestaura y conserva los datos</strong></h1><p>Mantener y restaurar una red fragmentada dinámicamente, como Shardeum, conlleva una serie de complejos retos técnicos que la diferencian de las redes blockchain tradicionales como Bitcoin o Ethereum. En un entorno de fragmentación dinámica con autoescalado, la reasignación y el equilibrio continuos de nodos y recursos entre diferentes fragmentaciones son cruciales para optimizar el rendimiento y la escalabilidad. Este flujo constante en la arquitectura de red añade una complejidad significativa a la hora de mantener la coherencia de los datos, garantizar la estabilidad de la red y facilitar una recuperación eficaz de los fallos.</p><p>La criticidad de estos retos se acentúa al contrastar la respuesta de Shardeum a las fluctuaciones de los nodos con la de Bitcoin. La red Bitcoin mantiene su funcionalidad incluso con un número mínimo de nodos, ya que cada nodo completo posee el estado completo y el historial de transacciones. Por el contrario, cada nodo activo de Shardeum no posee el estado completo ni el historial de transacciones, ya que la red Shardeum está fragmentada y cada validador sólo posee un subconjunto del estado completo. La consecuencia de esta fragmentación es que todos los nodos validadores son extremadamente ligeros. Esto crea una plétora de oportunidades y retos de ingeniería. Si un nodo se cae, ¿cómo nos aseguramos de que se conservan todos los datos? Shardeum tiene dos formas principales.</p><p>En primer lugar, Shardeum utiliza la <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://shardeum.org/blog/dynamic-state-sharding-shardeum/">fragmentación dinámica de estados</a>, en la que el espacio global de direcciones se particiona (o divide) en función del número de nodos activos. Cada nodo es responsable de sus particiones asignadas, junto con un determinado radio (R) a su alrededor y particiones adicionales (E) adyacentes a él, lo que garantiza una adaptabilidad dinámica y una sólida redundancia de datos en el marco de la red. Así, aunque un nodo se caiga, sigue habiendo continuidad en la red y no se pierden datos.</p><p>En segundo lugar, Shardeum utiliza <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://shardeum.org/blog/shardeum-archive-nodes-explained/">nodos archivadores</a> para almacenar el estado completo de toda la red. Para ello, los nodos activos envían sus estados parcialmente almacenados a los archivadores para que los recojan. Debido a estos dos factores y a las optimizaciones de diseño, la restauración de una red de este tipo tiene que diseñarse de forma novedosa para seguir facilitando características ventajosas como el autoescalado y el <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://shardeum.org/blog/shardeum-achieves-linear-scalability/">escalado lineal</a>.</p><h1 id="h-entendiendo-el-choque" class="text-4xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0"><strong>Entendiendo el Choque</strong></h1><p>Ahora que entendemos los fundamentos de la fragmentación dinámica de estados y que los nodos archivadores están implicados de alguna manera, vamos a desentrañar primero algunos componentes adicionales más profundamente y a explicarlos. Para entender la caída y la restauración de la betanet Shardeum, primero debemos entender un poco lo siguiente:</p><ul><li><p><strong>Nodos archivadores</strong></p></li><li><p><strong>Detección de archivadores perdidos</strong></p></li><li><p><strong>Modos de red</strong></p></li><li><p><strong>Modo de recuperación</strong></p></li></ul><p>Entender lo básico de cada uno de ellos es necesario antes de sumergirnos de cabeza en los fallos, ¡así que echemos un vistazo!</p><p><strong>Nodos archivadores: Almacenamiento interestelar</strong></p><p>En Shardeum, los nodos archivadores, también llamados archiveros, constituyen una categoría crítica de nodos, encargados de preservar el estado completo y los registros históricos de la red. A diferencia de los nodos activos, los archivadores no participan en los procesos de consenso; su función principal es archivar exhaustivamente la totalidad de los datos de la red, incluidas las transacciones y los recibos. La contribución de los nodos archivadores es esencial para mantener la integridad de la red y garantizar su perfecto funcionamiento, afirmando así el estatus de Shardeum como una red robusta, completa y fiable. Debido a que los archivadores son parte integral de la red, Shardeum debe tener un protocolo para detectar cualquier archivador (y validador) que no responda.</p><p><strong>Detección del Archivador perdido: Tecnología alienígena al descubierto</strong></p><p>Shardeum tiene un protocolo llamado detección de nodos perdidos que detecta cuando los nodos activos dejan de funcionar — esto está reservado <em>únicamente</em> para los nodos activos. Sin embargo, Shardeum también tiene un protocolo para los archivadores que hace algo similar llamado detección de archivador perdido. La detección de archivadores perdidos es un protocolo especializado diseñado para manejar escenarios raros en los que uno o más archivadores dejan de estar operativos y se marcan como perdidos. Dado que los nodos archivadores son fundamentales para mantener la integridad y accesibilidad de los datos históricos dentro de la red, es esencial que, en las raras ocasiones en que no respondan o no funcionen, se detecten estos eventos críticos para mitigar cualquier efecto posterior. Aunque la pérdida de archivadores no causó este fallo en particular, sí lo hizo la interacción entre el protocolo de detección de pérdida de archivadores y un modo de red específico. Examinemos ahora cuáles son los modos de red en Shardeum.</p><p><strong>Modos de red en Shardeum: No se necesita a la NASA</strong></p><p>Una innovación emblemática de Shardeum, impulsada por el protocolo subyacente Shardus, es el marco de modos de red. Estos modos trascienden los estados operativos básicos y encarnan una intrincada coordinación de diversas actividades de nodos, métodos de sincronización de datos y sistemas de gestión de transacciones. Estas configuraciones de red desempeñan un papel crucial en la preservación de la integridad operativa de la red, especialmente en escenarios caracterizados por la pérdida de nodos y datos, ya que Shardeum es una red fragmentada.</p><p>A un nivel más simple, la mejor manera de concebir los modos de red en Shardeum es como planes de contingencia codificados que permiten la continuidad de las operaciones de toda la red, incluso en condiciones improbables como la caída de la red o la degradación de toda la red. Esta resistencia y robustez operativas preprogramadas garantizan que Shardeum siempre seguirá viva, sea cual sea la adversidad a la que se enfrente la red.</p><p>Aunque para entender el fallo no hace falta digerir todas las facetas del marco de los modos de red, sí ayuda familiarizarse con lo básico. Un elemento central del marco de modos de red es la incorporación de varias fases de red distintas: Formación, Procesamiento, Seguridad, Recuperación, Reinicio, Restauración y Apagado. Estos modos están cuidadosamente diseñados para hacer frente a diversas situaciones y emergencias de la red. Sin embargo, el modo que nos ocupa en este artículo es el de recuperación.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/a5e063009de4be9f318e92cee23584e1b86b60f6bb88e4d24da4ed1e3fca535d.png" alt="Imagen generada por IA" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">Imagen generada por IA</figcaption></figure><p><strong>Modo de recuperación de ingeniería inversa: Rosewell revisitado</strong></p><p>El modo de recuperación es 1 de los 7 modos de red antes mencionados. El modo de recuperación se inicia cuando el recuento de nodos activos de la red desciende por debajo de un umbral crítico predefinido (actualmente configurado en 75% o inferior). Este umbral es ajustable según los requisitos de la red. En este modo, la red detiene temporalmente el procesamiento de transacciones de aplicaciones y la sincronización de datos de aplicaciones. Esta estrategia está diseñada para facilitar la expansión de la red mediante la introducción gradual de nodos de reserva como parte de la rotación de nodos, restaurando así el recuento de nodos activos a un nivel óptimo, idealmente por encima del 100%.</p><p>Durante el modo de recuperación, la arquitectura de red de Shardeum permite un aumento incremental de los nodos, con un tope del 20% de crecimiento por ciclo (<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://shardeum.org/blog/what-are-polling-cycles-in-shardeum/">cada ciclo dura aproximadamente 60 segundos</a>). Este ritmo de crecimiento controlado es fundamental para mantener la estabilidad de la red y garantizar una integración perfecta de los nuevos nodos. Un aumento rápido del número de nodos, por ejemplo del 50%, podría desestabilizar la red y complicar el proceso de integración.</p><p>Cada nuevo nodo añadido necesita recursos de red para su sincronización e integración. Al limitar el aumento al 20% por ciclo, la red se asegura de que su infraestructura pueda soportar adecuadamente la adición de nuevos nodos sin tensiones. Este enfoque no sólo preserva la estabilidad de la red, sino que también minimiza el riesgo de incoherencias o errores en los datos durante el proceso de sincronización, manteniendo así la integridad de los datos de la cadena de ciclos.</p><p><strong>La causa principal del accidente: Horizonte de sucesos</strong></p><p>Es importante señalar que había dos errores distintos. El <em>bug de la librería neon</em> — que causaba que los validadores se bloquearan aparentemente al azar y un <em>bug en el protocolo de detección de archivadores perdidos</em> — que no aceptaba una lista de validadores vacía. Aunque es el bug del protocolo de detección de archivadores perdidos el que causó el fallo de la versión betanet, me gustaría explicarles primero el bug de la librería neon.</p><p>En la versión Sphinx 1.9.1, integramos una actualización a una librería que emplea Neon bindings para unir funcionalidades Rust y TypeScript ya que Shardeum está construido predominantemente en TypeScript. Neon es reconocido por su enfoque innovador, aunque experimental, a menudo empujando los límites de las prácticas convencionales de desarrollo de software. Esta integración tenía como objetivo mejorar la interoperabilidad entre estos dos lenguajes, permitiendo una comunicación más eficiente y directa dentro de nuestra arquitectura de software. Sin embargo, esto provocó un error que hacía que los nodos abandonaran aleatoriamente la red.</p><p>En segundo lugar, en el reciente incidente que provocó la caída de la betanet en Shardeum, la causa principal se identificó como una anomalía crítica originada por la interacción entre los dos subsistemas distintos antes mencionados: <em>el mecanismo de detección de archivadores perdidos</em> y el <em>protocolo de modo de recuperación de la red</em>.Este breve fallo se precipitó por la activación simultánea de estos dos mecanismos, un escenario no encontrado ni probado anteriormente. El proceso de archivador perdido se activó junto con el mod de recuperación de red y debido a un fallo en el modo de archivador perdido que no aceptaba una lista de nodos activos vacía. Esto culminó en la caída de la red.</p><h1 id="h-cronica-de-la-recuperacion-del-shock-sistemico-a-la-recuperacion-estelar" class="text-4xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0"><strong>Crónica de la recuperación: Del shock sistémico a la recuperación estelar</strong></h1><p>¿Qué más ocurrió realmente y cuándo? La cronología de los acontecimientos que rodearon la caída de la red y su resolución es la siguiente:</p><ol><li><p><strong>Vulnerabilidad inicial y actualización:</strong> La red se encontró con una vulnerabilidad señalada por el proceso 1.9.1 linting dentro de una biblioteca npm (neon). Se implementó una actualización para solucionar este problema. Sin embargo, esta actualización introdujo inadvertidamente una excepción que no se reprodujo durante las pruebas locales.</p></li><li><p><strong>Excepción intermitente en la biblioteca que provoca cierres del validador</strong>: La biblioteca neon experimentaba excepciones esporádicas que provocaban cierres periódicos de los validadores de red. Aunque el diseño de la red permitía la resistencia mediante el rellenado de estos validadores y, por desgracia, la sincronización de fallos simultáneos entre varios validadores activó el modo de recuperación de la red.</p></li><li><p><strong>Activación del modo de recuperación de la red</strong>: Una vez en el modo de recuperación de la red, el protocolo necesitó borrar y regenerar la lista de nodos activos. La causa principal de la caída de la red fue un fallo simultáneo en el sistema de archivo de pérdidas, que no admitía una lista de validadores vacía.</p></li><li><p><strong>Resolución y restauración de la red</strong>: Se rectificó el fallo y la red se restauró con éxito utilizando los datos almacenados en los archivadores. <strong>Es la primera vez en la historia que una red fragmentada de capa 1 que se ha bloqueado se restaura con éxito y todos los datos de la red se conservan intactos</strong>. Esto no se había conseguido nunca en ninguna red, y mucho menos en una red con fragmentación dinámica de estados. Este logro marcó el exitoso “aterrizaje del cohete” en términos de recuperación de redes.</p></li><li><p><strong>Correcciones realizadas</strong>: Se implementó una corrección preliminar para solucionar el problema de la biblioteca, pero en un esfuerzo continuo por mejorar la estabilidad de la red, se lanzó la versión 1.9.5. Esta actualización introdujo un fallo singular pero crucial. Esta actualización introdujo una corrección de errores singular pero crucial que abordaba otro caso del fallo de enlace de neon, señalando y rectificando una vulnerabilidad específica sin obligar a una actualización de toda la red. Inicialmente, los usuarios que utilizaban la versión 1.9.4 tenían la posibilidad de permanecer en su versión actual u optar por la actualización a la 1.9.5, en función de sus preferencias de rendimiento y estabilidad de la red. Sin embargo, finalmente se decidió que, con el fin de mejorar la estabilidad de la red y resolver los problemas persistentes relacionados con los enlaces de neon, la versión mínima requerida para los validadores debía aumentarse a 1.9.5. Con esta actualización se pretendía excluir sistemáticamente a los validadores que funcionan con la versión 1.9.4, que se han identificado como susceptibles de bloquearse debido a la complicación de los neon bindings antes mencionada. Esto es necesario para asegurarse de que el fallo de neon está totalmente anulado y completamente solucionado.</p></li></ol><p>Ahora que conocemos la cronología y cómo se desencadenaron los principales acontecimientos, echemos un vistazo a lo que ocurrió para que la red se restableciera tan rápidamente.</p><h1 id="h-rumbo-a-la-restauracion" class="text-4xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0"><strong>Rumbo a la restauración</strong></h1><p><strong>Recuperación ágil</strong></p><p>La restauración de la red constó de muchas partes, pero una de las fundamentales fue el modo de recuperación de Shardeum. Como ya se ha dicho, el modo de recuperación se inicia cuando el recuento de nodos activos de la red desciende por debajo de un umbral crítico predefinido y permite un crecimiento rápido, controlado y eficaz de la red de forma segura para restaurarla. Es importante destacar que, sin el ingenio tecnológico de los diseñadores y desarrolladores de los modos de red, Shardeum no habría podido recuperarse de la caída con tanta facilidad ni hacer gala de su capacidad innovadora.</p><p>Además, el equipo técnico de Shardeum realizó esfuerzos clave al lanzarse a la acción inmediata. El primer paso consistió en un análisis exhaustivo para identificar la causa de la caída, que se atribuyó a una anomalía en la interacción entre la detección de archivos perdidos de la red y sus sistemas de modo de recuperación. Consciente de la complejidad del problema, el equipo aplicó rápidamente un enfoque polifacético para hacer frente tanto a las consecuencias inmediatas como a las vulnerabilidades subyacentes.</p><p><strong>Respuesta polifacética del equipo técnico de Shardeum</strong></p><p>Técnicamente, la respuesta fue polifacética: en primer lugar, el equipo aisló los componentes afectados para evitar una mayor degradación de la red. Al mismo tiempo, desplegaron un parche para rectificar el error en el sistema de archivo perdido, asegurándose de que podía manejar una lista de validadores vacía, un descuido crítico que había precipitado el fallo de la red. Para restablecer la plena capacidad operativa de la red, se activaron los datos conservados en los archivadores y se utilizaron para reconstruir el estado de la red antes de la caída, garantizando que no se perdieran datos en el proceso.</p><p>Desde el punto de vista logístico, el equipo se coordinó a través de diferentes zonas horarias y disciplinas, aprovechando las herramientas basadas en la nube para la colaboración y la supervisión en tiempo real. Este esfuerzo coordinado no solo facilitó el rápido desarrollo y despliegue de las correcciones, sino que también garantizó que todos los miembros del equipo estuvieran alineados en el proceso de recuperación y los siguientes pasos.</p><p>Este incidente sirvió como rigurosa prueba de los protocolos de gestión de accidentes de Shardeum y puso de relieve la importancia de las respuestas ágiles e innovadoras a los retos imprevistos. Subraya el compromiso del equipo de mantener una red resistente y segura, preparada para afrontar los complejos obstáculos técnicos que surjan.</p><h1 id="h-aterrizaje-seguro-e-innovacion-espacial" class="text-4xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0"><strong>Aterrizaje seguro e innovación espacial</strong></h1><p>En conclusión, la exitosa restauración de la red fragmentada de Shardeum anuncia un cambio significativo en la tecnología de redes, marcando un hito con implicaciones de largo alcance para la industria. Aunque actualmente no se reconocen en gran medida, innovaciones como los modos de red acabarán estableciendo nuevas normas industriales en la web3.</p><p>Creo desde hace tiempo que las innovaciones fundamentales de Shardeum influirán con toda probabilidad en futuros avances tecnológicos, inspirando innovaciones y nuevas generaciones de tecnologías de libro mayor. Habiendo sido testigo de primera mano de la restauración de la red de Shardeum, la primera de su clase, sé que esto catalizará una reevaluación de los estándares de la industria, lo que potencialmente conducirá a la adopción de protocolos y metodologías más rigurosos en el diseño y la arquitectura de la red.</p><p>Este acontecimiento no sólo pone de manifiesto la destreza técnica y la innovación del <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://shardeum.org/blog/category/about-shardeum-team/">equipo de Shardeum</a>, sino que también señala el comienzo de una era en la que las redes descentralizadas son más robustas, adaptables y capaces de hacer frente a retos imprevistos en la planificación de la recuperación en caso de catástrofe. En última instancia, la tecnología de Shardeum anunciará una nueva era de descentralización.</p><p>Fuente de la traducción (15 de marzo de 2024): <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://shardeum.org/blog/shardeum-resilience-restoring-sharded-network/">https://shardeum.org/blog/shardeum-resilience-restoring-sharded-network/</a></p>]]></content:encoded>
            <author>maxeuwe@newsletter.paragraph.com (maxeuwe.eth)</author>
        </item>
        <item>
            <title><![CDATA[Crear una Dapp para mintear NFT en Shardeum]]></title>
            <link>https://paragraph.com/@maxeuwe/crear-una-dapp-para-mintear-nft-en-shardeum</link>
            <guid>4n1o7B1RnhyDm6xhdCPG</guid>
            <pubDate>Sun, 10 Mar 2024 15:03:11 GMT</pubDate>
            <description><![CDATA[@Shardeum and #ShardeumIsBorderless Echa un vistazo a cómo construir una sencilla aplicación para mintear NFT en la red de pruebas Shardeum utilizando React JS, IPFS y…Esta guía te guiará a través del proceso de creación de una sencilla aplicación de minteo de NFT que utiliza React JS para el front-end, IPFS para el almacenamiento descentralizado y despliega un contrato inteligente Solidity en la red de pruebas Shardeum. Esta aplicación permite a los usuarios mintear NFTs con metadatos person...]]></description>
            <content:encoded><![CDATA[<p>@<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://medium.com/u/d72da890b002?source=post_page-----046fc5032b1d--------------------------------"><strong>Shardeum</strong></a><strong> and #ShardeumIsBorderless</strong></p><p>Echa un vistazo a cómo construir una sencilla aplicación para mintear NFT en la red de pruebas Shardeum utilizando React JS, IPFS y…</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/98ce6742f4dce3a201c234ba89802e6f798b9c937123a25f0702e47d57ae0d28.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>Esta guía te guiará a través del proceso de creación de una sencilla aplicación de minteo de NFT que utiliza React JS para el front-end, IPFS para el almacenamiento descentralizado y despliega un contrato inteligente Solidity en la red de pruebas Shardeum. Esta aplicación permite a los usuarios mintear NFTs con metadatos personalizados como nombre, descripción e imagen/gif.</p><h1 id="h-1-configurar-nuestro-proyecto" class="text-4xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0"><strong>1. Configurar nuestro proyecto</strong></h1><p>Vamos a empezar con la creación de un archivo de proyecto vacío y la inicialización de npm.</p><pre data-type="codeBlock" text="mkdir shardeum-nft-minter
cd shardeum-nft-minter
npm init
"><code>mkdir shardeum<span class="hljs-operator">-</span>nft<span class="hljs-operator">-</span>minter
cd shardeum<span class="hljs-operator">-</span>nft<span class="hljs-operator">-</span>minter
npm init
</code></pre><h1 id="h-2-contrato-inteligente-y-configuracion-de-hardhat" class="text-4xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0"><strong>2. Contrato inteligente y configuración de Hardhat</strong></h1><p>Utilizaremos <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://docs.shardeum.org/smartContracts/deploy/hardhat?_gl=1*fdbkn5*_ga*MTQ1NzQ0MTc4NS4xNzA4NjA0ODQ3*_ga_2VJLR99VYW*MTcxMDA3OTU5Ni45LjAuMTcxMDA3OTU5Ni42MC4wLjA.&amp;_ga=2.208745618.1899079138.1710079597-1457441785.1708604847">Hardhat</a> — Un marco de desarrollo para desplegar, probar y depurar contratos inteligentes.</p><p>i) Ahora, vamos a instalar hardhat como dev-dependencia; elige ‘Create an empty hardhat.config.js’ e instala la <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://docs.openzeppelin.com/contracts/4.x/">librería de contratos de Openzeppelin</a>. Además, vamos a instalar todas las otras bibliotecas necesarias hardhat.</p><pre data-type="codeBlock" text="npm install --save-dev hardhat
npx hardhat
npm install @openzeppelin/contracts
npm install --save ethers@5.7.2 hardhat @nomiclabs/hardhat-waffle ethereum-waffle chai @nomiclabs/hardhat-ethers
"><code>npm install <span class="hljs-operator">-</span><span class="hljs-operator">-</span>save<span class="hljs-operator">-</span>dev hardhat
npx hardhat
npm install @openzeppelin<span class="hljs-operator">/</span>contracts
npm install <span class="hljs-operator">-</span><span class="hljs-operator">-</span>save ethers@<span class="hljs-number">5.7</span><span class="hljs-number">.2</span> hardhat @nomiclabs<span class="hljs-operator">/</span>hardhat<span class="hljs-operator">-</span>waffle ethereum<span class="hljs-operator">-</span>waffle chai @nomiclabs<span class="hljs-operator">/</span>hardhat<span class="hljs-operator">-</span>ethers
</code></pre><p>ii) Crear una carpeta ‘contracts’ y ‘scripts’. En la carpeta de contratos, agrega el siguiente código al archivo <em>NftMinter.sol</em>:</p><pre data-type="codeBlock" text="// SPDX-License-Identifier: MIT

pragma solidity ^0.8.3;
import &quot;@openzeppelin/contracts/token/ERC721/ERC721.sol&quot;;
import &quot;@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol&quot;;
import &quot;@openzeppelin/contracts/utils/Counters.sol&quot;;

contract NFTMinter is ERC721URIStorage {
    using Counters for Counters.Counter;
    Counters.Counter private _tokenIds;
    constructor() ERC721(&quot;Shardeum Dev NFTMinter, &quot;SNFT&quot;) {}
    function mintNFT(address recipient, string memory tokenURI) public returns (uint256) {
        _tokenIds.increment();
        uint256 newItemId = _tokenIds.current();
        _mint(recipient, newItemId);
        _setTokenURI(newItemId, tokenURI);
        return newItemId;
    }
}
"><code><span class="hljs-comment">// SPDX-License-Identifier: MIT</span>

pragma solidity ^<span class="hljs-number">0.8</span><span class="hljs-selector-class">.3</span>;
import "<span class="hljs-keyword">@openzeppelin</span>/contracts/token/ERC721/ERC721.sol<span class="hljs-string">";
import "</span><span class="hljs-keyword">@openzeppelin</span>/contracts/token/ERC721/extensions/ERC721URIStorage.sol<span class="hljs-string">";
import "</span><span class="hljs-keyword">@openzeppelin</span>/contracts/utils/Counters.sol<span class="hljs-string">";

contract NFTMinter is ERC721URIStorage {
    using Counters for Counters.Counter;
    Counters.Counter private _tokenIds;
    constructor() ERC721("</span>Shardeum Dev NFTMinter, <span class="hljs-string">"SNFT"</span>) {}
    function <span class="hljs-built_in">mintNFT</span>(address recipient, string memory tokenURI) public returns (uint256) {
        _tokenIds<span class="hljs-selector-class">.increment</span>();
        uint256 newItemId = _tokenIds<span class="hljs-selector-class">.current</span>();
        <span class="hljs-built_in">_mint</span>(recipient, newItemId);
        <span class="hljs-built_in">_setTokenURI</span>(newItemId, tokenURI);
        return newItemId;
    }
}
</code></pre><p>El contrato anterior hereda del contrato ERC721URIStorage de OpenZeppelin, poniendo a nuestra disposición la mayoría de las funcionalidades necesarias de un ERC721. Puedes personalizar el constructor y cambiar el nombre y el símbolo del token ERC721 a tu gusto. También estamos definiendo una función minNFT en la que hacemos un seguimiento de los tokenIDs y establecemos el tokenURI que almacena los metadatos de ese token. Eso es todo, este único contrato inteligente es suficiente para nuestra aplicación minter.</p><p>iii) Crea un archivo <em>deploy.js</em> en tu carpeta de scripts y añade el siguiente script de despliegue:</p><pre data-type="codeBlock" text="const { ethers } = require(&quot;hardhat&quot;);

async function main() {
    const NFTMinter = await ethers.getContractFactory(&quot;NFTMinter&quot;);
    const nftMinter = await NFTMinter.deploy();
    await nftMinter.deployed();
    console.log(&quot;NFTMinter deployed to:&quot;, nftMinter.address);
  }

    main()
    .then(() =&gt; process.exit(0))
    .catch((error) =&gt; {
      console.error(error);
      process.exit(1);
    });
"><code>const { ethers } <span class="hljs-operator">=</span> <span class="hljs-built_in">require</span>(<span class="hljs-string">"hardhat"</span>);

async <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">main</span>(<span class="hljs-params"></span>) </span>{
    const NFTMinter <span class="hljs-operator">=</span> await ethers.getContractFactory(<span class="hljs-string">"NFTMinter"</span>);
    const nftMinter <span class="hljs-operator">=</span> await NFTMinter.deploy();
    await nftMinter.deployed();
    console.log(<span class="hljs-string">"NFTMinter deployed to:"</span>, nftMinter.<span class="hljs-built_in">address</span>);
  }

    main()
    .then(() <span class="hljs-operator">=</span><span class="hljs-operator">></span> process.exit(<span class="hljs-number">0</span>))
    .catch((<span class="hljs-function"><span class="hljs-keyword">error</span>) => </span>{
      console.error(<span class="hljs-function"><span class="hljs-keyword">error</span>)</span>;
      process.exit(<span class="hljs-number">1</span>);
    });
</code></pre><p>iv) Ahora, vamos a añadir el código necesario para desplegar en Shardeum testnet.</p><pre data-type="codeBlock" text="require(&quot;@nomiclabs/hardhat-waffle&quot;);
module.exports = {
  networks: {
    hardhat: {
    },
    sphinx: {
      url: &quot;https://dapps.shardeum.org/&quot;,
      accounts:[``] // Add private key here
    },
  solidity: &quot;0.8.3&quot;,
};
"><code><span class="hljs-built_in">require</span>(<span class="hljs-string">"@nomiclabs/hardhat-waffle"</span>);
module.exports <span class="hljs-operator">=</span> {
  networks: {
    hardhat: {
    },
    sphinx: {
      url: <span class="hljs-string">"https://dapps.shardeum.org/"</span>,
      accounts:[``] <span class="hljs-comment">// Add private key here</span>
    },
  solidity: <span class="hljs-string">"0.8.3"</span>,
};
</code></pre><p>Añade tu clave privada en la variable accounts y asegúrate de que tu cuenta tiene suficientes <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://docs.shardeum.org/faucet/claim?_gl=1*yohvu0*_ga*MTQ1NzQ0MTc4NS4xNzA4NjA0ODQ3*_ga_2VJLR99VYW*MTcxMDA3OTU5Ni45LjAuMTcxMDA3OTU5Ni42MC4wLjA.&amp;_ga=2.209736725.1899079138.1710079597-1457441785.1708604847">tokens Shardeum testnet.</a></p><p>v) Ahora, vamos a desplegar nuestros contratos inteligentes en la Shardeum Sphinx Dapp para este ejemplo.</p><pre data-type="codeBlock" text="npx hardhat run scripts/deploy.js --network sphinx
"><code>npx hardhat run scripts<span class="hljs-operator">/</span>deploy.js <span class="hljs-operator">-</span><span class="hljs-operator">-</span>network sphinx
</code></pre><p>El script desplegará el contrato inteligente en la Testnet de Shardeum y mostrará la dirección del contrato inteligente desplegado. Necesitarás esta dirección más adelante, así que guárdala.</p><h1 id="h-3-crear-una-aplicacion-front-end" class="text-4xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0"><strong>3. Crear una Aplicación Front-End</strong></h1><p>Ahora, vamos a crear una aplicación front-end básica para interactuar con nuestro contrato inteligente desplegado.</p><p>Vamos a empezar con la inicialización de un react-aplicación en la misma carpeta. Después de configurar la aplicación react, instala también todos los paquetes front-end necesarios.</p><pre data-type="codeBlock" text="npx create-react-app .
npm install @emotion/react @emotion/styled @mui/material axios
"><code>npx create<span class="hljs-operator">-</span>react<span class="hljs-operator">-</span>app .
npm install @emotion<span class="hljs-operator">/</span>react @emotion<span class="hljs-operator">/</span>styled @mui<span class="hljs-operator">/</span>material axios
</code></pre><p>Haremos todos nuestros cambios de código front-end en la carpeta src. Localiza el archivo <em>NFTMinter.json</em> de tu carpeta de <em>artifactos</em> y llévalo a la carpeta src.</p><p>Aquí están los cuatro nuevos archivos javascript que necesitas crear para tener las funcionalidades necesarias:</p><ul><li><p><em>connectWallet.js</em>: Este archivo nos permitirá conectar nuestro front-end con el contrato inteligente y nos conecta a metamask. Añade la dirección de tu contrato en la variable designada.</p></li></ul><pre data-type="codeBlock" text="import { ethers } from &quot;ethers&quot;;
import NFTMinter from &quot;./NftMinter.json&quot;;
export async function connectWallet() {
  await window.ethereum.request({ method: &quot;eth_requestAccounts&quot; });
  const provider = new ethers.providers.Web3Provider(window.ethereum);
  const signer = provider.getSigner();
  // Insert deployed contract address here
  const contract = new ethers.Contract(``, NFTMinter.abi, signer);
  
  return { signer, contract };
  }
  
  export async function connectMetaMask (){
    const { signer } = await connectWallet();
    const address = await signer.getAddress();
    const balance = await signer.getBalance();
    const formattedBalance = ethers.utils.formatEther(balance);
    return {address, formattedBalance}
  };
"><code><span class="hljs-keyword">import</span> { <span class="hljs-title">ethers</span> } <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"ethers"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-title">NFTMinter</span> <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"./NftMinter.json"</span>;
export async <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">connectWallet</span>(<span class="hljs-params"></span>) </span>{
  await window.ethereum.request({ method: <span class="hljs-string">"eth_requestAccounts"</span> });
  const provider <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> ethers.providers.Web3Provider(window.ethereum);
  const signer <span class="hljs-operator">=</span> provider.getSigner();
  <span class="hljs-comment">// Insert deployed contract address here</span>
  const <span class="hljs-class"><span class="hljs-keyword">contract</span> = <span class="hljs-title"><span class="hljs-keyword">new</span></span> <span class="hljs-title">ethers</span>.<span class="hljs-title">Contract</span>(<span class="hljs-params">``, NFTMinter.<span class="hljs-built_in">abi</span>, signer</span>);
  
  <span class="hljs-title"><span class="hljs-keyword">return</span></span> </span>{ signer, <span class="hljs-class"><span class="hljs-keyword">contract</span> };
  }
  
  <span class="hljs-title">export</span> <span class="hljs-title">async</span> <span class="hljs-title"><span class="hljs-keyword">function</span></span> <span class="hljs-title">connectMetaMask</span> (<span class="hljs-params"></span>)</span>{
    const { signer } <span class="hljs-operator">=</span> await connectWallet();
    const <span class="hljs-keyword">address</span> <span class="hljs-operator">=</span> await signer.getAddress();
    const balance <span class="hljs-operator">=</span> await signer.getBalance();
    const formattedBalance <span class="hljs-operator">=</span> ethers.utils.formatEther(balance);
    <span class="hljs-keyword">return</span> {<span class="hljs-keyword">address</span>, formattedBalance}
  };
</code></pre><ul><li><p><em>ipfsUploader.js</em>: Este archivo contiene todo el código necesario para subir nuestros archivos a ipfs usando Pinata. Crea una cuenta en <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.pinata.cloud/">Pinata </a>y genera un nuevo enlace API.</p></li></ul><pre data-type="codeBlock" text="import axios from &apos;axios&apos;;
const pinataApiKey = ``; // Insert pinata Api Key
const pinataApiSecret = `` ; // Insert pinata Api secret
const pinataApiUrl = &apos;https://api.pinata.cloud/pinning/pinFileToIPFS&apos;;
const pinataHeaders = {
  headers: {
    &apos;Content-Type&apos;: &apos;multipart/form-data&apos;,
    pinata_api_key: pinataApiKey,
    pinata_secret_api_key: pinataApiSecret,
  },
};
export async function uploadToIPFS(file) {
  const formData = new FormData();
  formData.append(&apos;file&apos;, file);
  try {
    const response = await axios.post(pinataApiUrl, formData, pinataHeaders);
    const ipfsHash = response.data.IpfsHash;
    return `https://gateway.pinata.cloud/ipfs/${ipfsHash}`;
  } catch (error) {
    console.error(&apos;Error uploading file to Pinata:&apos;, error);
    throw error;
  }
}
"><code><span class="hljs-keyword">import</span> <span class="hljs-title">axios</span> <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">'axios'</span>;
const pinataApiKey <span class="hljs-operator">=</span> ``; <span class="hljs-comment">// Insert pinata Api Key</span>
const pinataApiSecret <span class="hljs-operator">=</span> `` ; <span class="hljs-comment">// Insert pinata Api secret</span>
const pinataApiUrl <span class="hljs-operator">=</span> <span class="hljs-string">'https://api.pinata.cloud/pinning/pinFileToIPFS'</span>;
const pinataHeaders <span class="hljs-operator">=</span> {
  headers: {
    <span class="hljs-string">'Content-Type'</span>: <span class="hljs-string">'multipart/form-data'</span>,
    pinata_api_key: pinataApiKey,
    pinata_secret_api_key: pinataApiSecret,
  },
};
export async <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">uploadToIPFS</span>(<span class="hljs-params">file</span>) </span>{
  const formData <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> FormData();
  formData.append(<span class="hljs-string">'file'</span>, file);
  <span class="hljs-keyword">try</span> {
    const response <span class="hljs-operator">=</span> await axios.post(pinataApiUrl, formData, pinataHeaders);
    const ipfsHash <span class="hljs-operator">=</span> response.data.IpfsHash;
    <span class="hljs-keyword">return</span> `https:<span class="hljs-comment">//gateway.pinata.cloud/ipfs/${ipfsHash}`;</span>
  } <span class="hljs-keyword">catch</span> (<span class="hljs-function"><span class="hljs-keyword">error</span>) </span>{
    console.error(<span class="hljs-string">'Error uploading file to Pinata:'</span>, <span class="hljs-function"><span class="hljs-keyword">error</span>)</span>;
    <span class="hljs-keyword">throw</span> <span class="hljs-function"><span class="hljs-keyword">error</span></span>;
  }
}
</code></pre><ul><li><p><em>MintNFT.js</em>: Este archivo contiene los componentes principales de nuestra aplicación de minting y también todo nuestro código front-end.</p></li></ul><pre data-type="codeBlock" text="import React, { useState } from &quot;react&quot;;
import { connectWallet, connectMetaMask } from &quot;./connectWallet&quot;;
import { uploadToIPFS } from &quot;./ipfsUploader&quot;;
import {
  TextField,
  Button,
  Typography,
  Container,
  Box,
  Link,
  Grid,
  Snackbar,
  Alert,
  LinearProgress,
} from &quot;@mui/material&quot;;
function MintNFT() {
  const [name, setName] = useState(&quot;&quot;);
  const [description, setDescription] = useState(&quot;&quot;);
  const [image, setImage] = useState(null);
  const [status, setStatus] = useState(&quot;&quot;);
  const [ipfsLink, setIpfsLink] = useState(&quot;&quot;);
  const [imageStatus, setImageStatus] = useState(&quot;&quot;);
  const [alertOpen, setAlertOpen] = useState(false);
  const [loading, setLoading] = useState(false);
  const [walletAddress, setWalletAddress] = useState(&quot;&quot;);
  const [walletBalance, setWalletBalance] = useState(&quot;&quot;);
  const [imagePreviewUrl, setImagePreviewUrl] = useState(null);
  const [transactionHistory, setTransactionHistory] = useState([]);
  const handleConnectMetaMask = async () =&gt; {
    const { address, formattedBalance } = await connectMetaMask();
    setWalletAddress(address);
    setWalletBalance(formattedBalance);
  };
  const handleImageChange = (e) =&gt; {
    setImage(e.target.files[0]);
    setImageStatus(&quot;Image selected for upload&quot;);
    setImagePreviewUrl(URL.createObjectURL(e.target.files[0]));
  };
  const mint = async () =&gt; {
    setStatus(&quot;Uploading to IPFS...&quot;);
    const imageURI = await uploadToIPFS(image);
    setIpfsLink(imageURI);
    setStatus(&quot;Minting NFT...&quot;);
    setLoading(true);
    const { signer, contract } = await connectWallet();
    const tokenURI = `data:application/json;base64,${btoa(
      JSON.stringify({
        name,
        description,
        image: imageURI,
      })
    )}`;
    const transaction = await contract.mintNFT(signer.getAddress(), tokenURI);
    await transaction.wait();
    setTransactionHistory((prevHistory) =&gt; [
      ...prevHistory,
      transaction.hash,
    ]);
    setStatus(&quot;NFT minted!&quot;);
    setAlertOpen(true);
    setLoading(false);
  };
  return (
    
    &lt;Container maxWidth=&quot;lg&quot;&gt;
      &lt;Box sx={{ mt: 4, mb: 2 }}&gt;
        &lt;Typography variant=&quot;h4&quot; align=&quot;center&quot; gutterBottom&gt;
          Shardeum NFT Minter
        &lt;/Typography&gt;
      &lt;/Box&gt;
      &lt;Grid container spacing={2}&gt;
        &lt;Grid item xs={12} md={6}&gt;
        &lt;Box mt={2}&gt;
              &lt;Button
                fullWidth
                variant=&quot;contained&quot;
                color=&quot;primary&quot;
                onClick={handleConnectMetaMask}
                size=&quot;small&quot;
                disabled={walletAddress} 
              &gt;
                {walletAddress ? &quot;Wallet Connected&quot; : &quot;Connect Wallet to Shardeum Sphinx Dapp 1.X&quot;}
              &lt;/Button&gt;
            &lt;/Box&gt;
          {walletAddress &amp;&amp; (
            &lt;Box mt={2}&gt;
              &lt;Typography align=&quot;center&quot;&gt;
                Wallet Address: {walletAddress}
              &lt;/Typography&gt;
              &lt;Typography align=&quot;center&quot;&gt;
                Wallet Balance: {walletBalance} SHM
              &lt;/Typography&gt;
            &lt;/Box&gt;
          )}
          &lt;TextField
            fullWidth
            label=&quot;NFT Name&quot;
            variant=&quot;outlined&quot;
            margin=&quot;normal&quot;
            onChange={(e) =&gt; setName(e.target.value)}
          /&gt;
          &lt;TextField
            fullWidth
            label=&quot;NFT Description&quot;
            variant=&quot;outlined&quot;
            margin=&quot;normal&quot;
            onChange={(e) =&gt; setDescription(e.target.value)}
          /&gt;
          &lt;input
            type=&quot;file&quot;
            style={{ display: &quot;none&quot; }}
            id=&quot;image-upload&quot;
            onChange={handleImageChange}
          /&gt;
          &lt;p&gt;&lt;/p&gt;
          &lt;label      htmlFor=&quot;image-upload&quot;&gt;
        &lt;Button variant=&quot;contained&quot; color=&quot;primary&quot; component=&quot;span&quot;&gt;
          Upload Image
        &lt;/Button&gt;
      &lt;/label&gt;
      {imageStatus &amp;&amp; (
        &lt;Typography variant=&quot;caption&quot; display=&quot;block&quot; gutterBottom&gt;
          {imageStatus}
        &lt;/Typography&gt;
      )}
      &lt;Box mt={2}&gt;
        &lt;Button
          fullWidth
          variant=&quot;contained&quot;
          color=&quot;secondary&quot;
          onClick={mint}
        &gt;
          Mint NFT
        &lt;/Button&gt;
      &lt;/Box&gt;
      {loading &amp;&amp; &lt;LinearProgress /&gt;}
      
      &lt;Snackbar
        open={alertOpen}
        autoHideDuration={6000}
        onClose={() =&gt; setAlertOpen(false)}
        anchorOrigin={{ vertical: &quot;top&quot;, horizontal: &quot;right&quot; }}
      &gt;
        &lt;Alert
          onClose={() =&gt; setAlertOpen(false)}
          severity=&quot;success&quot;
          variant=&quot;filled&quot;
          sx={{ width: &quot;100%&quot; }}
        &gt;
          NFT minted successfully!
        &lt;/Alert&gt;
      &lt;/Snackbar&gt;
    &lt;/Grid&gt;
    &lt;Grid item xs={12} md={6}&gt;
  &lt;Box
    mt={2}
    sx={{
      border: &quot;1px dashed #999&quot;,
      borderRadius: &quot;12px&quot;,
      padding: &quot;16px&quot;,
      display: &quot;flex&quot;,
      justifyContent: &quot;center&quot;,
      alignItems: &quot;center&quot;,
      minHeight: &quot;300px&quot;,
      background: imagePreviewUrl
        ? &quot;none&quot;
        : &quot;linear-gradient(45deg, rgba(255,255,255,1) 0%, rgba(255,255,255,0) 100%)&quot;,
    }}
  &gt;
    {imagePreviewUrl ? (
      &lt;img
        src={imagePreviewUrl}
        alt=&quot;Uploaded preview&quot;
        style={{
          width: &quot;100%&quot;,
          maxHeight: &quot;300px&quot;,
          objectFit: &quot;contain&quot;,
          borderRadius: &quot;12px&quot;,
        }}
      /&gt;
    ) : (
      &lt;Typography variant=&quot;caption&quot; color=&quot;text.secondary&quot;&gt;
        Preview image will be displayed here
      &lt;/Typography&gt;
    )}
  &lt;/Box&gt;
&lt;/Grid&gt;
    &lt;Box mt={2}&gt;
        &lt;Typography align=&quot;center&quot; color=&quot;textSecondary&quot;&gt;
          {status}
        &lt;/Typography&gt;
        {ipfsLink &amp;&amp; (
      &lt;Typography align=&quot;left&quot;&gt;
    IPFS Link:{&quot; &quot;}
    &lt;Link href={ipfsLink} target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;
      {ipfsLink}
    &lt;/Link&gt;
      &lt;/Typography&gt;
)}
      &lt;/Box&gt;
  &lt;/Grid&gt;
  &lt;Box mt={4}&gt;
        &lt;Typography variant=&quot;h7&quot; align=&quot;center&quot;&gt;
          Transaction History:
        &lt;/Typography&gt;
        {transactionHistory.length &gt; 0 ? (
          transactionHistory.map((hash, index) =&gt; (
            &lt;Box key={index} mt={1} textAlign=&quot;left&quot;&gt;
              &lt;Link
                href={`https://explorer-dapps.shardeum.org/transaction/${hash}`}
                target=&quot;_blank&quot;
                rel=&quot;noopener noreferrer&quot;
              &gt;
                {`Transaction ${index + 1}: ${hash}`}
              &lt;/Link&gt;
            &lt;/Box&gt;
          ))
        ) : (
          &lt;Typography align=&quot;center&quot; mt={1}&gt;
            No transactions yet.
          &lt;/Typography&gt;
        )}import React, { useState } from &quot;react&quot;;
import { connectWallet, connectMetaMask } from &quot;./connectWallet&quot;;
import { uploadToIPFS } from &quot;./ipfsUploader&quot;;
import {TextField,Button,Typography,Container,Box,Link,Grid,Snackbar,Alert,LinearProgress,} from &quot;@mui/material&quot;;
function MintNFT() {
  const [name, setName] = useState(&quot;&quot;);
  const [description, setDescription] = useState(&quot;&quot;);
  const [image, setImage] = useState(null);
  const [status, setStatus] = useState(&quot;&quot;);
  const [ipfsLink, setIpfsLink] = useState(&quot;&quot;);
  const [imageStatus, setImageStatus] = useState(&quot;&quot;);
  const [alertOpen, setAlertOpen] = useState(false);
  const [loading, setLoading] = useState(false);
  const [walletAddress, setWalletAddress] = useState(&quot;&quot;);
  const [walletBalance, setWalletBalance] = useState(&quot;&quot;);
  const [imagePreviewUrl, setImagePreviewUrl] = useState(null);
  const [transactionHistory, setTransactionHistory] = useState([]);
  const handleConnectMetaMask = async () =&gt; {
    const { address, formattedBalance } = await connectMetaMask();
    setWalletAddress(address);
    setWalletBalance(formattedBalance);
  };
  const handleImageChange = (e) =&gt; {
    setImage(e.target.files[0]);
    setImageStatus(&quot;Image selected for upload&quot;);
    setImagePreviewUrl(URL.createObjectURL(e.target.files[0]));
  };
  const mint = async () =&gt; {
    setStatus(&quot;Uploading to IPFS...&quot;);
    const imageURI = await uploadToIPFS(image);
    setIpfsLink(imageURI);
    setStatus(&quot;Minting NFT...&quot;);
    setLoading(true);
    const { signer, contract } = await connectWallet();
    const tokenURI = `data:application/json;base64,${btoa(
      JSON.stringify({
        name,
        description,
        image: imageURI,
      })
    )}`;
    const transaction = await contract.mintNFT(signer.getAddress(), tokenURI);
    await transaction.wait();
    setTransactionHistory((prevHistory) =&gt; [
      ...prevHistory,
      transaction.hash,
    ]);
    setStatus(&quot;NFT minted!&quot;);
    setAlertOpen(true);
    setLoading(false);
  };
  return (
    
    &lt;Container maxWidth=&quot;lg&quot;&gt;
      &lt;Box sx={{ mt: 4, mb: 2 }}&gt;
        &lt;Typography variant=&quot;h4&quot; align=&quot;center&quot; gutterBottom&gt;
          Shardeum NFT Minter
        &lt;/Typography&gt;
      &lt;/Box&gt;
      &lt;Grid container spacing={2}&gt;
        &lt;Grid item xs={12} md={6}&gt;
        &lt;Box mt={2}&gt;
              &lt;Button
                fullWidth
                variant=&quot;contained&quot;
                color=&quot;primary&quot;
                onClick={handleConnectMetaMask}
                size=&quot;small&quot;
                disabled={walletAddress} 
              &gt;
                {walletAddress ? &quot;Wallet Connected&quot; : &quot;Connect Wallet to Shardeum Sphinx Dapp 1.X&quot;}
              &lt;/Button&gt;
            &lt;/Box&gt;
          {walletAddress &amp;&amp; (
            &lt;Box mt={2}&gt;
              &lt;Typography align=&quot;center&quot;&gt;
                Wallet Address: {walletAddress}
              &lt;/Typography&gt;
              &lt;Typography align=&quot;center&quot;&gt;
                Wallet Balance: {walletBalance} SHM
              &lt;/Typography&gt;
            &lt;/Box&gt;
          )}
          &lt;TextField
            fullWidth
            label=&quot;NFT Name&quot;
            variant=&quot;outlined&quot;
            margin=&quot;normal&quot;
            onChange={(e) =&gt; setName(e.target.value)}
          /&gt;
          &lt;TextField
            fullWidth
            label=&quot;NFT Description&quot;
            variant=&quot;outlined&quot;
            margin=&quot;normal&quot;
            onChange={(e) =&gt; setDescription(e.target.value)}
          /&gt;
          &lt;input
            type=&quot;file&quot;
            style={{ display: &quot;none&quot; }}
            id=&quot;image-upload&quot;
            onChange={handleImageChange}
          /&gt;
          &lt;p&gt;&lt;/p&gt;
          &lt;label      htmlFor=&quot;image-upload&quot;&gt;
        &lt;Button variant=&quot;contained&quot; color=&quot;primary&quot; component=&quot;span&quot;&gt;
          Upload Image
        &lt;/Button&gt;
      &lt;/label&gt;
      {imageStatus &amp;&amp; (
        &lt;Typography variant=&quot;caption&quot; display=&quot;block&quot; gutterBottom&gt;
          {imageStatus}
        &lt;/Typography&gt;
      )}
      &lt;Box mt={2}&gt;
        &lt;Button
          fullWidth
          variant=&quot;contained&quot;
          color=&quot;secondary&quot;
          onClick={mint}
        &gt;
          Mint NFT
        &lt;/Button&gt;
      &lt;/Box&gt;
      {loading &amp;&amp; &lt;LinearProgress /&gt;}
      
      &lt;Snackbar
        open={alertOpen}
        autoHideDuration={6000}
        onClose={() =&gt; setAlertOpen(false)}
        anchorOrigin={{ vertical: &quot;top&quot;, horizontal: &quot;right&quot; }}
      &gt;
        &lt;Alert
          onClose={() =&gt; setAlertOpen(false)}
          severity=&quot;success&quot;
          variant=&quot;filled&quot;
          sx={{ width: &quot;100%&quot; }}
        &gt;
          NFT minted successfully!
        &lt;/Alert&gt;
      &lt;/Snackbar&gt;
    &lt;/Grid&gt;
    &lt;Grid item xs={12} md={6}&gt;
  &lt;Box
    mt={2}
    sx={{
      border: &quot;1px dashed #999&quot;,
      borderRadius: &quot;12px&quot;,
      padding: &quot;16px&quot;,
      display: &quot;flex&quot;,
      justifyContent: &quot;center&quot;,
      alignItems: &quot;center&quot;,
      minHeight: &quot;300px&quot;,
      background: imagePreviewUrl
        ? &quot;none&quot;
        : &quot;linear-gradient(45deg, rgba(255,255,255,1) 0%, rgba(255,255,255,0) 100%)&quot;,
    }}
  &gt;
    {imagePreviewUrl ? (
      &lt;img
        src={imagePreviewUrl}
        alt=&quot;Uploaded preview&quot;
        style={{
          width: &quot;100%&quot;,
          maxHeight: &quot;300px&quot;,
          objectFit: &quot;contain&quot;,
          borderRadius: &quot;12px&quot;,
        }}
      /&gt;
    ) : (
      &lt;Typography variant=&quot;caption&quot; color=&quot;text.secondary&quot;&gt;
        Preview image will be displayed here
      &lt;/Typography&gt;
    )}
  &lt;/Box&gt;
&lt;/Grid&gt;
    &lt;Box mt={2}&gt;
        &lt;Typography align=&quot;center&quot; color=&quot;textSecondary&quot;&gt;
          {status}
        &lt;/Typography&gt;
        {ipfsLink &amp;&amp; (
      &lt;Typography align=&quot;left&quot;&gt;
    IPFS Link:{&quot; &quot;}
    &lt;Link href={ipfsLink} target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;
      {ipfsLink}
    &lt;/Link&gt;
      &lt;/Typography&gt;
)}
      &lt;/Box&gt;
  &lt;/Grid&gt;
  &lt;Box mt={4}&gt;
        &lt;Typography variant=&quot;h7&quot; align=&quot;center&quot;&gt;
          Transaction History:
        &lt;/Typography&gt;
        {transactionHistory.length &gt; 0 ? (
          transactionHistory.map((hash, index) =&gt; (
            &lt;Box key={index} mt={1} textAlign=&quot;left&quot;&gt;
              &lt;Link
                href={`https://explorer-dapps.shardeum.org/transaction/${hash}`}
                target=&quot;_blank&quot;
                rel=&quot;noopener noreferrer&quot;
              &gt;
                {`Transaction ${index + 1}: ${hash}`}
              &lt;/Link&gt;
            &lt;/Box&gt;
          ))
        ) : (
          &lt;Typography align=&quot;center&quot; mt={1}&gt;
            No transactions yet.
          &lt;/Typography&gt;
        )}
      &lt;/Box&gt;
&lt;/Container&gt;
);
}
export default MintNFT;
"><code><span class="hljs-keyword">import</span> <span class="hljs-title">React</span>, { <span class="hljs-title">useState</span> } <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> { <span class="hljs-title">connectWallet</span>, <span class="hljs-title">connectMetaMask</span> } <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"./connectWallet"</span>;
<span class="hljs-keyword">import</span> { <span class="hljs-title">uploadToIPFS</span> } <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"./ipfsUploader"</span>;
<span class="hljs-keyword">import</span> {
  <span class="hljs-title">TextField</span>,
  <span class="hljs-title">Button</span>,
  <span class="hljs-title">Typography</span>,
  <span class="hljs-title">Container</span>,
  <span class="hljs-title">Box</span>,
  <span class="hljs-title">Link</span>,
  <span class="hljs-title">Grid</span>,
  <span class="hljs-title">Snackbar</span>,
  <span class="hljs-title">Alert</span>,
  <span class="hljs-title">LinearProgress</span>,
} <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"@mui/material"</span>;
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">MintNFT</span>(<span class="hljs-params"></span>) </span>{
  const [name, setName] <span class="hljs-operator">=</span> useState(<span class="hljs-string">""</span>);
  const [description, setDescription] <span class="hljs-operator">=</span> useState(<span class="hljs-string">""</span>);
  const [image, setImage] <span class="hljs-operator">=</span> useState(null);
  const [status, setStatus] <span class="hljs-operator">=</span> useState(<span class="hljs-string">""</span>);
  const [ipfsLink, setIpfsLink] <span class="hljs-operator">=</span> useState(<span class="hljs-string">""</span>);
  const [imageStatus, setImageStatus] <span class="hljs-operator">=</span> useState(<span class="hljs-string">""</span>);
  const [alertOpen, setAlertOpen] <span class="hljs-operator">=</span> useState(<span class="hljs-literal">false</span>);
  const [loading, setLoading] <span class="hljs-operator">=</span> useState(<span class="hljs-literal">false</span>);
  const [walletAddress, setWalletAddress] <span class="hljs-operator">=</span> useState(<span class="hljs-string">""</span>);
  const [walletBalance, setWalletBalance] <span class="hljs-operator">=</span> useState(<span class="hljs-string">""</span>);
  const [imagePreviewUrl, setImagePreviewUrl] <span class="hljs-operator">=</span> useState(null);
  const [transactionHistory, setTransactionHistory] <span class="hljs-operator">=</span> useState([]);
  const handleConnectMetaMask <span class="hljs-operator">=</span> async () <span class="hljs-operator">=</span><span class="hljs-operator">></span> {
    const { <span class="hljs-keyword">address</span>, formattedBalance } <span class="hljs-operator">=</span> await connectMetaMask();
    setWalletAddress(<span class="hljs-keyword">address</span>);
    setWalletBalance(formattedBalance);
  };
  const handleImageChange <span class="hljs-operator">=</span> (e) <span class="hljs-operator">=</span><span class="hljs-operator">></span> {
    setImage(e.target.files[<span class="hljs-number">0</span>]);
    setImageStatus(<span class="hljs-string">"Image selected for upload"</span>);
    setImagePreviewUrl(URL.createObjectURL(e.target.files[<span class="hljs-number">0</span>]));
  };
  const mint <span class="hljs-operator">=</span> async () <span class="hljs-operator">=</span><span class="hljs-operator">></span> {
    setStatus(<span class="hljs-string">"Uploading to IPFS..."</span>);
    const imageURI <span class="hljs-operator">=</span> await uploadToIPFS(image);
    setIpfsLink(imageURI);
    setStatus(<span class="hljs-string">"Minting NFT..."</span>);
    setLoading(<span class="hljs-literal">true</span>);
    const { signer, <span class="hljs-class"><span class="hljs-keyword">contract</span> } = <span class="hljs-title">await</span> <span class="hljs-title">connectWallet</span>(<span class="hljs-params"></span>);
    <span class="hljs-title">const</span> <span class="hljs-title">tokenURI</span> = `<span class="hljs-title">data</span>:<span class="hljs-title">application</span>/<span class="hljs-title">json</span>;<span class="hljs-title">base64</span>,<span class="hljs-title">$</span></span>{btoa(
      JSON.stringify({
        name,
        description,
        image: imageURI,
      })
    )}`;
    const transaction <span class="hljs-operator">=</span> await <span class="hljs-keyword">contract</span>.mintNFT(signer.getAddress(), tokenURI);
    await transaction.wait();
    setTransactionHistory((prevHistory) <span class="hljs-operator">=</span><span class="hljs-operator">></span> [
      ...prevHistory,
      transaction.hash,
    ]);
    setStatus(<span class="hljs-string">"NFT minted!"</span>);
    setAlertOpen(<span class="hljs-literal">true</span>);
    setLoading(<span class="hljs-literal">false</span>);
  };
  <span class="hljs-keyword">return</span> (
    
    <span class="hljs-operator">&#x3C;</span>Container maxWidth<span class="hljs-operator">=</span><span class="hljs-string">"lg"</span><span class="hljs-operator">></span>
      <span class="hljs-operator">&#x3C;</span>Box sx<span class="hljs-operator">=</span>{{ mt: <span class="hljs-number">4</span>, mb: <span class="hljs-number">2</span> }}<span class="hljs-operator">></span>
        <span class="hljs-operator">&#x3C;</span>Typography variant<span class="hljs-operator">=</span><span class="hljs-string">"h4"</span> align<span class="hljs-operator">=</span><span class="hljs-string">"center"</span> gutterBottom<span class="hljs-operator">></span>
          Shardeum NFT Minter
        <span class="hljs-operator">&#x3C;</span><span class="hljs-operator">/</span>Typography<span class="hljs-operator">></span>
      <span class="hljs-operator">&#x3C;</span><span class="hljs-operator">/</span>Box<span class="hljs-operator">></span>
      <span class="hljs-operator">&#x3C;</span>Grid container spacing<span class="hljs-operator">=</span>{<span class="hljs-number">2</span>}<span class="hljs-operator">></span>
        <span class="hljs-operator">&#x3C;</span>Grid item xs<span class="hljs-operator">=</span>{<span class="hljs-number">12</span>} md<span class="hljs-operator">=</span>{<span class="hljs-number">6</span>}<span class="hljs-operator">></span>
        <span class="hljs-operator">&#x3C;</span>Box mt<span class="hljs-operator">=</span>{<span class="hljs-number">2</span>}<span class="hljs-operator">></span>
              <span class="hljs-operator">&#x3C;</span>Button
                fullWidth
                variant<span class="hljs-operator">=</span><span class="hljs-string">"contained"</span>
                color<span class="hljs-operator">=</span><span class="hljs-string">"primary"</span>
                onClick<span class="hljs-operator">=</span>{handleConnectMetaMask}
                size<span class="hljs-operator">=</span><span class="hljs-string">"small"</span>
                disabled<span class="hljs-operator">=</span>{walletAddress} 
              <span class="hljs-operator">></span>
                {walletAddress ? <span class="hljs-string">"Wallet Connected"</span> : <span class="hljs-string">"Connect Wallet to Shardeum Sphinx Dapp 1.X"</span>}
              <span class="hljs-operator">&#x3C;</span><span class="hljs-operator">/</span>Button<span class="hljs-operator">></span>
            <span class="hljs-operator">&#x3C;</span><span class="hljs-operator">/</span>Box<span class="hljs-operator">></span>
          {walletAddress <span class="hljs-operator">&#x26;</span><span class="hljs-operator">&#x26;</span> (
            <span class="hljs-operator">&#x3C;</span>Box mt<span class="hljs-operator">=</span>{<span class="hljs-number">2</span>}<span class="hljs-operator">></span>
              <span class="hljs-operator">&#x3C;</span>Typography align<span class="hljs-operator">=</span><span class="hljs-string">"center"</span><span class="hljs-operator">></span>
                Wallet Address: {walletAddress}
              <span class="hljs-operator">&#x3C;</span><span class="hljs-operator">/</span>Typography<span class="hljs-operator">></span>
              <span class="hljs-operator">&#x3C;</span>Typography align<span class="hljs-operator">=</span><span class="hljs-string">"center"</span><span class="hljs-operator">></span>
                Wallet Balance: {walletBalance} SHM
              <span class="hljs-operator">&#x3C;</span><span class="hljs-operator">/</span>Typography<span class="hljs-operator">></span>
            <span class="hljs-operator">&#x3C;</span><span class="hljs-operator">/</span>Box<span class="hljs-operator">></span>
          )}
          <span class="hljs-operator">&#x3C;</span>TextField
            fullWidth
            label<span class="hljs-operator">=</span><span class="hljs-string">"NFT Name"</span>
            variant<span class="hljs-operator">=</span><span class="hljs-string">"outlined"</span>
            margin<span class="hljs-operator">=</span><span class="hljs-string">"normal"</span>
            onChange<span class="hljs-operator">=</span>{(e) <span class="hljs-operator">=</span><span class="hljs-operator">></span> setName(e.target.<span class="hljs-built_in">value</span>)}
          <span class="hljs-operator">/</span><span class="hljs-operator">></span>
          <span class="hljs-operator">&#x3C;</span>TextField
            fullWidth
            label<span class="hljs-operator">=</span><span class="hljs-string">"NFT Description"</span>
            variant<span class="hljs-operator">=</span><span class="hljs-string">"outlined"</span>
            margin<span class="hljs-operator">=</span><span class="hljs-string">"normal"</span>
            onChange<span class="hljs-operator">=</span>{(e) <span class="hljs-operator">=</span><span class="hljs-operator">></span> setDescription(e.target.<span class="hljs-built_in">value</span>)}
          <span class="hljs-operator">/</span><span class="hljs-operator">></span>
          <span class="hljs-operator">&#x3C;</span>input
            <span class="hljs-keyword">type</span><span class="hljs-operator">=</span><span class="hljs-string">"file"</span>
            style<span class="hljs-operator">=</span>{{ display: <span class="hljs-string">"none"</span> }}
            id<span class="hljs-operator">=</span><span class="hljs-string">"image-upload"</span>
            onChange<span class="hljs-operator">=</span>{handleImageChange}
          <span class="hljs-operator">/</span><span class="hljs-operator">></span>
          <span class="hljs-operator">&#x3C;</span>p<span class="hljs-operator">></span><span class="hljs-operator">&#x3C;</span><span class="hljs-operator">/</span>p<span class="hljs-operator">></span>
          <span class="hljs-operator">&#x3C;</span>label      htmlFor<span class="hljs-operator">=</span><span class="hljs-string">"image-upload"</span><span class="hljs-operator">></span>
        <span class="hljs-operator">&#x3C;</span>Button variant<span class="hljs-operator">=</span><span class="hljs-string">"contained"</span> color<span class="hljs-operator">=</span><span class="hljs-string">"primary"</span> component<span class="hljs-operator">=</span><span class="hljs-string">"span"</span><span class="hljs-operator">></span>
          Upload Image
        <span class="hljs-operator">&#x3C;</span><span class="hljs-operator">/</span>Button<span class="hljs-operator">></span>
      <span class="hljs-operator">&#x3C;</span><span class="hljs-operator">/</span>label<span class="hljs-operator">></span>
      {imageStatus <span class="hljs-operator">&#x26;</span><span class="hljs-operator">&#x26;</span> (
        <span class="hljs-operator">&#x3C;</span>Typography variant<span class="hljs-operator">=</span><span class="hljs-string">"caption"</span> display<span class="hljs-operator">=</span><span class="hljs-string">"block"</span> gutterBottom<span class="hljs-operator">></span>
          {imageStatus}
        <span class="hljs-operator">&#x3C;</span><span class="hljs-operator">/</span>Typography<span class="hljs-operator">></span>
      )}
      <span class="hljs-operator">&#x3C;</span>Box mt<span class="hljs-operator">=</span>{<span class="hljs-number">2</span>}<span class="hljs-operator">></span>
        <span class="hljs-operator">&#x3C;</span>Button
          fullWidth
          variant<span class="hljs-operator">=</span><span class="hljs-string">"contained"</span>
          color<span class="hljs-operator">=</span><span class="hljs-string">"secondary"</span>
          onClick<span class="hljs-operator">=</span>{mint}
        <span class="hljs-operator">></span>
          Mint NFT
        <span class="hljs-operator">&#x3C;</span><span class="hljs-operator">/</span>Button<span class="hljs-operator">></span>
      <span class="hljs-operator">&#x3C;</span><span class="hljs-operator">/</span>Box<span class="hljs-operator">></span>
      {loading <span class="hljs-operator">&#x26;</span><span class="hljs-operator">&#x26;</span> <span class="hljs-operator">&#x3C;</span>LinearProgress <span class="hljs-operator">/</span><span class="hljs-operator">></span>}
      
      <span class="hljs-operator">&#x3C;</span>Snackbar
        open<span class="hljs-operator">=</span>{alertOpen}
        autoHideDuration<span class="hljs-operator">=</span>{<span class="hljs-number">6000</span>}
        onClose<span class="hljs-operator">=</span>{() <span class="hljs-operator">=</span><span class="hljs-operator">></span> setAlertOpen(<span class="hljs-literal">false</span>)}
        anchorOrigin<span class="hljs-operator">=</span>{{ vertical: <span class="hljs-string">"top"</span>, horizontal: <span class="hljs-string">"right"</span> }}
      <span class="hljs-operator">></span>
        <span class="hljs-operator">&#x3C;</span>Alert
          onClose<span class="hljs-operator">=</span>{() <span class="hljs-operator">=</span><span class="hljs-operator">></span> setAlertOpen(<span class="hljs-literal">false</span>)}
          severity<span class="hljs-operator">=</span><span class="hljs-string">"success"</span>
          variant<span class="hljs-operator">=</span><span class="hljs-string">"filled"</span>
          sx<span class="hljs-operator">=</span>{{ width: <span class="hljs-string">"100%"</span> }}
        <span class="hljs-operator">></span>
          NFT minted successfully<span class="hljs-operator">!</span>
        <span class="hljs-operator">&#x3C;</span><span class="hljs-operator">/</span>Alert<span class="hljs-operator">></span>
      <span class="hljs-operator">&#x3C;</span><span class="hljs-operator">/</span>Snackbar<span class="hljs-operator">></span>
    <span class="hljs-operator">&#x3C;</span><span class="hljs-operator">/</span>Grid<span class="hljs-operator">></span>
    <span class="hljs-operator">&#x3C;</span>Grid item xs<span class="hljs-operator">=</span>{<span class="hljs-number">12</span>} md<span class="hljs-operator">=</span>{<span class="hljs-number">6</span>}<span class="hljs-operator">></span>
  <span class="hljs-operator">&#x3C;</span>Box
    mt<span class="hljs-operator">=</span>{<span class="hljs-number">2</span>}
    sx<span class="hljs-operator">=</span>{{
      border: <span class="hljs-string">"1px dashed #999"</span>,
      borderRadius: <span class="hljs-string">"12px"</span>,
      padding: <span class="hljs-string">"16px"</span>,
      display: <span class="hljs-string">"flex"</span>,
      justifyContent: <span class="hljs-string">"center"</span>,
      alignItems: <span class="hljs-string">"center"</span>,
      minHeight: <span class="hljs-string">"300px"</span>,
      background: imagePreviewUrl
        ? <span class="hljs-string">"none"</span>
        : <span class="hljs-string">"linear-gradient(45deg, rgba(255,255,255,1) 0%, rgba(255,255,255,0) 100%)"</span>,
    }}
  <span class="hljs-operator">></span>
    {imagePreviewUrl ? (
      <span class="hljs-operator">&#x3C;</span>img
        src<span class="hljs-operator">=</span>{imagePreviewUrl}
        alt<span class="hljs-operator">=</span><span class="hljs-string">"Uploaded preview"</span>
        style<span class="hljs-operator">=</span>{{
          width: <span class="hljs-string">"100%"</span>,
          maxHeight: <span class="hljs-string">"300px"</span>,
          objectFit: <span class="hljs-string">"contain"</span>,
          borderRadius: <span class="hljs-string">"12px"</span>,
        }}
      <span class="hljs-operator">/</span><span class="hljs-operator">></span>
    ) : (
      <span class="hljs-operator">&#x3C;</span>Typography variant<span class="hljs-operator">=</span><span class="hljs-string">"caption"</span> color<span class="hljs-operator">=</span><span class="hljs-string">"text.secondary"</span><span class="hljs-operator">></span>
        Preview image will be displayed here
      <span class="hljs-operator">&#x3C;</span><span class="hljs-operator">/</span>Typography<span class="hljs-operator">></span>
    )}
  <span class="hljs-operator">&#x3C;</span><span class="hljs-operator">/</span>Box<span class="hljs-operator">></span>
<span class="hljs-operator">&#x3C;</span><span class="hljs-operator">/</span>Grid<span class="hljs-operator">></span>
    <span class="hljs-operator">&#x3C;</span>Box mt<span class="hljs-operator">=</span>{<span class="hljs-number">2</span>}<span class="hljs-operator">></span>
        <span class="hljs-operator">&#x3C;</span>Typography align<span class="hljs-operator">=</span><span class="hljs-string">"center"</span> color<span class="hljs-operator">=</span><span class="hljs-string">"textSecondary"</span><span class="hljs-operator">></span>
          {status}
        <span class="hljs-operator">&#x3C;</span><span class="hljs-operator">/</span>Typography<span class="hljs-operator">></span>
        {ipfsLink <span class="hljs-operator">&#x26;</span><span class="hljs-operator">&#x26;</span> (
      <span class="hljs-operator">&#x3C;</span>Typography align<span class="hljs-operator">=</span><span class="hljs-string">"left"</span><span class="hljs-operator">></span>
    IPFS Link:{<span class="hljs-string">" "</span>}
    <span class="hljs-operator">&#x3C;</span>Link href<span class="hljs-operator">=</span>{ipfsLink} target<span class="hljs-operator">=</span><span class="hljs-string">"_blank"</span> rel<span class="hljs-operator">=</span><span class="hljs-string">"noopener noreferrer"</span><span class="hljs-operator">></span>
      {ipfsLink}
    <span class="hljs-operator">&#x3C;</span><span class="hljs-operator">/</span>Link<span class="hljs-operator">></span>
      <span class="hljs-operator">&#x3C;</span><span class="hljs-operator">/</span>Typography<span class="hljs-operator">></span>
)}
      <span class="hljs-operator">&#x3C;</span><span class="hljs-operator">/</span>Box<span class="hljs-operator">></span>
  <span class="hljs-operator">&#x3C;</span><span class="hljs-operator">/</span>Grid<span class="hljs-operator">></span>
  <span class="hljs-operator">&#x3C;</span>Box mt<span class="hljs-operator">=</span>{<span class="hljs-number">4</span>}<span class="hljs-operator">></span>
        <span class="hljs-operator">&#x3C;</span>Typography variant<span class="hljs-operator">=</span><span class="hljs-string">"h7"</span> align<span class="hljs-operator">=</span><span class="hljs-string">"center"</span><span class="hljs-operator">></span>
          Transaction History:
        <span class="hljs-operator">&#x3C;</span><span class="hljs-operator">/</span>Typography<span class="hljs-operator">></span>
        {transactionHistory.<span class="hljs-built_in">length</span> <span class="hljs-operator">></span> <span class="hljs-number">0</span> ? (
          transactionHistory.map((hash, index) <span class="hljs-operator">=</span><span class="hljs-operator">></span> (
            <span class="hljs-operator">&#x3C;</span>Box key<span class="hljs-operator">=</span>{index} mt<span class="hljs-operator">=</span>{<span class="hljs-number">1</span>} textAlign<span class="hljs-operator">=</span><span class="hljs-string">"left"</span><span class="hljs-operator">></span>
              <span class="hljs-operator">&#x3C;</span>Link
                href<span class="hljs-operator">=</span>{`https:<span class="hljs-comment">//explorer-dapps.shardeum.org/transaction/${hash}`}</span>
                target<span class="hljs-operator">=</span><span class="hljs-string">"_blank"</span>
                rel<span class="hljs-operator">=</span><span class="hljs-string">"noopener noreferrer"</span>
              <span class="hljs-operator">></span>
                {`Transaction ${index <span class="hljs-operator">+</span> <span class="hljs-number">1</span>}: ${hash}`}
              <span class="hljs-operator">&#x3C;</span><span class="hljs-operator">/</span>Link<span class="hljs-operator">></span>
            <span class="hljs-operator">&#x3C;</span><span class="hljs-operator">/</span>Box<span class="hljs-operator">></span>
          ))
        ) : (
          <span class="hljs-operator">&#x3C;</span>Typography align<span class="hljs-operator">=</span><span class="hljs-string">"center"</span> mt<span class="hljs-operator">=</span>{<span class="hljs-number">1</span>}<span class="hljs-operator">></span>
            No transactions yet.
          &#x3C;<span class="hljs-operator">/</span>Typography<span class="hljs-operator">></span>
        )}<span class="hljs-keyword">import</span> <span class="hljs-title">React</span>, { <span class="hljs-title">useState</span> } <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> { <span class="hljs-title">connectWallet</span>, <span class="hljs-title">connectMetaMask</span> } <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"./connectWallet"</span>;
<span class="hljs-keyword">import</span> { <span class="hljs-title">uploadToIPFS</span> } <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"./ipfsUploader"</span>;
<span class="hljs-keyword">import</span> {<span class="hljs-title">TextField</span>,<span class="hljs-title">Button</span>,<span class="hljs-title">Typography</span>,<span class="hljs-title">Container</span>,<span class="hljs-title">Box</span>,<span class="hljs-title">Link</span>,<span class="hljs-title">Grid</span>,<span class="hljs-title">Snackbar</span>,<span class="hljs-title">Alert</span>,<span class="hljs-title">LinearProgress</span>,} <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"@mui/material"</span>;
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">MintNFT</span>(<span class="hljs-params"></span>) </span>{
  const [name, setName] <span class="hljs-operator">=</span> useState(<span class="hljs-string">""</span>);
  const [description, setDescription] <span class="hljs-operator">=</span> useState(<span class="hljs-string">""</span>);
  const [image, setImage] <span class="hljs-operator">=</span> useState(null);
  const [status, setStatus] <span class="hljs-operator">=</span> useState(<span class="hljs-string">""</span>);
  const [ipfsLink, setIpfsLink] <span class="hljs-operator">=</span> useState(<span class="hljs-string">""</span>);
  const [imageStatus, setImageStatus] <span class="hljs-operator">=</span> useState(<span class="hljs-string">""</span>);
  const [alertOpen, setAlertOpen] <span class="hljs-operator">=</span> useState(<span class="hljs-literal">false</span>);
  const [loading, setLoading] <span class="hljs-operator">=</span> useState(<span class="hljs-literal">false</span>);
  const [walletAddress, setWalletAddress] <span class="hljs-operator">=</span> useState(<span class="hljs-string">""</span>);
  const [walletBalance, setWalletBalance] <span class="hljs-operator">=</span> useState(<span class="hljs-string">""</span>);
  const [imagePreviewUrl, setImagePreviewUrl] <span class="hljs-operator">=</span> useState(null);
  const [transactionHistory, setTransactionHistory] <span class="hljs-operator">=</span> useState([]);
  const handleConnectMetaMask <span class="hljs-operator">=</span> async () <span class="hljs-operator">=</span><span class="hljs-operator">></span> {
    const { <span class="hljs-keyword">address</span>, formattedBalance } <span class="hljs-operator">=</span> await connectMetaMask();
    setWalletAddress(<span class="hljs-keyword">address</span>);
    setWalletBalance(formattedBalance);
  };
  const handleImageChange <span class="hljs-operator">=</span> (e) <span class="hljs-operator">=</span><span class="hljs-operator">></span> {
    setImage(e.target.files[<span class="hljs-number">0</span>]);
    setImageStatus(<span class="hljs-string">"Image selected for upload"</span>);
    setImagePreviewUrl(URL.createObjectURL(e.target.files[<span class="hljs-number">0</span>]));
  };
  const mint <span class="hljs-operator">=</span> async () <span class="hljs-operator">=</span><span class="hljs-operator">></span> {
    setStatus(<span class="hljs-string">"Uploading to IPFS..."</span>);
    const imageURI <span class="hljs-operator">=</span> await uploadToIPFS(image);
    setIpfsLink(imageURI);
    setStatus(<span class="hljs-string">"Minting NFT..."</span>);
    setLoading(<span class="hljs-literal">true</span>);
    const { signer, <span class="hljs-class"><span class="hljs-keyword">contract</span> } = <span class="hljs-title">await</span> <span class="hljs-title">connectWallet</span>(<span class="hljs-params"></span>);
    <span class="hljs-title">const</span> <span class="hljs-title">tokenURI</span> = `<span class="hljs-title">data</span>:<span class="hljs-title">application</span>/<span class="hljs-title">json</span>;<span class="hljs-title">base64</span>,<span class="hljs-title">$</span></span>{btoa(
      JSON.stringify({
        name,
        description,
        image: imageURI,
      })
    )}`;
    const transaction <span class="hljs-operator">=</span> await <span class="hljs-keyword">contract</span>.mintNFT(signer.getAddress(), tokenURI);
    await transaction.wait();
    setTransactionHistory((prevHistory) <span class="hljs-operator">=</span><span class="hljs-operator">></span> [
      ...prevHistory,
      transaction.hash,
    ]);
    setStatus(<span class="hljs-string">"NFT minted!"</span>);
    setAlertOpen(<span class="hljs-literal">true</span>);
    setLoading(<span class="hljs-literal">false</span>);
  };
  <span class="hljs-keyword">return</span> (
    
    <span class="hljs-operator">&#x3C;</span>Container maxWidth<span class="hljs-operator">=</span><span class="hljs-string">"lg"</span><span class="hljs-operator">></span>
      <span class="hljs-operator">&#x3C;</span>Box sx<span class="hljs-operator">=</span>{{ mt: <span class="hljs-number">4</span>, mb: <span class="hljs-number">2</span> }}<span class="hljs-operator">></span>
        <span class="hljs-operator">&#x3C;</span>Typography variant<span class="hljs-operator">=</span><span class="hljs-string">"h4"</span> align<span class="hljs-operator">=</span><span class="hljs-string">"center"</span> gutterBottom<span class="hljs-operator">></span>
          Shardeum NFT Minter
        <span class="hljs-operator">&#x3C;</span><span class="hljs-operator">/</span>Typography<span class="hljs-operator">></span>
      <span class="hljs-operator">&#x3C;</span><span class="hljs-operator">/</span>Box<span class="hljs-operator">></span>
      <span class="hljs-operator">&#x3C;</span>Grid container spacing<span class="hljs-operator">=</span>{<span class="hljs-number">2</span>}<span class="hljs-operator">></span>
        <span class="hljs-operator">&#x3C;</span>Grid item xs<span class="hljs-operator">=</span>{<span class="hljs-number">12</span>} md<span class="hljs-operator">=</span>{<span class="hljs-number">6</span>}<span class="hljs-operator">></span>
        <span class="hljs-operator">&#x3C;</span>Box mt<span class="hljs-operator">=</span>{<span class="hljs-number">2</span>}<span class="hljs-operator">></span>
              <span class="hljs-operator">&#x3C;</span>Button
                fullWidth
                variant<span class="hljs-operator">=</span><span class="hljs-string">"contained"</span>
                color<span class="hljs-operator">=</span><span class="hljs-string">"primary"</span>
                onClick<span class="hljs-operator">=</span>{handleConnectMetaMask}
                size<span class="hljs-operator">=</span><span class="hljs-string">"small"</span>
                disabled<span class="hljs-operator">=</span>{walletAddress} 
              <span class="hljs-operator">></span>
                {walletAddress ? <span class="hljs-string">"Wallet Connected"</span> : <span class="hljs-string">"Connect Wallet to Shardeum Sphinx Dapp 1.X"</span>}
              <span class="hljs-operator">&#x3C;</span><span class="hljs-operator">/</span>Button<span class="hljs-operator">></span>
            <span class="hljs-operator">&#x3C;</span><span class="hljs-operator">/</span>Box<span class="hljs-operator">></span>
          {walletAddress <span class="hljs-operator">&#x26;</span><span class="hljs-operator">&#x26;</span> (
            <span class="hljs-operator">&#x3C;</span>Box mt<span class="hljs-operator">=</span>{<span class="hljs-number">2</span>}<span class="hljs-operator">></span>
              <span class="hljs-operator">&#x3C;</span>Typography align<span class="hljs-operator">=</span><span class="hljs-string">"center"</span><span class="hljs-operator">></span>
                Wallet Address: {walletAddress}
              <span class="hljs-operator">&#x3C;</span><span class="hljs-operator">/</span>Typography<span class="hljs-operator">></span>
              <span class="hljs-operator">&#x3C;</span>Typography align<span class="hljs-operator">=</span><span class="hljs-string">"center"</span><span class="hljs-operator">></span>
                Wallet Balance: {walletBalance} SHM
              <span class="hljs-operator">&#x3C;</span><span class="hljs-operator">/</span>Typography<span class="hljs-operator">></span>
            <span class="hljs-operator">&#x3C;</span><span class="hljs-operator">/</span>Box<span class="hljs-operator">></span>
          )}
          <span class="hljs-operator">&#x3C;</span>TextField
            fullWidth
            label<span class="hljs-operator">=</span><span class="hljs-string">"NFT Name"</span>
            variant<span class="hljs-operator">=</span><span class="hljs-string">"outlined"</span>
            margin<span class="hljs-operator">=</span><span class="hljs-string">"normal"</span>
            onChange<span class="hljs-operator">=</span>{(e) <span class="hljs-operator">=</span><span class="hljs-operator">></span> setName(e.target.<span class="hljs-built_in">value</span>)}
          <span class="hljs-operator">/</span><span class="hljs-operator">></span>
          <span class="hljs-operator">&#x3C;</span>TextField
            fullWidth
            label<span class="hljs-operator">=</span><span class="hljs-string">"NFT Description"</span>
            variant<span class="hljs-operator">=</span><span class="hljs-string">"outlined"</span>
            margin<span class="hljs-operator">=</span><span class="hljs-string">"normal"</span>
            onChange<span class="hljs-operator">=</span>{(e) <span class="hljs-operator">=</span><span class="hljs-operator">></span> setDescription(e.target.<span class="hljs-built_in">value</span>)}
          <span class="hljs-operator">/</span><span class="hljs-operator">></span>
          <span class="hljs-operator">&#x3C;</span>input
            <span class="hljs-keyword">type</span><span class="hljs-operator">=</span><span class="hljs-string">"file"</span>
            style<span class="hljs-operator">=</span>{{ display: <span class="hljs-string">"none"</span> }}
            id<span class="hljs-operator">=</span><span class="hljs-string">"image-upload"</span>
            onChange<span class="hljs-operator">=</span>{handleImageChange}
          <span class="hljs-operator">/</span><span class="hljs-operator">></span>
          <span class="hljs-operator">&#x3C;</span>p<span class="hljs-operator">></span><span class="hljs-operator">&#x3C;</span><span class="hljs-operator">/</span>p<span class="hljs-operator">></span>
          <span class="hljs-operator">&#x3C;</span>label      htmlFor<span class="hljs-operator">=</span><span class="hljs-string">"image-upload"</span><span class="hljs-operator">></span>
        <span class="hljs-operator">&#x3C;</span>Button variant<span class="hljs-operator">=</span><span class="hljs-string">"contained"</span> color<span class="hljs-operator">=</span><span class="hljs-string">"primary"</span> component<span class="hljs-operator">=</span><span class="hljs-string">"span"</span><span class="hljs-operator">></span>
          Upload Image
        <span class="hljs-operator">&#x3C;</span><span class="hljs-operator">/</span>Button<span class="hljs-operator">></span>
      <span class="hljs-operator">&#x3C;</span><span class="hljs-operator">/</span>label<span class="hljs-operator">></span>
      {imageStatus <span class="hljs-operator">&#x26;</span><span class="hljs-operator">&#x26;</span> (
        <span class="hljs-operator">&#x3C;</span>Typography variant<span class="hljs-operator">=</span><span class="hljs-string">"caption"</span> display<span class="hljs-operator">=</span><span class="hljs-string">"block"</span> gutterBottom<span class="hljs-operator">></span>
          {imageStatus}
        <span class="hljs-operator">&#x3C;</span><span class="hljs-operator">/</span>Typography<span class="hljs-operator">></span>
      )}
      <span class="hljs-operator">&#x3C;</span>Box mt<span class="hljs-operator">=</span>{<span class="hljs-number">2</span>}<span class="hljs-operator">></span>
        <span class="hljs-operator">&#x3C;</span>Button
          fullWidth
          variant<span class="hljs-operator">=</span><span class="hljs-string">"contained"</span>
          color<span class="hljs-operator">=</span><span class="hljs-string">"secondary"</span>
          onClick<span class="hljs-operator">=</span>{mint}
        <span class="hljs-operator">></span>
          Mint NFT
        <span class="hljs-operator">&#x3C;</span><span class="hljs-operator">/</span>Button<span class="hljs-operator">></span>
      <span class="hljs-operator">&#x3C;</span><span class="hljs-operator">/</span>Box<span class="hljs-operator">></span>
      {loading <span class="hljs-operator">&#x26;</span><span class="hljs-operator">&#x26;</span> <span class="hljs-operator">&#x3C;</span>LinearProgress <span class="hljs-operator">/</span><span class="hljs-operator">></span>}
      
      <span class="hljs-operator">&#x3C;</span>Snackbar
        open<span class="hljs-operator">=</span>{alertOpen}
        autoHideDuration<span class="hljs-operator">=</span>{<span class="hljs-number">6000</span>}
        onClose<span class="hljs-operator">=</span>{() <span class="hljs-operator">=</span><span class="hljs-operator">></span> setAlertOpen(<span class="hljs-literal">false</span>)}
        anchorOrigin<span class="hljs-operator">=</span>{{ vertical: <span class="hljs-string">"top"</span>, horizontal: <span class="hljs-string">"right"</span> }}
      <span class="hljs-operator">></span>
        <span class="hljs-operator">&#x3C;</span>Alert
          onClose<span class="hljs-operator">=</span>{() <span class="hljs-operator">=</span><span class="hljs-operator">></span> setAlertOpen(<span class="hljs-literal">false</span>)}
          severity<span class="hljs-operator">=</span><span class="hljs-string">"success"</span>
          variant<span class="hljs-operator">=</span><span class="hljs-string">"filled"</span>
          sx<span class="hljs-operator">=</span>{{ width: <span class="hljs-string">"100%"</span> }}
        <span class="hljs-operator">></span>
          NFT minted successfully<span class="hljs-operator">!</span>
        <span class="hljs-operator">&#x3C;</span><span class="hljs-operator">/</span>Alert<span class="hljs-operator">></span>
      <span class="hljs-operator">&#x3C;</span><span class="hljs-operator">/</span>Snackbar<span class="hljs-operator">></span>
    <span class="hljs-operator">&#x3C;</span><span class="hljs-operator">/</span>Grid<span class="hljs-operator">></span>
    <span class="hljs-operator">&#x3C;</span>Grid item xs<span class="hljs-operator">=</span>{<span class="hljs-number">12</span>} md<span class="hljs-operator">=</span>{<span class="hljs-number">6</span>}<span class="hljs-operator">></span>
  <span class="hljs-operator">&#x3C;</span>Box
    mt<span class="hljs-operator">=</span>{<span class="hljs-number">2</span>}
    sx<span class="hljs-operator">=</span>{{
      border: <span class="hljs-string">"1px dashed #999"</span>,
      borderRadius: <span class="hljs-string">"12px"</span>,
      padding: <span class="hljs-string">"16px"</span>,
      display: <span class="hljs-string">"flex"</span>,
      justifyContent: <span class="hljs-string">"center"</span>,
      alignItems: <span class="hljs-string">"center"</span>,
      minHeight: <span class="hljs-string">"300px"</span>,
      background: imagePreviewUrl
        ? <span class="hljs-string">"none"</span>
        : <span class="hljs-string">"linear-gradient(45deg, rgba(255,255,255,1) 0%, rgba(255,255,255,0) 100%)"</span>,
    }}
  <span class="hljs-operator">></span>
    {imagePreviewUrl ? (
      <span class="hljs-operator">&#x3C;</span>img
        src<span class="hljs-operator">=</span>{imagePreviewUrl}
        alt<span class="hljs-operator">=</span><span class="hljs-string">"Uploaded preview"</span>
        style<span class="hljs-operator">=</span>{{
          width: <span class="hljs-string">"100%"</span>,
          maxHeight: <span class="hljs-string">"300px"</span>,
          objectFit: <span class="hljs-string">"contain"</span>,
          borderRadius: <span class="hljs-string">"12px"</span>,
        }}
      <span class="hljs-operator">/</span><span class="hljs-operator">></span>
    ) : (
      <span class="hljs-operator">&#x3C;</span>Typography variant<span class="hljs-operator">=</span><span class="hljs-string">"caption"</span> color<span class="hljs-operator">=</span><span class="hljs-string">"text.secondary"</span><span class="hljs-operator">></span>
        Preview image will be displayed here
      <span class="hljs-operator">&#x3C;</span><span class="hljs-operator">/</span>Typography<span class="hljs-operator">></span>
    )}
  <span class="hljs-operator">&#x3C;</span><span class="hljs-operator">/</span>Box<span class="hljs-operator">></span>
<span class="hljs-operator">&#x3C;</span><span class="hljs-operator">/</span>Grid<span class="hljs-operator">></span>
    <span class="hljs-operator">&#x3C;</span>Box mt<span class="hljs-operator">=</span>{<span class="hljs-number">2</span>}<span class="hljs-operator">></span>
        <span class="hljs-operator">&#x3C;</span>Typography align<span class="hljs-operator">=</span><span class="hljs-string">"center"</span> color<span class="hljs-operator">=</span><span class="hljs-string">"textSecondary"</span><span class="hljs-operator">></span>
          {status}
        <span class="hljs-operator">&#x3C;</span><span class="hljs-operator">/</span>Typography<span class="hljs-operator">></span>
        {ipfsLink <span class="hljs-operator">&#x26;</span><span class="hljs-operator">&#x26;</span> (
      <span class="hljs-operator">&#x3C;</span>Typography align<span class="hljs-operator">=</span><span class="hljs-string">"left"</span><span class="hljs-operator">></span>
    IPFS Link:{<span class="hljs-string">" "</span>}
    <span class="hljs-operator">&#x3C;</span>Link href<span class="hljs-operator">=</span>{ipfsLink} target<span class="hljs-operator">=</span><span class="hljs-string">"_blank"</span> rel<span class="hljs-operator">=</span><span class="hljs-string">"noopener noreferrer"</span><span class="hljs-operator">></span>
      {ipfsLink}
    <span class="hljs-operator">&#x3C;</span><span class="hljs-operator">/</span>Link<span class="hljs-operator">></span>
      <span class="hljs-operator">&#x3C;</span><span class="hljs-operator">/</span>Typography<span class="hljs-operator">></span>
)}
      <span class="hljs-operator">&#x3C;</span><span class="hljs-operator">/</span>Box<span class="hljs-operator">></span>
  <span class="hljs-operator">&#x3C;</span><span class="hljs-operator">/</span>Grid<span class="hljs-operator">></span>
  <span class="hljs-operator">&#x3C;</span>Box mt<span class="hljs-operator">=</span>{<span class="hljs-number">4</span>}<span class="hljs-operator">></span>
        <span class="hljs-operator">&#x3C;</span>Typography variant<span class="hljs-operator">=</span><span class="hljs-string">"h7"</span> align<span class="hljs-operator">=</span><span class="hljs-string">"center"</span><span class="hljs-operator">></span>
          Transaction History:
        <span class="hljs-operator">&#x3C;</span><span class="hljs-operator">/</span>Typography<span class="hljs-operator">></span>
        {transactionHistory.<span class="hljs-built_in">length</span> <span class="hljs-operator">></span> <span class="hljs-number">0</span> ? (
          transactionHistory.map((hash, index) <span class="hljs-operator">=</span><span class="hljs-operator">></span> (
            <span class="hljs-operator">&#x3C;</span>Box key<span class="hljs-operator">=</span>{index} mt<span class="hljs-operator">=</span>{<span class="hljs-number">1</span>} textAlign<span class="hljs-operator">=</span><span class="hljs-string">"left"</span><span class="hljs-operator">></span>
              <span class="hljs-operator">&#x3C;</span>Link
                href<span class="hljs-operator">=</span>{`https:<span class="hljs-comment">//explorer-dapps.shardeum.org/transaction/${hash}`}</span>
                target<span class="hljs-operator">=</span><span class="hljs-string">"_blank"</span>
                rel<span class="hljs-operator">=</span><span class="hljs-string">"noopener noreferrer"</span>
              <span class="hljs-operator">></span>
                {`Transaction ${index <span class="hljs-operator">+</span> <span class="hljs-number">1</span>}: ${hash}`}
              <span class="hljs-operator">&#x3C;</span><span class="hljs-operator">/</span>Link<span class="hljs-operator">></span>
            <span class="hljs-operator">&#x3C;</span><span class="hljs-operator">/</span>Box<span class="hljs-operator">></span>
          ))
        ) : (
          <span class="hljs-operator">&#x3C;</span>Typography align<span class="hljs-operator">=</span><span class="hljs-string">"center"</span> mt<span class="hljs-operator">=</span>{<span class="hljs-number">1</span>}<span class="hljs-operator">></span>
            No transactions yet.
          &#x3C;<span class="hljs-operator">/</span>Typography<span class="hljs-operator">></span>
        )}
      <span class="hljs-operator">&#x3C;</span><span class="hljs-operator">/</span>Box<span class="hljs-operator">></span>
<span class="hljs-operator">&#x3C;</span><span class="hljs-operator">/</span>Container<span class="hljs-operator">></span>
);
}
export default MintNFT;
</code></pre><ul><li><p><em>Theme.js</em>: Este archivo contiene todos los temas necesarios para dar estilo a nuestra aplicación.</p></li></ul><pre data-type="codeBlock" text="import { createTheme } from &quot;@mui/material/styles&quot;;
const theme = createTheme({
  palette: {
    mode: &quot;dark&quot;,
    
    primary: {
      main: &quot;#ffc926&quot;,
    },
    secondary: {
      main: &quot;#088ef3&quot;,
    },
  },
  typography: {
    fontFamily: &quot;Roboto, Arial, sans-serif&quot;,
    h4: {
      fontWeight: 700,
      marginBottom: &quot;16px&quot;,
    },
    h5: {
      fontWeight: 600,
      marginBottom: &quot;12px&quot;,
    },
    h6: {
      fontWeight: 500,
      marginBottom: &quot;8px&quot;,
    },
    subtitle1: {
      fontWeight: 400,
      marginBottom: &quot;8px&quot;,
    },
    caption: {
      fontStyle: &quot;italic&quot;,
    },
  },
});
export default theme;
"><code>import { createTheme } <span class="hljs-keyword">from</span> <span class="hljs-string">"@mui/material/styles"</span>;
<span class="hljs-keyword">const</span> <span class="hljs-variable constant_">theme</span> = <span class="hljs-title function_ invoke__">createTheme</span>({
  <span class="hljs-attr">palette</span>: {
    <span class="hljs-attr">mode</span>: <span class="hljs-string">"dark"</span>,
    
    <span class="hljs-attr">primary</span>: {
      <span class="hljs-attr">main</span>: <span class="hljs-string">"#ffc926"</span>,
    },
    <span class="hljs-attr">secondary</span>: {
      <span class="hljs-attr">main</span>: <span class="hljs-string">"#088ef3"</span>,
    },
  },
  <span class="hljs-attr">typography</span>: {
    <span class="hljs-attr">fontFamily</span>: <span class="hljs-string">"Roboto, Arial, sans-serif"</span>,
    <span class="hljs-attr">h4</span>: {
      <span class="hljs-attr">fontWeight</span>: <span class="hljs-number">700</span>,
      <span class="hljs-attr">marginBottom</span>: <span class="hljs-string">"16px"</span>,
    },
    <span class="hljs-attr">h5</span>: {
      <span class="hljs-attr">fontWeight</span>: <span class="hljs-number">600</span>,
      <span class="hljs-attr">marginBottom</span>: <span class="hljs-string">"12px"</span>,
    },
    <span class="hljs-attr">h6</span>: {
      <span class="hljs-attr">fontWeight</span>: <span class="hljs-number">500</span>,
      <span class="hljs-attr">marginBottom</span>: <span class="hljs-string">"8px"</span>,
    },
    <span class="hljs-attr">subtitle1</span>: {
      <span class="hljs-attr">fontWeight</span>: <span class="hljs-number">400</span>,
      <span class="hljs-attr">marginBottom</span>: <span class="hljs-string">"8px"</span>,
    },
    <span class="hljs-attr">caption</span>: {
      <span class="hljs-attr">fontStyle</span>: <span class="hljs-string">"italic"</span>,
    },
  },
});
export <span class="hljs-keyword">default</span> theme;
</code></pre><p>Con los archivos anteriores, ahora tenemos la mayor parte de nuestro front-end cubierto. Realiza los cambios necesarios en <em>App.js, App.css, index.js &amp; index.css</em> para incorporar todos los estilos e importar los archivos necesarios. Puedes encontrar los archivos finales para estos en el Github Jist <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://gist.github.com/skundu42/3139408119043a91a9a567e97b078c08">aquí</a>.</p><p>También puedes encontrar la aplicación completamente construida <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/skundu42/nft-minter-dapp">aquí</a>. Siéntete libre para que coincida con su propio código siempre que se pegue.</p><h1 id="h-4-ejecutar-la-aplicacion-localmente" class="text-4xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0"><strong>4. Ejecutar la aplicación localmente</strong></h1><p>Ahora que tenemos todo el código necesario escrito, es el momento de ejecutar nuestra aplicación localmente. Ejecuta el siguiente comando para ejecutarlo en tu localhost.</p><pre data-type="codeBlock" text="npm start
"><code>npm <span class="hljs-keyword">start</span>
</code></pre><p>Abre <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="http://localhost:3000/">http://localhost:3000</a> en tu navegador web para empezar a utilizar tu aplicación recién creada para mintear NFT en Shardeum.</p><p>Aquí tienes una imagen de demostración de la aplicación:</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/8134c5477b72c94d90a647419777534a30be1db54aa71c9e364f8bcaff5fc47c.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>Fuente de la traducción (9 de marzo de 2024): <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://shardeum.org/blog/build-an-nft-minter-dapp-on-shardeum/">https://shardeum.org/blog/build-an-nft-minter-dapp-on-shardeum/</a></p>]]></content:encoded>
            <author>maxeuwe@newsletter.paragraph.com (maxeuwe.eth)</author>
        </item>
        <item>
            <title><![CDATA[Hito de Shardeum: Restauración de la red dinámicamente fragmentada.]]></title>
            <link>https://paragraph.com/@maxeuwe/hito-de-shardeum-restauraci-n-de-la-red-din-micamente-fragmentada</link>
            <guid>TEiWog67KSZczaIvuGTe</guid>
            <pubDate>Tue, 20 Feb 2024 14:26:21 GMT</pubDate>
            <description><![CDATA[#ShardeumIsBorderless and @shardeumShardeum’s Blast Off: un logro revolucionarioEl lunes 27 de enero de 2024 se produjo un acontecimiento sin precedentes en el mundo de la web3 que puede compararse a la hazaña histórica de una nave espacial que regresa sin problemas a su plataforma de lanzamiento tras su primera misión de vuelo de prueba. En este extraordinario escenario, Shardeum no sólo se enfrentó a un reto formidable, sino que también salió triunfal, con la capacidad de recuperación de su...]]></description>
            <content:encoded><![CDATA[<p><strong>#ShardeumIsBorderless and @shardeum</strong></p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/a54764e1cfadc7dd0950406e8105c85a3901523d3f40375d7860e7f7c5ca4250.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><h1 id="h-shardeums-blast-off-un-logro-revolucionario" class="text-4xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0"><strong>Shardeum’s Blast Off: un logro revolucionario</strong></h1><p>El lunes 27 de enero de 2024 se produjo un acontecimiento sin precedentes en el mundo de la web3 que puede compararse a la hazaña histórica de una nave espacial que regresa sin problemas a su plataforma de lanzamiento tras su primera misión de vuelo de prueba. En este extraordinario escenario, <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://shardeum.org/">Shardeum</a> no sólo se enfrentó a un reto formidable, sino que también salió triunfal, con la capacidad de recuperación de su red marcando la primera vez que una red fragmentada se ha auto-restaurado en el ámbito de la tecnología de ledger distribuido.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/7bfe20717ebd6784e61407e46d14412f316a0451cc0448fe4ad388e0d9e23ef4.png" alt="Imagen generada por IA" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">Imagen generada por IA</figcaption></figure><p>Al igual que el viaje de una nave espacial implica una planificación meticulosa, ingeniería de precisión y la ejecución perfecta de maniobras complejas, la restauración por Shardeum de su <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://shardeum.org/betanet/">betanet Sphinx</a>, que había sufrido un accidente crítico, requirió un nivel equivalente de dominio tecnológico e innovación. La capacidad de preservar todos los datos de una red, sobre todo de una que funciona con fragmentación dinámica de estados, no tiene nada de innovador.</p><p>Al embarcarnos en esta exploración, no sólo celebramos el trascendental aterrizaje de Shardeum, sino que lo reconocemos como un momento crucial en la evolución de la tecnología web3, un salto que podría redefinir los límites de la resistencia de las redes informáticas y la integridad de los datos.</p><h1 id="h-primera-red-fragmentada-que-se-autorrestaura-y-conserva-los-datos" class="text-4xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0"><strong>Primera red fragmentada que se autorrestaura y conserva los datos</strong></h1><p>Mantener y restaurar una red fragmentada dinámicamente, como Shardeum, conlleva una serie de complejos retos técnicos que la diferencian de las redes blockchain tradicionales como Bitcoin o Ethereum. En un entorno de fragmentación dinámica con autoescalado, la reasignación y el equilibrio continuos de nodos y recursos entre diferentes fragmentaciones son cruciales para optimizar el rendimiento y la escalabilidad. Este flujo constante en la arquitectura de red añade una complejidad significativa a la hora de mantener la coherencia de los datos, garantizar la estabilidad de la red y facilitar una recuperación eficaz de los fallos.</p><p>La criticidad de estos retos se acentúa al contrastar la respuesta de Shardeum a las fluctuaciones de los nodos con la de Bitcoin. La red Bitcoin mantiene su funcionalidad incluso con un número mínimo de nodos, ya que cada nodo completo posee el estado completo y el historial de transacciones. Por el contrario, cada nodo activo de Shardeum no posee el estado completo ni el historial de transacciones, ya que la red Shardeum está fragmentada y cada validador sólo posee un subconjunto del estado completo. La consecuencia de esta fragmentación es que todos los nodos validadores son extremadamente ligeros. Esto crea una plétora de oportunidades y retos de ingeniería. Si un nodo se cae, ¿cómo nos aseguramos de que se conservan todos los datos? Shardeum tiene dos formas principales.</p><p>En primer lugar, Shardeum utiliza la <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://shardeum.org/blog/dynamic-state-sharding-shardeum/">fragmentación dinámica de estados</a>, en la que el espacio global de direcciones se particiona (o divide) en función del número de nodos activos. Cada nodo es responsable de sus particiones asignadas, junto con un determinado radio (R) a su alrededor y particiones adicionales (E) adyacentes a él, lo que garantiza una adaptabilidad dinámica y una sólida redundancia de datos en el marco de la red. Así, aunque un nodo se caiga, sigue habiendo continuidad en la red y no se pierden datos.</p><p>En segundo lugar, Shardeum utiliza <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://shardeum.org/blog/shardeum-archive-nodes-explained/">nodos archivadores</a> para almacenar el estado completo de toda la red. Para ello, los nodos activos envían sus estados parcialmente almacenados a los archivadores para que los recojan. Debido a estos dos factores y a las optimizaciones de diseño, la restauración de una red de este tipo tiene que diseñarse de forma novedosa para seguir facilitando características ventajosas como el autoescalado y el <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://shardeum.org/blog/shardeum-achieves-linear-scalability/">escalado lineal</a>.</p><h1 id="h-entendiendo-el-choque" class="text-4xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0"><strong>Entendiendo el Choque</strong></h1><p>Ahora que entendemos los fundamentos de la fragmentación dinámica de estados y que los nodos archivadores están implicados de alguna manera, vamos a desentrañar primero algunos componentes adicionales más profundamente y a explicarlos. Para entender la caída y la restauración de la betanet Shardeum, primero debemos entender un poco lo siguiente:</p><ul><li><p><strong>Nodos archivadores</strong></p></li><li><p><strong>Detección de archivadores perdidos</strong></p></li><li><p><strong>Modos de red</strong></p></li><li><p><strong>Modo de recuperación</strong></p></li></ul><p>Entender lo básico de cada uno de ellos es necesario antes de sumergirnos de cabeza en los fallos, ¡así que echemos un vistazo!</p><h1 id="h-nodos-archivadores-almacenamiento-interestelar" class="text-4xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0"><strong>Nodos archivadores: Almacenamiento interestelar</strong></h1><p>En Shardeum, los nodos archivadores, también llamados archiveros, constituyen una categoría crítica de nodos, encargados de preservar el estado completo y los registros históricos de la red. A diferencia de los nodos activos, los archivadores no participan en los procesos de consenso; su función principal es archivar exhaustivamente la totalidad de los datos de la red, incluidas las transacciones y los recibos. La contribución de los nodos archivadores es esencial para mantener la integridad de la red y garantizar su perfecto funcionamiento, afirmando así el estatus de Shardeum como una red robusta, completa y fiable. Debido a que los archivadores son parte integral de la red, Shardeum debe tener un protocolo para detectar cualquier archivador (y validador) que no responda.</p><h1 id="h-deteccion-del-archivador-perdido-tecnologia-alienigena-al-descubierto" class="text-4xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0"><strong>Detección del Archivador Perdido: Tecnología alienígena al descubierto</strong></h1><p>Shardeum tiene un protocolo llamado detección de nodos perdidos que detecta cuando los nodos activos dejan de funcionar — esto está reservado <em>únicamente</em> para los nodos activos. Sin embargo, Shardeum también tiene un protocolo para los archivadores que hace algo similar llamado detección de archivador perdido. La detección de archivadores perdidos es un protocolo especializado diseñado para manejar escenarios raros en los que uno o más archivadores dejan de estar operativos y se marcan como perdidos. Dado que los nodos archivadores son fundamentales para mantener la integridad y accesibilidad de los datos históricos dentro de la red, es esencial que, en las raras ocasiones en que no respondan o no funcionen, se detecten estos eventos críticos para mitigar cualquier efecto posterior. Aunque la pérdida de archivadores no causó este fallo en particular, sí lo hizo la interacción entre el protocolo de detección de pérdida de archivadores y un modo de red específico. Examinemos ahora cuáles son los modos de red en Shardeum.</p><h1 id="h-modos-de-red-en-shardeum-no-se-necesita-a-la-nasa" class="text-4xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0"><strong>Modos de red en Shardeum: No se necesita a la NASA</strong></h1><p>Una innovación emblemática de Shardeum, impulsada por el protocolo subyacente Shardus, es el marco de modos de red. Estos modos trascienden los estados operativos básicos y encarnan una intrincada coordinación de diversas actividades de nodos, métodos de sincronización de datos y sistemas de gestión de transacciones. Estas configuraciones de red desempeñan un papel crucial en la preservación de la integridad operativa de la red, especialmente en escenarios caracterizados por la pérdida de nodos y datos, ya que Shardeum es una red fragmentada.</p><p>A un nivel más simple, la mejor manera de concebir los modos de red en Shardeum es como planes de contingencia codificados que permiten la continuidad de las operaciones de toda la red, incluso en condiciones improbables como la caída de la red o la degradación de toda la red. Esta resistencia y robustez operativas preprogramadas garantizan que Shardeum siempre seguirá viva, sea cual sea la adversidad a la que se enfrente la red.</p><p>Aunque para entender el fallo no hace falta digerir todas las facetas del marco de los modos de red, sí ayuda familiarizarse con lo básico. Un elemento central del marco de modos de red es la incorporación de varias fases de red distintas: Formación, Procesamiento, Seguridad, Recuperación, Reinicio, Restauración y Apagado. Estos modos están cuidadosamente diseñados para hacer frente a diversas situaciones y emergencias de la red. Sin embargo, el modo que nos ocupa en este artículo es el de recuperación.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/7ff9eadcda163f840f7c65c6863afa70f5c018688e63a237523e7f3e90f57c49.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><h1 id="h-modo-de-recuperacion-de-ingenieria-inversa-rosewell-revisitado" class="text-4xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0"><strong>Modo de recuperación de ingeniería inversa: Rosewell revisitado</strong></h1><p>El modo de recuperación es 1 de los 7 modos de red antes mencionados. El modo de recuperación se inicia cuando el recuento de nodos activos de la red desciende por debajo de un umbral crítico predefinido (actualmente configurado en 75% o inferior). Este umbral es ajustable según los requisitos de la red. En este modo, la red detiene temporalmente el procesamiento de transacciones de aplicaciones y la sincronización de datos de aplicaciones. Esta estrategia está diseñada para facilitar la expansión de la red mediante la introducción gradual de nodos de reserva como parte de la rotación de nodos, restaurando así el recuento de nodos activos a un nivel óptimo, idealmente por encima del 100%.</p><p>Durante el modo de recuperación, la arquitectura de red de Shardeum permite un aumento incremental de los nodos, con un tope del 20% de crecimiento por ciclo (<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://shardeum.org/blog/what-are-polling-cycles-in-shardeum/">cada ciclo dura aproximadamente 60 segundos</a>). Este ritmo de crecimiento controlado es fundamental para mantener la estabilidad de la red y garantizar una integración perfecta de los nuevos nodos. Un aumento rápido del número de nodos, por ejemplo del 50%, podría desestabilizar la red y complicar el proceso de integración.</p><p>Cada nuevo nodo añadido necesita recursos de red para su sincronización e integración. Al limitar el aumento al 20% por ciclo, la red se asegura de que su infraestructura pueda soportar adecuadamente la adición de nuevos nodos sin tensiones. Este enfoque no sólo preserva la estabilidad de la red, sino que también minimiza el riesgo de incoherencias o errores en los datos durante el proceso de sincronización, manteniendo así la integridad de los datos de la cadena de ciclos.</p><h1 id="h-la-causa-principal-del-accidente-horizonte-de-sucesos" class="text-4xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0"><strong>La causa principal del accidente: Horizonte de sucesos</strong></h1><p>Es importante señalar que había dos errores distintos. El <em>bug de la librería neon</em> — que causaba que los validadores se bloquearan aparentemente al azar y un <em>bug en el protocolo de detección de archivadores perdidos</em> — que no aceptaba una lista de validadores vacía. Aunque es el bug del protocolo de detección de archivadores perdidos el que causó el fallo de la versión betanet, me gustaría explicarles primero el bug de la librería neon.</p><p>En la versión Sphinx 1.9.1, integramos una actualización a una librería que emplea Neon bindings para unir funcionalidades Rust y TypeScript ya que Shardeum está construido predominantemente en TypeScript. Neon es reconocido por su enfoque innovador, aunque experimental, a menudo empujando los límites de las prácticas convencionales de desarrollo de software. Esta integración tenía como objetivo mejorar la interoperabilidad entre estos dos lenguajes, permitiendo una comunicación más eficiente y directa dentro de nuestra arquitectura de software. Sin embargo, esto provocó un error que hacía que los nodos abandonaran aleatoriamente la red.</p><p>En segundo lugar, en el reciente incidente que provocó la caída de la betanet en Shardeum, la causa principal se identificó como una anomalía crítica originada por la interacción entre los dos subsistemas distintos antes mencionados: <em>el mecanismo de detección de archivadores perdidos</em> y el <em>protocolo de modo de recuperación de la red</em>.Este breve fallo se precipitó por la activación simultánea de estos dos mecanismos, un escenario no encontrado ni probado anteriormente. El proceso de archivador perdido se activó junto con el mod de recuperación de red y debido a un fallo en el modo de archivador perdido que no aceptaba una lista de nodos activos vacía. Esto culminó en la caída de la red.</p><h1 id="h-cronicas-de-la-recuperacion-del-shock-sistemico-a-la-recuperacion-estelar" class="text-4xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0"><strong>Crónicas de la recuperación: Del shock sistémico a la recuperación estelar</strong></h1><p>¿Qué más ocurrió realmente y cuándo? La cronología de los acontecimientos que rodearon la caída de la red y su resolución es la siguiente:</p><ol><li><p><strong>Vulnerabilidad inicial y actualización:</strong> La red se encontró con una vulnerabilidad señalada por el proceso 1.9.1 linting dentro de una biblioteca npm (neon). Se implementó una actualización para solucionar este problema. Sin embargo, esta actualización introdujo inadvertidamente una excepción que no se reprodujo durante las pruebas locales.</p></li><li><p><strong>Excepción intermitente en la biblioteca que provoca cierres del validador</strong>: La biblioteca neon experimentaba excepciones esporádicas que provocaban cierres periódicos de los validadores de red. Aunque el diseño de la red permitía la resistencia mediante el rellenado de estos validadores y, por desgracia, la sincronización de fallos simultáneos entre varios validadores activó el modo de recuperación de la red.</p></li><li><p><strong>Activación del modo de recuperación de la red</strong>: Una vez en el modo de recuperación de la red, el protocolo necesitó borrar y regenerar la lista de nodos activos. La causa principal de la caída de la red fue un fallo simultáneo en el sistema de archivo de pérdidas, que no admitía una lista de validadores vacía.</p></li><li><p><strong>Resolución y restauración de la red</strong>: Se rectificó el fallo y la red se restauró con éxito utilizando los datos almacenados en los archivadores. <strong>Es la primera vez en la historia que una red fragmentada de capa 1 que se ha bloqueado se restaura con éxito y todos los datos de la red se conservan intactos</strong>. Esto no se había conseguido nunca en ninguna red, y mucho menos en una red con fragmentación dinámica de estados. Este logro marcó el exitoso “aterrizaje del cohete” en términos de recuperación de redes.</p></li><li><p><strong>Correcciones realizadas</strong>: Se implementó una corrección preliminar para solucionar el problema de la biblioteca, pero en un esfuerzo continuo por mejorar la estabilidad de la red, se lanzó la versión 1.9.5. Esta actualización introdujo un fallo singular pero crucial. Esta actualización introdujo una corrección de errores singular pero crucial que abordaba otro caso del fallo de enlace de neon, señalando y rectificando una vulnerabilidad específica sin obligar a una actualización de toda la red. Inicialmente, los usuarios que utilizaban la versión 1.9.4 tenían la posibilidad de permanecer en su versión actual u optar por la actualización a la 1.9.5, en función de sus preferencias de rendimiento y estabilidad de la red. Sin embargo, finalmente se decidió que, con el fin de mejorar la estabilidad de la red y resolver los problemas persistentes relacionados con los enlaces de neon, la versión mínima requerida para los validadores debía aumentarse a 1.9.5. Con esta actualización se pretendía excluir sistemáticamente a los validadores que funcionan con la versión 1.9.4, que se han identificado como susceptibles de bloquearse debido a la complicación de los neon bindings antes mencionada. Esto es necesario para asegurarse de que el fallo de neon está totalmente anulado y completamente solucionado.</p></li></ol><p>Ahora que conocemos la cronología y cómo se desencadenaron los principales acontecimientos, echemos un vistazo a lo que ocurrió para que la red se restableciera tan rápidamente.</p><h1 id="h-rumbo-a-la-restauracion" class="text-4xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0"><strong>Rumbo a la restauración</strong></h1><p><strong>Recuperación ágil</strong>La restauración de la red constó de muchas partes, pero una de las fundamentales fue el modo de recuperación de Shardeum. Como ya se ha dicho, el modo de recuperación se inicia cuando el recuento de nodos activos de la red desciende por debajo de un umbral crítico predefinido y permite un crecimiento rápido, controlado y eficaz de la red de forma segura para restaurarla. Es importante destacar que, sin el ingenio tecnológico de los diseñadores y desarrolladores de los modos de red, Shardeum no habría podido recuperarse de la caída con tanta facilidad ni hacer gala de su capacidad innovadora.</p><p>Además, el equipo técnico de Shardeum realizó esfuerzos clave al lanzarse a la acción inmediata. El primer paso consistió en un análisis exhaustivo para identificar la causa de la caída, que se atribuyó a una anomalía en la interacción entre la detección de archivos perdidos de la red y sus sistemas de modo de recuperación. Consciente de la complejidad del problema, el equipo aplicó rápidamente un enfoque polifacético para hacer frente tanto a las consecuencias inmediatas como a las vulnerabilidades subyacentes.</p><h1 id="h-respuesta-polifacetica-del-equipo-tecnico-de-shardeum" class="text-4xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0"><strong>Respuesta polifacética del equipo técnico de Shardeum</strong></h1><p>Técnicamente, la respuesta fue polifacética: en primer lugar, el equipo aisló los componentes afectados para evitar una mayor degradación de la red. Al mismo tiempo, desplegaron un parche para rectificar el error en el sistema de archivo perdido, asegurándose de que podía manejar una lista de validadores vacía, un descuido crítico que había precipitado el fallo de la red. Para restablecer la plena capacidad operativa de la red, se activaron los datos conservados en los archivadores y se utilizaron para reconstruir el estado de la red antes de la caída, garantizando que no se perdieran datos en el proceso.</p><p>Desde el punto de vista logístico, el equipo se coordinó a través de diferentes zonas horarias y disciplinas, aprovechando las herramientas basadas en la nube para la colaboración y la supervisión en tiempo real. Este esfuerzo coordinado no solo facilitó el rápido desarrollo y despliegue de las correcciones, sino que también garantizó que todos los miembros del equipo estuvieran alineados en el proceso de recuperación y los siguientes pasos.</p><p>Este incidente sirvió como rigurosa prueba de los protocolos de gestión de accidentes de Shardeum y puso de relieve la importancia de las respuestas ágiles e innovadoras a los retos imprevistos. Subraya el compromiso del equipo de mantener una red resistente y segura, preparada para afrontar los complejos obstáculos técnicos que surjan.</p><h1 id="h-aterrizaje-seguro-e-innovacion-espacial" class="text-4xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0"><strong>Aterrizaje seguro e innovación espacial</strong></h1><p>En conclusión, la exitosa restauración de la red fragmentada de Shardeum anuncia un cambio significativo en la tecnología de redes, marcando un hito con implicaciones de largo alcance para la industria. Aunque actualmente no se reconocen en gran medida, innovaciones como los modos de red acabarán estableciendo nuevas normas industriales en la web3.</p><p>Creo desde hace tiempo que las innovaciones fundamentales de Shardeum influirán con toda probabilidad en futuros avances tecnológicos, inspirando innovaciones y nuevas generaciones de tecnologías de libro mayor. Habiendo sido testigo de primera mano de la restauración de la red de Shardeum, la primera de su clase, sé que esto catalizará una reevaluación de los estándares de la industria, lo que potencialmente conducirá a la adopción de protocolos y metodologías más rigurosos en el diseño y la arquitectura de la red.</p><p>Este acontecimiento no sólo pone de manifiesto la destreza técnica y la innovación del <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://shardeum.org/blog/category/about-shardeum-team/">equipo de Shardeum</a>, sino que también señala el comienzo de una era en la que las redes descentralizadas son más robustas, adaptables y capaces de hacer frente a retos imprevistos en la planificación de la recuperación en caso de catástrofe. En última instancia, la tecnología de Shardeum anunciará una nueva era de descentralización.</p><p>Fuente de la traducción (19 de febrero de 2024): <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://shardeum.org/blog/shardeum-resilience-restoring-sharded-network/">https://shardeum.org/blog/shardeum-resilience-restoring-sharded-network/</a></p>]]></content:encoded>
            <author>maxeuwe@newsletter.paragraph.com (maxeuwe.eth)</author>
        </item>
    </channel>
</rss>