Aptos Move dApp
En esta guía, aprenderemos cómo crear una dApp "onchain bio" de extremo a extremo. Comenzaremos con el contrato Move. Luego, construiremos una interfaz de React y permitiremos que las billeteras se conecten y registren una biografía.
Requisitos
Asegúrese de tener instalado Movement CLI . Si utiliza Aptos CLI, consulte nuestra guía sobre cómo configurar Aptos CLI para Movement .
Vea un ejemplo de la dApp terminada aquí .
Configuración
Cree un nuevo directorio y navegue hasta él:
Copiar
mkdir my-onchain-bio && cd my-onchain-bio
Abra un editor de código para que pueda ver la estructura de archivos de su dApp. Aquí usaremos VS Code:
Copiar
code .
Creación y publicación del contrato inteligente Onchain Bio
Ahora que nuestro entorno está configurado, escribamos algo de código, ¡comenzando con el contrato Move!
Primero, cree un move
directorio y navegue hasta él:
Copiar
mkdir move && cd move
Luego cree un move
proyecto que contenga código para un paquete en cadena:
Copiar
movement aptos move init --name my_todo_list
Su estructura de archivos ahora debería verse así:

Creando un módulo
Cree un nuevo archivo nombrado onchain_bio.move
dentro del sources
directorio y agregue lo siguiente a ese archivo:
Escribiendo nuestro módulo biológico en cadena
Aquí está el módulo Bio Move completo en cadena:
Copiar
module onchain_bio_addr::onchain_bio {
use std::string::{String};
use std::signer;
struct Bio has key, store, drop {
name: String,
bio: String,
}
public entry fun register(account: &signer, name: String, bio: String) acquires Bio {
// Check if an Bio already exists for the account
if (exists<Bio>(signer::address_of(account))) {
// Remove the existing Bio
let _old_Bio = move_from<Bio>(signer::address_of(account));
};
// Create the new Bio
let bio = Bio {
name,
bio,
};
// Store the new Bio under the account
move_to<Bio>(account, bio);
}
}
¡A continuación, implementemos en M1!
Implementación del módulo en la cadena de bloques M1 de Movement
Primero, desde dentro del move
directorio, inicialice su configuración de Movement Aptos:
Copiar
movement aptos init
Cuando se le solicite elegir una red, ingrese custom
.
Luego ingrese el siguiente punto final REST:
Copiar
https://aptos.devnet.m1.movementlabs.xyz
Y la misma URL para el punto final del faucet.
Cuando se le solicite una clave privada, presione Entrar para generar un nuevo par de claves.
Tras una inicialización exitosa, verá el mensaje de éxito (con la dirección de su cuenta en lugar de 0x39883cbc29500a8bf79911ea1469e1c3b58104547a88fb0fbdf17470f80b2a91)
:
Copiar
No key given, generating key...
Account 0x39883cbc29500a8bf79911ea1469e1c3b58104547a88fb0fbdf17470f80b2a91 doesn't exist, creating it and funding it with 100000000 Octas
Account 0x39883cbc29500a8bf79911ea1469e1c3b58104547a88fb0fbdf17470f80b2a91 funded successfully
---
Aptos CLI is now set up for account 0x39883cbc29500a8bf79911ea1469e1c3b58104547a88fb0fbdf17470f80b2a91 as profile default! Run `aptos --help` for more information about commands
{
"Result": "Success"
}
Ahora su move
directorio contendrá una .aptos
carpeta oculta que contiene un config.yaml
archivo. Puede ver el contenido de ese archivo para ver sus claves públicas y privadas.
En la línea debajo [addresses]
de Move.toml
, agregue la dirección de su cuenta:
Copiar
onchain_bio_addr = "<your-account-address>"
Después de compilar, verá un mensaje de resultado con el formato siguiente:
Copiar
{
"Result": [
"39883cbc29500a8bf79911ea1469e1c3b58104547a88fb0fbdf17470f80b2a91::onchain_bio"
]
}
Ahora puedes publicar el paquete:
Copiar
movement aptos move publish
Después de confirmar que el precio está bien, su transacción se enviará a la cadena de bloques.
Obtendrá un resultado con el formato siguiente, con valores asociados a su transacción:
Copiar
{
"Result": {
"transaction_hash": "0x37ea722ad4f1ff0d8d0710965a47354cc903579d38b659d90c4286ddab946151",
"gas_used": 1236,
"gas_unit_price": 100,
"sender": "39883cbc29500a8bf79911ea1469e1c3b58104547a88fb0fbdf17470f80b2a91",
"sequence_number": 0,
"success": true,
"timestamp_us": 1707748417269022,
"version": 248,
"vm_status": "Executed successfully"
}
}
¡Felicidades! Su módulo ahora está implementado.
Pasemos al frente.
Creación de una aplicación React para que los usuarios se registren y vean su biografía en cadena
Navegue a la raíz de nuestro directorio de proyectos:
Copiar
cd ..
Crea una nueva aplicación React llamada client
:
Copiar
npx create-react-app client --template typescript
En la raíz de su proyecto, tendrá dos directorios: client
y move
.
cd
en el client
directorio y ejecute npm start
.
Su aplicación ahora debería ejecutarse en http://localhost:3000 y mostrar el diseño predeterminado de React.
Los archivos de sus aplicaciones están en el client/src
directorio.
Reemplace el código Index.tsx
con lo siguiente:
Copiar
import { PetraWallet } from "petra-plugin-wallet-adapter";
import { AptosWalletAdapterProvider } from "@aptos-labs/wallet-adapter-react";
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
import reportWebVitals from "./reportWebVitals";
import './index.css';
const wallets = [new PetraWallet()];
const root = ReactDOM.createRoot(document.getElementById("root") as HTMLElement);
root.render(
<React.StrictMode>
<AptosWalletAdapterProvider plugins={wallets} autoConnect={true}>
<App />
</AptosWalletAdapterProvider>
</React.StrictMode>,
);
reportWebVitals();
Esto envuelve nuestra aplicación en la <AptosWalletAdapterProvider />
etiqueta para que podamos conectar una billetera. Para agregar soporte para más billeteras, consulte el archivo README del Adaptador de billetera Aptos .
Ahora reemplace su App.tsx
código con lo siguiente:
Copiar
import { WalletSelector } from "@aptos-labs/wallet-adapter-ant-design";
import "@aptos-labs/wallet-adapter-ant-design/dist/index.css";
import { useRef, useState, useEffect } from "react";
import { useWallet, InputTransactionData } from '@aptos-labs/wallet-adapter-react';
import { Aptos, AptosConfig, Network } from "@aptos-labs/ts-sdk";
import { ONCHAIN_BIO } from "./constants";
import './index.css';
// with custom configuration
const aptosConfig = new AptosConfig({ network: Network.CUSTOM });
const aptos = new Aptos(aptosConfig);
function App() {
const { signAndSubmitTransaction, account } = useWallet();
const name = useRef<HTMLInputElement>(null);
const bio = useRef<HTMLTextAreaElement>(null);
const [accountHasBio, setAccountHasBio] = useState(false);
const [currentName, setCurrentName] = useState(null);
const [currentBio, setCurrentBio] = useState(null);
const fetchBio = async () => {
if (!account) {
console.log("No account")
return [];
}
try {
const bioResource = await aptos.getAccountResource(
{
accountAddress:account?.address,
resourceType:`${ONCHAIN_BIO}::onchain_bio::Bio`
}
);
console.log("Name:", bioResource.name, "Bio:", bioResource.bio);
setAccountHasBio(true);
if (bioResource) {
setCurrentName(bioResource.name);
setCurrentBio(bioResource.bio);
} else {
console.log("no bio")
}
} catch (e: any) {
setAccountHasBio(false);
}
};
async function registerBio() {
if (bio.current !== null && name.current !== null) {
const onchainName = name.current.value;
const onchainBio = bio.current.value;
const transaction: InputTransactionData = {
data: {
function:`${ONCHAIN_BIO}::onchain_bio::register`,
functionArguments:[onchainName, onchainBio]
}
}
try {
// sign and submit transaction to chain
const response = await signAndSubmitTransaction(transaction);
// wait for transaction
console.log(`Success! View your transaction at https://explorer.aptoslabs.com/txn/${response.hash}`)
await aptos.waitForTransaction({transactionHash:response.hash});
fetchBio();
} catch (error: any) {
console.log("Error:", error)
}
}
}
return (
<>
<div className="navbar">
<div className="navbar-text">Your Onchain Bio</div>
<div>
<WalletSelector />
</div>
</div>
<div className="center-container">
<div className="row">
<h1>You Onchain Bio</h1>
</div>
<div className="row">
<h3>Your name:</h3>
</div>
<div className="row">
<input ref={name} type="text" className="name" placeholder="Enter your name"/>
</div>
<div className="row">
<h3>Your Bio:</h3>
</div>
<div className="row">
<textarea ref={bio} className="bio" placeholder="Your onchain bio"
/>
</div>
<div className="row">
<button onClick={registerBio}>Register Bio</button>
</div>
<div className="row">
<button onClick={fetchBio}>Fetch Bio</button>
</div>
<div className="row">
<center>
<h3>Your Name:</h3>
<p>{currentName}</p>
</center>
</div>
<div className="row">
<center>
<h3>Your Bio:</h3>
<p>{currentBio}</p>
</center>
</div>
</div>
</>
);
}
export default App;
Por último, reemplace el código en index.css
:
Copiar
:root {
font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
line-height: 1.5;
font-weight: 400;
font-synthesis: none;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
-webkit-text-size-adjust: 100%;
}
body {
margin: 0;
}
h1, h3 {
margin-bottom: 5px;
}
h3 {
margin-top: 0;
}
.navbar {
display: flex;
justify-content: space-between;
align-items: center;
background-color: #333;
color: #fff;
padding: 10px 20px;
}
.navbar-text {
font-size: 20px;
}
.center-container {
display: flex;
flex-direction: column;
align-items: center;
height: 100vh; /* Adjust this to control vertical centering */
}
.row {
display: flex;
justify-content: center;
}
.name {
margin-bottom: 10px;
width: 200px;
}
.bio {
margin-bottom: 10px;
width: 300px;
height: 200px;
resize: vertical;
}
Su aplicación que se ejecuta localmente ahora debería verse así:

Siéntete libre de diseñar la aplicación como prefieras.
Usando tu aplicación
Para usar la dApp, primero configure una billetera Aptos en M1.
Dirígete a Movement Faucet y deposita fondos en tu billetera M1 devnet. Ingrese un nombre y biografía. Haga clic en el botón Registrar biografía. La billetera debería aparecer para que la firmes. Después de que la transacción se haya enviado a la cadena de bloques, verá actualizada su información biográfica en la cadena:

¿Qué dApps desarrollarás en Movement?
Ahora ya sabe cómo implementar una dApp Aptos para M1.
Compruebe onchain_bio.move
la lógica, intente una redistribución modificándola. Como desafío, intenta modificar el Front End para mostrar mejor tu nombre y biografía.
¡Estamos ansiosos por ver qué dApps creas e implementas en Movement Network!
Last updated