Componentes NEAR: Una guía para principiantes en el desarrollo Web3

NEAR_ES
10 min readMay 15, 2024

--

Autor: América Castro. Publicado 15 de Mayo de 2024

Explorando el Futuro del Desarrollo Web3 con los Componentes NEAR

En la era de la Web 3.0, la descentralización y la innovación tecnológica están redefiniendo la forma en que concebimos y construimos aplicaciones en línea. En este contexto, NEAR Protocol emerge como una plataforma líder que impulsa esta revolución, ofreciendo herramientas y tecnologías avanzadas para desarrolladores de todo el mundo.

Los Componentes NEAR representan la piedra angular de esta transformación. Más que simples elementos de diseño, estos componentes encapsulan los principios fundamentales de la Web 3.0: son componibles, reutilizables y descentralizados. Al integrar la potencia de NEAR Protocol con la familiaridad y versatilidad de los componentes basados en React, los desarrolladores obtienen acceso a un ecosistema de desarrollo robusto y escalable.

En esta guía introductoria, exploraremos en profundidad el papel vital que juegan los Componentes en el panorama emergente de la Web 3.0. Desde su capacidad para interactuar de forma nativa con contratos inteligentes en la blockchain NEAR hasta su integración fluida con redes sociales descentralizadas, cada aspecto revela nuevas posibilidades y oportunidades para la innovación.

A medida que nos sumergimos en la lectura, descubriremos cómo los Componentes NEAR están allanando el camino hacia un futuro más inclusivo, transparente y descentralizado en el desarrollo web. Prepárate para explorar los horizontes ilimitados de la Web 3.0 y descubrir cómo NEAR Protocol está liderando el camino hacia una nueva era de la internet.

¿Qué son los Componentes NEAR?

Los Componentes son una nueva forma de construir aplicaciones web. Son componibles, reutilizables y descentralizados. En comparación con las tecnologías web tradicionales, los Componentes ofrecen un enfoque más moderno y eficiente para el desarrollo de aplicaciones descentralizadas (dApps).

Familiar para Desarrolladores Web:

Los Componentes NEAR se basan en React Components, una tecnología ampliamente utilizada en el desarrollo web. React Components es una biblioteca de JavaScript que permite a los desarrolladores construir interfaces de usuario interactivas y dinámicas de manera eficiente. Su popularidad se debe a su enfoque en la modularidad, reutilización y facilidad de mantenimiento del código.

En el contexto de los Componentes, esta familiaridad con React Components se traduce en una curva de aprendizaje sencilla para los desarrolladores web. Aquí hay una breve explicación de los conceptos clave que se utilizan en React Components y que también se aplican en los Componentes NEAR:

  • Variables Props: En React, las props (propiedades) son parámetros que se pasan de un componente padre a un componente hijo. Estas props son variables inmutables que contienen información y configuraciones específicas que el componente puede utilizar para renderizar su interfaz de usuario de manera dinámica. Por ejemplo, en un componente de botón, las props podrían incluir el texto del botón o una función de manejo de clic.
const name = props.name || "Maria";
const [count, setCount] = useState(1);

return (
<div>
<p> {count} aplausos para {name}! </p>
<button onClick={() => setCount(count + 1)}>Aplaudir!</button>
</div>
);
  • Estado a través del Hook useState: El estado en React se refiere a los datos que pueden cambiar durante el ciclo de vida de un componente. El hook useState es una función que permite a los componentes funcionales de React tener estado. Al usar useState, los desarrolladores pueden declarar variables de estado y actualizarlas según sea necesario. Por ejemplo, un contador en una aplicación podría almacenarse en el estado utilizando useState, lo que permite que el componente se vuelva a renderizar cada vez que cambie el valor del contador.
  • Efectos Secundarios a través del Hook useEffect: Los efectos secundarios en React son acciones que ocurren después de que se renderiza un componente, como hacer una solicitud a una API externa o suscribirse a eventos del navegador. El hook useEffect permite a los desarrolladores realizar estas acciones en componentes funcionales de React. Al utilizar useEffect, los desarrolladores pueden asegurarse de que su lógica de efectos secundarios esté separada del código de renderizado principal, lo que mejora la legibilidad y el mantenimiento del código.

Explorando las Características Clave de los Componentes NEAR

NEAR Nativo:

Los Componentes actúan como intermediarios directos entre los desarrolladores y los contratos inteligentes en la Blockchain NEAR. Simplificando, son como mensajeros inteligentes que pueden tanto recibir información como llevar a cabo acciones en estos contratos.

const counter = Near.view('counter.near-examples.testnet', 'get_num')

if(counter === null) return 'Loading...'

const add = () => {
Near.call('counter.near-examples.testnet', 'increment')
}

const subtract = () => {
Near.call('counter.near-examples.testnet', 'decrement')
}

return <>
<p> Counter: {counter} </p>
{!context.accountId &&
<p color="red"> Please login to interact with the contract</p>
}
{context.accountId &&
<>
<button onClick={add}> + </button>
<button onClick={subtract}> - </button>
</>
}
</>

Social desde el Principio:

Los Componentes son como piezas de un rompecabezas que encajan perfectamente en NEAR Social, una red social descentralizada construida sobre NEAR Protocol. Imagina los Componentes como las herramientas que los desarrolladores usan para agregar nuevas funciones y experiencias a esta red, como mostrar publicaciones o permitir que los usuarios interactúen con contenido de manera descentralizada.

const item = (blockHeight) => ({ type: 'social', path: 'influencer.testnet/post/main', blockHeight });

// retrieve indexed posts by influencer.testnet
const idx_posts = Social.index(
'post', 'main', { accountId: ['influencer.testnet'] }
);

if (idx_posts === null) return 'Loading...';

// retrieve likes for each post
const likes = idx_posts.map(
index => Social.index('like', item(index.blockHeight)).length
);

// retrieve data for each post
const post_data = idx_posts.map(
index => Social.get(`${index.accountId}/post/main`, index.blockHeight)
);

// defined "Like" function
const like = (blockHeight) => Social.set(
{index:{like: JSON.stringify({key: item(blockHeight), value: {type: 'like'}})}}
)

return <>
<h5>Posts from <i>influencer.testnet</i></h5>
{post_data.map((post, idx) =>
<div className="mt-3">
<div>{JSON.parse(post).text} - {likes[idx]} likes</div>
{context.accountId && <button className="btn btn-danger btn-sm" onClick={() => like(idx_posts[idx].blockHeight)}>Like</button>}
</div>
)}
</>

Totalmente en la Cadena y Fácilmente Componible:

Imagina los bloques de LEGO, cada bloque es como un componente que se almacenan en la cadena de bloques NEAR. Como estos bloques, los Componentes pueden ensamblarse fácilmente para crear aplicaciones web complejas y poderosas. Su capacidad para encajar y combinarse de manera fluida facilita el proceso de construcción de aplicaciones descentralizadas.

// al recuperar el código de un componente almacenado
return Social.get('influencer.testnet/widget/Greeter')

return `${props.amount} aplausos para ${props.name}!`;

Multi-Cadena por Diseño:

En un mundo donde hay diferentes tipos de monedas, tokens y blockchains, cada una con su propio valor y características únicas, los componentes actúan como esa bolsa mágica al permitir que las aplicaciones interactúen con diferentes blockchains, incluida Ethereum y otras compatibles. Esto significa que, si tienes una aplicación que necesita acceder a datos o realizar acciones en múltiples blockchains, los componentes pueden hacerlo sin problemas.

Los Componentes están diseñados para ser compatibles con múltiples blockchains, lo que permite a los desarrolladores crear aplicaciones web descentralizadas que pueden operar en un ecosistema multi-cadena de manera fluida y sin problemas.

if (
state.chainId === undefined &&
ethers !== undefined &&
Ethers.send("eth_requestAccounts", [])[0]
) {
Ethers.provider()
.getNetwork()
.then((chainIdData) => {
if (chainIdData?.chainId) {
State.update({ chainId: chainIdData.chainId });
}
});
}
if (state.chainId !== undefined && state.chainId !== 1) {
return <p>Switch to Ethereum Mainnet</p>;
}

// FETCH LIDO ABI

const lidoContract = "0xae7ab96520de3a18e5e111b5eaab095312d7fe84";
const tokenDecimals = 18;

const lidoAbi = fetch(
"https://raw.githubusercontent.com/lidofinance/lido-subgraph/master/abis/Lido.json"
);
if (!lidoAbi.ok) {
return "Loading";
}

const iface = new ethers.utils.Interface(lidoAbi.body);

// FETCH LIDO STAKING APR

if (state.lidoArp === undefined) {
const apr = fetch(
"https://api.allorigins.win/get?url=https://stake.lido.fi/api/sma-steth-apr"
);
if (!apr) return;
State.update({ lidoArp: JSON.parse(apr?.body?.contents) ?? "..." });
}

// HELPER FUNCTIONS

const getStakedBalance = (receiver) => {
const encodedData = iface.encodeFunctionData("balanceOf", [receiver]);

return Ethers.provider()
.call({
to: lidoContract,
data: encodedData,
})
.then((rawBalance) => {
const receiverBalanceHex = iface.decodeFunctionResult(
"balanceOf",
rawBalance
);

return Big(receiverBalanceHex.toString())
.div(Big(10).pow(tokenDecimals))
.toFixed(2)
.replace(/\d(?=(\d{3})+\.)/g, "$&,");
});
};

const submitEthers = (strEther, _referral) => {
if (!strEther) {
return console.log("Amount is missing");
}
const erc20 = new ethers.Contract(
lidoContract,
lidoAbi.body,
Ethers.provider().getSigner()
);

let amount = ethers.utils.parseUnits(strEther, tokenDecimals).toHexString();

erc20.submit(lidoContract, { value: amount }).then((transactionHash) => {
console.log("transactionHash is " + transactionHash);
});
};

// DETECT SENDER

if (state.sender === undefined) {
const accounts = Ethers.send("eth_requestAccounts", []);
if (accounts.length) {
State.update({ sender: accounts[0] });
console.log("set sender", accounts[0]);
}
}

//if (!state.sender) return "Please login first";

// FETCH SENDER BALANCE

if (state.balance === undefined && state.sender) {
Ethers.provider()
.getBalance(state.sender)
.then((balance) => {
State.update({ balance: Big(balance).div(Big(10).pow(18)).toFixed(2) });
});
}

// FETCH SENDER STETH BALANCE

if (state.stakedBalance === undefined && state.sender) {
getStakedBalance(state.sender).then((stakedBalance) => {
State.update({ stakedBalance });
});
}

// FETCH TX COST

if (state.txCost === undefined) {
const gasEstimate = ethers.BigNumber.from(1875000);
const gasPrice = ethers.BigNumber.from(1500000000);

const gasCostInWei = gasEstimate.mul(gasPrice);
const gasCostInEth = ethers.utils.formatEther(gasCostInWei);

let responseGql = fetch(
"https://api.thegraph.com/subgraphs/name/uniswap/uniswap-v2",
{
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
query: `{
bundle(id: "1" ) {
ethPrice
}
}`,
}),
}
);

if (!responseGql) return "";

const ethPriceInUsd = responseGql.body.data.bundle.ethPrice;

const txCost = Number(gasCostInEth) * Number(ethPriceInUsd);

State.update({ txCost: `$${txCost.toFixed(2)}` });
}

// FETCH CSS

const cssFont = fetch(
"https://fonts.googleapis.com/css2?family=Manrope:wght@200;300;400;500;600;700;800"
).body;
const css = fetch(
"https://pluminite.mypinata.cloud/ipfs/Qmboz8aoSvVXLeP5pZbRtNKtDD3kX5D9DEnfMn2ZGSJWtP"
).body;

if (!cssFont || !css) return "";

if (!state.theme) {
State.update({
theme: styled.div`
font-family: Manrope, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
${cssFont}
${css}
`,
});
}
const Theme = state.theme;

// OUTPUT UI

const getSender = () => {
return !state.sender
? ""
: state.sender.substring(0, 6) +
"..." +
state.sender.substring(state.sender.length - 4, state.sender.length);
};

return (
<Theme>
<div className="LidoContainer">
<div className="Header">Stake Ether</div>
<div className="SubHeader">Stake ETH and receive stETH while staking.</div>

<div className="LidoForm">
{state.sender && (
<>
<div className="LidoFormTopContainer">
<div className="LidoFormTopContainerLeft">
<div className="LidoFormTopContainerLeftContent1">
<div className="LidoFormTopContainerLeftContent1Container">
<span>Available to stake</span>
<div className="LidoFormTopContainerLeftContent1Circle" />
</div>
</div>
<div className="LidoFormTopContainerLeftContent2">
<span>
{state.balance ?? (!state.sender ? "0" : "...")}&nbsp;ETH
</span>
</div>
</div>
<div className="LidoFormTopContainerRight">
<div className="LidoFormTopContainerRightContent1">
<div className="LidoFormTopContainerRightContent1Text">
<span>{getSender()}</span>
</div>
</div>
</div>
</div>
<div className="LidoSplitter" />
</>
)}
<div
className={
state.sender ? "LidoFormBottomContainer" : "LidoFormTopContainer"
}
>
<div className="LidoFormTopContainerLeft">
<div className="LidoFormTopContainerLeftContent1">
<div className="LidoFormTopContainerLeftContent1Container">
<span>Staked amount</span>
</div>
</div>
<div className="LidoFormTopContainerLeftContent2">
<span>
{state.stakedBalance ?? (!state.sender ? "0" : "...")}
&nbsp;stETH
</span>
</div>
</div>
<div className="LidoFormTopContainerRight">
<div className="LidoAprContainer">
<div className="LidoAprTitle">Lido APR</div>
<div className="LidoAprValue">{state.lidoArp ?? "..."}%</div>
</div>
</div>
</div>
</div>
<div className="LidoStakeForm">
<div className="LidoStakeFormInputContainer">
<span className="LidoStakeFormInputContainerSpan1">
<svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor">
<path
opacity="0.6"
d="M11.999 3.75v6.098l5.248 2.303-5.248-8.401z"
></path>
<path d="M11.999 3.75L6.75 12.151l5.249-2.303V3.75z"></path>
<path
opacity="0.6"
d="M11.999 16.103v4.143l5.251-7.135L12 16.103z"
></path>
<path d="M11.999 20.246v-4.144L6.75 13.111l5.249 7.135z"></path>
<path
opacity="0.2"
d="M11.999 15.144l5.248-2.993-5.248-2.301v5.294z"
></path>
<path
opacity="0.6"
d="M6.75 12.151l5.249 2.993V9.85l-5.249 2.3z"
></path>
</svg>
</span>
<span className="LidoStakeFormInputContainerSpan2">
<input
disabled={!state.sender}
className="LidoStakeFormInputContainerSpan2Input"
value={state.strEther}
onChange={(e) => State.update({ strEther: e.target.value })}
placeholder="Amount"
/>
</span>
<span
className="LidoStakeFormInputContainerSpan3"
onClick={() => {
State.update({
strEther: (state.balance > 0.05
? parseFloat(state.balance) - 0.05
: 0
).toFixed(2),
});
}}
>
<button
className="LidoStakeFormInputContainerSpan3Content"
disabled={!state.sender}
>
<span className="LidoStakeFormInputContainerSpan3Max">MAX</span>
</button>
</span>
</div>
{!!state.sender ? (
<button
className="LidoStakeFormSubmitContainer"
onClick={() => submitEthers(state.strEther, state.sender)}
>
<span>Submit</span>
</button>
) : (
<Web3Connect
className="LidoStakeFormSubmitContainer"
connectLabel="Connect with Web3"
/>
)}

<div className="LidoFooterContainer">
{state.sender && (
<div className="LidoFooterRaw">
<div className="LidoFooterRawLeft">You will receive</div>
<div className="LidoFooterRawRight">${state.strEther ?? 0} stETH</div>
</div>
)}
<div className="LidoFooterRaw">
<div className="LidoFooterRawLeft">Exchange rate</div>
<div className="LidoFooterRawRight">1 ETH = 1 stETH</div>
</div>
{false && (
<div className="LidoFooterRaw">
<div className="LidoFooterRawLeft">Transaction cost</div>
<div className="LidoFooterRawRight">{state.txCost}</div>
</div>
)}
<div className="LidoFooterRaw">
<div className="LidoFooterRawLeft">Reward fee</div>
<div className="LidoFooterRawRight">10%</div>
</div>
</div>
</div>
</div>
</Theme>
);

Próximos Pasos:

Ahora que tienes una comprensión básica de los Componentes NEAR, es hora de dar el siguiente paso. Puedes Construir y desplegar tus primeros componentes sin salir del navegador. Visita https://near.org/sandbox, crea una cuenta para comenzar. Necesitarás una billetera NEAR, crea la tuya siguiendo esta guía

Lo que necesitas:

Herramientas Web

Para comenzar rápidamente a construir Componentes, puedes utilizar una de las herramientas en línea disponibles. Son ideales para dar tus primeros pasos y te permiten encontrar otros desarrolladores y componentes en el ecosistema NEAR.

  • NEAR Sandbox: El sitio web de NEAR contiene su propio editor de sandbox. El sandbox te permite codificar, previsualizar y desplegar tus componentes directamente desde tu navegador.
  • Jutsu.ai: Jutsu.ai es un IDE web diseñado para desarrolladores de NEAR. Contiene ejemplos y tutoriales para ayudarte en el proceso de integración.

Herramientas Locales

Si deseas colaborar con un equipo o trabajar en un proyecto más grande, es probable que desees más control de versiones, pruebas y despliegue automatizados, y otros flujos de trabajo. Para esto, el ecosistema NEAR ofrece un conjunto de herramientas para desarrollar y probar fácilmente tus componentes de forma completamente local.

  • Extensión NEAR para VSCode: La extensión NEAR para VSCode se integra con el IDE de VSCode para ayudarte a desarrollar, previsualizar y desplegar componentes todo dentro de VSCode.
  • BOS Loader: Una herramienta CLI para previsualizar componentes locales en NEAR BOS. Un compañero perfecto para el BOS CLI.
  • BOS CLI: Una utilidad de línea de comandos que simplifica el desarrollo local de componentes para NEAR BOS.
  • BOS Workspace: Un conjunto completo de herramientas para simplificar el desarrollo local de componentes y aplicaciones NEAR, con soporte de recarga en caliente, soporte de TypeScript, gestión de múltiples aplicaciones y una puerta de enlace local.
  • Além: Una biblioteca JavaScript/TypeScript web3 para crear aplicaciones web3 para Near BOS. Es fácil de usar para los desarrolladores y utiliza patrones de React, lo que facilita la organización de archivos y la escritura de código. Accede a la documentación de Além para obtener más información.

Los Componentes representan una emocionante evolución en el desarrollo web hacia la descentralización y la innovación. Con su capacidad para interactuar nativamente con la blockchain NEAR, ofrecen un camino hacia un futuro más inclusivo y transparente en la web.

A medida que exploramos este emocionante viaje, es fundamental recordar que este artículo es solo el comienzo.

Estén atentos a futuras publicaciones donde exploraremos más a fondo los componentes específicos y cómo interactúan con los contratos de NEAR. ¡Prepárense para descubrir un mundo de posibilidades en la Web 3.0 con NEAR Protocol liderando el camino hacia una nueva era de Internet!

Sigue las cuentas de NEAR Es en Español

X (Twitter) oficial de NEAR_ES

Canal YouTube: NEAR_ES

NEAR Social: NEAR_ES

Telegram oficial de NEAR_ES

--

--

NEAR_ES
NEAR_ES

Written by NEAR_ES

Espacio informativo y educativo sobre NEAR Protocol, Aurora, web3 y blockchain en Español para toda la comunidad

No responses yet