Aviso legal : Esta publicación es una traducción realizada por un miembro de la Comunidad Fuel. Se realizan cuidadosos controles para garantizar la exactitud de las traducciones, pero éstas pueden contener errores u omisiones. Fuel Labs no se hace responsable de la exactitud, fiabilidad o actualidad de la información traducida. Enlace a la publicación original: Building a Frontend to interact With your Contract.
Para poder construir nuestro frontend seguiremos los siguientes pasos:
Instalar la wallet de fuel en nuestro navegador.
Inicializar un proyecto en React.
Instalar the fuels SDK dependency.
Escribir el código de nuestro frontend.
Ejecutar nuestro proyecto.
Verifica que tu navegador este usando la ultima version de chromium
Nuestro frontend necesitara interactuar con la red de fuel y para que esto sea posible debemos tener instalada la wallet de fuel en nuestro navegador.
Entonces antes de empezar instala la Wallet de fuel aquÃ.
Si ya tenias la wallet de fuel instalada verifica que este actualizada a la ultima version.
Ahora que ya tienes la wallet de fuel instalada toma tu dirección y obtén monedas en el beta-4 faucet.
Primero dividamos nuestro contrato del frontend, asumiendo que estamos en la carpeta de nuestros contratos retrocederemos al directorio principal de nuestro proyecto.
cd ..
Ahora inicialicemos nuestro proyecto de react usando el create react app
npx create-react-app frontend --template typescript
El resultado debe de ser similar a esto.
Success! Created frontend at Fuel/fuel-project/frontend
Ahora nuestra carpeta inicial debe de tener dos carpetas, fuel-project, tendrá dos carpetas, counter-contract y frontend.
El paquete fuels umbrella
incluye todas las herramientas principales que necesitaremos para nuestro frontend; wallet, contracts, providers, y mas.
Tambien, contiene las rutinas para la generación de Typescript ABI.
Primero entremos a nuestra carpeta frontend.
cd frontend
Empecemos instalando fuels y @fuel-wallet/sdk
npm install fuels@0.60.0 @fuel-wallet/sdk@0.13.0 --save
Si la instalación finalizó exitosamente el resultado debe ser similar a esto:
added 114 packages, and audited 115 packages in 9s
Ahora debemos actualizar la configuración de nuestro tsconfig.json
y añadir el fuel wallet type.
{
"compilerOptions": {
"types": ["@fuel-wallet/sdk"]
}
}
Para facilitar la interacción con nuestros contratos debemos usar el comando fuels typegen
, para poder interpretar la salida ABI JSON de nuestro contrato, y generar las definiciones de typescript basadas en el. Este JSON se creo cuando ejecutamos el forc build
para compilar los contratos en sway.
Si vemos la carpeta fuel-project/counter-contract/out
el ABI JSON estará allÃ. Si quieres aprender mas acerca de esto, lee el ABI spec.
Dentro del directorio fuel-project/frontend
debemos ejecutar:
npx fuels typegen -i ../counter-contract/out/debug/*-abi.json -o ./src/contracts
Si el proceso culmino con éxito la salida debe ser similar a esto:
Generating files..
- src/contracts/CounterContractAbi.d.ts
- src/contracts/factories/CounterContractAbi__factory.ts
- src/contracts/index.ts
Done.âš¡
Ahora deberÃamos poder encontrar la siguiente carpeta fuel-project/frontend/src/contracts
. Esta carpeta fue auto-generada con el fuel typegen command
, y estos archivos abstraen el trabajo que tendrÃamos que hacer para crear una instancia de contrato, y generar una interfaz completa en Typescript del contrato, haciendo mas fácil el desarrollo.
Dentro de la carpeta frontend/src
añadiremos el código que va interactuar con nuestro contrato. Modifiquemos el archivo fuel-project/frontend/src/App.tsx
a esto:
import { useEffect, useState } from "react";
import "./App.css";
// Import the contract factory -- you can find the name in index.ts.
// You can also do command + space and the compiler will suggest the correct name.
import { CounterContractAbi__factory } from "./contracts";
// The address of the contract deployed the Fuel testnet
const CONTRACT_ID =
"0x...";
function App() {
const [connected, setConnected] = useState<boolean>(false);
const [account, setAccount] = useState<string>("");
const [counter, setCounter] = useState<number>(0);
const [loaded, setLoaded] = useState(false);
useEffect(() => {
setTimeout(() => {
checkConnection();
setLoaded(true);
}, 200)
if (connected) getCount();
}, [connected])
async function connect() {
if (window.fuel) {
try {
await window.fuel.connect();
const [account] = await window.fuel.accounts();
setAccount(account);
setConnected(true);
} catch (err) {
console.log("error connecting: ", err);
}
}
}
async function checkConnection() {
if (window.fuel) {
const isConnected = await window.fuel.isConnected();
if (isConnected) {
const [account] = await window.fuel.accounts();
setAccount(account);
setConnected(true);
}
}
}
async function getCount() {
if (window.fuel) {
const wallet = await window.fuel.getWallet(account);
const contract = CounterContractAbi__factory.connect(CONTRACT_ID, wallet);
const { value } = await contract.functions.count().simulate();
setCounter(value.toNumber());
}
}
async function increment() {
if (window.fuel) {
const wallet = await window.fuel.getWallet(account);
const contract = CounterContractAbi__factory.connect(CONTRACT_ID, wallet);
// Creates a transactions to call the increment function
// because it creates a TX and updates the contract state this requires the wallet to have enough coins to cover the costs and also to sign the Transaction
try {
await contract.functions.increment().txParams({ gasPrice: 1 }).call();
getCount();
} catch (err) {
console.log("error sending transaction...", err);
}
}
}
if (!loaded) return null
return (
<>
<div className="App">
{
connected ? (
<>
<h3>Counter: {counter}</h3>
<button style={buttonStyle} onClick={increment}>
Increment
</button>
</>
) : (
<button style={buttonStyle} onClick={connect}>Connect</button>
)
}
</div>
</>
);
}
export default App;
const buttonStyle = {
borderRadius: "48px",
marginTop: "10px",
backgroundColor: "#03ffc8",
fontSize: "20px",
fontWeight: "600",
color: "rgba(0, 0, 0, .88)",
border: "none",
outline: "none",
height: "60px",
width: "400px",
cursor: "pointer"
}
Finalmente, remplazaremos el valor de la variable CONTRACT ID que esta en el inicio de App.tsx por el Address del contrato que desplegamos.
Dentro del directorio fuel-project/frontend
ejecutaremos:
npm start
Compiled successfully!
You can now view frontend in the browser.
Local: http://localhost:3000
On Your Network: http://192.168.4.48:3000
Note that the development build is not optimized.
To create a production build, use npm run build.
Aquà esta el repo del proyecto, si lo ejecutaste y tuviste problemas un buen primer paso es comparar tu código con el del repo y resolver las diferencias que tengas.
Twitteanos y haznos saber que construiste una dapp en fuel, podrÃas ser invitado a un grupo de builders privado, ser invitado a la próxima cena de fuel, o algo 👀.
Si haces cambios a tu contrato, aquà están los pasos que debes tomar para que tu frontend y tu contrato estén sincronizados.
Ejecuta forc build
en el directorio de tu contrato.
En el directorio de tu contrato, vuelve a desplegar tu contrato ejecutando este comando y siguiendo los mismos pasos anteriores para firmar la transacción con tu wallet: forc deploy --testnet
En el directorio de tu frontend, vuelve a ejecutar este comando: npx fuels typegen -i ../counter-contract/out/debug/*-abi.json -o ./src/contracts
En tu directorio fuel-project/frontend, actualiza el CONTRACT ID en el archivo App.tsx
Hasta la próxima, good coding 🫡.