Saltar al contenido principal

Instalar y desplegar un contrato inteligente con código

Esta guía te guiará a través del proceso de instalar y desplegar un contrato inteligente usando js-stellar-sdk. Cubriremos la configuración de un contrato Rust de ejemplo, crear un proyecto Node.js para gestionar el despliegue, y finalmente, instalar el Wasm del contrato y desplegarlo en la red

Requisitos previos

Antes de comenzar, asegúrate de tener lo siguiente instalado:

  1. Rust y Cargo (para compilar contratos inteligentes)
  2. Node.js y npm (para ejecutar scripts de despliegue en JavaScript)
  3. Soroban CLI

Inicializar un contrato Rust de ejemplo

soroban contract init hello-world
cd hello-world
soroban contract build

Esta secuencia de comandos crea un nuevo directorio para tu proyecto, inicializa un nuevo contrato inteligente Soroban dentro de ese directorio y desarrolla el contrato. El desarrollo genera un archivo .wasm en la ruta hello-word/target/wasm32-unknown-unknown/release/hello_world.wasm

Crear un Proyecto Node

  1. Crea un nuevo directorio para tu proyecto Node.js y navega a él:
mkdir deploy-contract
cd deploy-contract
  1. Inicializa un nuevo proyecto Node.js e instala las dependencias necesarias:
npm init -y
npm install @stellar/stellar-sdk fs

Configurar Scripts de Despliegue

Importaciones

Importa los módulos necesarios en tu archivo JavaScript:

import * as StellarSDK from "@stellar/stellar-sdk";
import fs from "fs";

Instalando el Wasm en la red

Crea una función para subir el archivo Wasm compilado:

async function uploadWasm(filePath) {
const bytecode = fs.readFileSync(filePath);
const account = await server.getAccount(sourceKeypair.publicKey());
const operation = StellarSDK.Operation.uploadContractWasm({ wasm: bytecode });
return await buildAndSendTransaction(account, operation);
}

Esta función lee el archivo Wasm compilado, recupera los detalles de la cuenta de la red e instala el bytecode usando la operación Stellar uploadContractWasm, que cuando se envuelve en una transacción se envía a la red.

Desplegar contrato

Despliega el contrato haciendo referencia al hash del Wasm:

async function deployContract(response) {
const account = await server.getAccount(sourceKeypair.publicKey());
const operation = StellarSDK.Operation.createCustomContract({
wasmHash: response.returnValue.bytes(),
address: StellarSDK.Address.fromString(sourceKeypair.publicKey()),
salt: response.hash,
});
const responseDeploy = await buildAndSendTransaction(account, operation);
const contractAddress = StellarSDK.StrKey.encodeContract(
StellarSDK.Address.fromScAddress(
responseDeploy.returnValue.address(),
).toBuffer(),
);
console.log(contractAddress);
}

Esta función utiliza el hash del Wasm para desplegar el contrato usando la operación stellar createCustomContract, que cuando se envuelve en una transacción se envía a la red, generando una dirección de contrato.

Construyendo, Firmando y Enviando la Transacción

Gestionar la construcción, firma y envío de transacciones:

async function buildAndSendTransaction(account, operations) {
const transaction = new StellarSDK.TransactionBuilder(account, {
fee: StellarSDK.BASE_FEE,
networkPassphrase: StellarSDK.Networks.TESTNET,
})
.addOperation(operations)
.setTimeout(30)
.build();

const tx = await server.prepareTransaction(transaction);
tx.sign(sourceKeypair);

console.log("Submitting transaction...");
let response = await server.sendTransaction(tx);
const hash = response.hash;
console.log(`Transaction hash: ${hash}`);
console.log("Awaiting confirmation...");

while (true) {
response = await server.getTransaction(hash);
if (response.status !== "NOT_FOUND") {
break;
}
await new Promise((resolve) => setTimeout(resolve, 1000));
}

if (response.status === "SUCCESS") {
console.log("Transaction successful.");
return response;
} else {
console.log("Transaction failed.");
throw new Error("Transaction failed");
}
}

Esta función construye una transacción, la firma y la envía a la red, gestionando cualquier reintento necesario para la confirmación de la transacción.

Ejecutando el Script

Ejecuta el script de despliegue:

const server = new StellarSDK.SorobanRpc.Server(
"https://soroban-testnet.stellar.org:443",
);
const sourceKeypair = StellarSDK.Keypair.fromSecret("Your_Secret_Key");
const wasmFilePath =
"../hello-world/target/wasm32-unknown-unknown/release/hello_world.wasm"; // Adjust this path as necessary

try {
let uploadResponse = await uploadWasm(wasmFilePath);
await deployContract(uploadResponse);
} catch (error) {
console.error(error);
}

Reemplaza "Your_Secret_Key" con tu clave secreta real. Este script inicia la subida del archivo Wasm y despliega el contrato, resultando en una dirección de contrato donde el contrato está desplegado.

Este es solo un código de demostración, así que asegúrate de manejar secretos y claves privadas de forma segura en entornos de producción y nunca las expongas en tus repositorios de código. Esta guía debería proporcionarte un camino claro para instalar y desplegar tus contratos inteligentes usando código Javascript.

Script Completo

Aquí están todos los fragmentos apilados juntos en un solo archivo para conveniencia:

import * as StellarSDK from "@stellar/stellar-sdk";
import fs from "fs";
async function uploadWasm(filePath) {
const bytecode = fs.readFileSync(filePath);
const account = await server.getAccount(sourceKeypair.publicKey());
const operation = StellarSDK.Operation.uploadContractWasm({ wasm: bytecode });
return await buildAndSendTransaction(account, operation);
}
async function deployContract(response) {
const account = await server.getAccount(sourceKeypair.publicKey());
const operation = StellarSDK.Operation.createCustomContract({
wasmHash: response.returnValue.bytes(),
address: StellarSDK.Address.fromString(sourceKeypair.publicKey()),
salt: response.hash,
});
const responseDeploy = await buildAndSendTransaction(account, operation);
const contractAddress = StellarSDK.StrKey.encodeContract(
StellarSDK.Address.fromScAddress(
responseDeploy.returnValue.address(),
).toBuffer(),
);
console.log(contractAddress);
}
async function buildAndSendTransaction(account, operations) {
const transaction = new StellarSDK.TransactionBuilder(account, {
fee: StellarSDK.BASE_FEE,
networkPassphrase: StellarSDK.Networks.TESTNET,
})
.addOperation(operations)
.setTimeout(30)
.build();

const tx = await server.prepareTransaction(transaction);
tx.sign(sourceKeypair);

console.log("Submitting transaction...");
let response = await server.sendTransaction(tx);
const hash = response.hash;
console.log(`Transaction hash: ${hash}`);
console.log("Awaiting confirmation...");

while (true) {
response = await server.getTransaction(hash);
if (response.status !== "NOT_FOUND") {
break;
}
await new Promise((resolve) => setTimeout(resolve, 1000));
}

if (response.status === "SUCCESS") {
console.log("Transaction successful.");
return response;
} else {
console.log("Transaction failed.");
throw new Error("Transaction failed");
}
}

const server = new StellarSDK.SorobanRpc.Server(
"https://soroban-testnet.stellar.org:443",
);
const sourceKeypair = StellarSDK.Keypair.fromSecret("Your_Secret_Key");
const wasmFilePath =
"../hello-world/target/wasm32-unknown-unknown/release/hello_world.wasm"; // Adjust this path as necessary

try {
let uploadResponse = await uploadWasm(wasmFilePath);
await deployContract(uploadResponse);
} catch (error) {
console.error(error);
}