Saltar al contenido principal

Desplegar Smart Contracts (TypeScript)

Esta guía muestra los pasos principales para desplegar un smart contract ULVM usando el SDK de TypeScript de ULedger.

Vas a:

  1. Inicializar el SDK
  2. Cargar o generar un wallet (el firmante)
  3. Leer tu contrato compilado (.wat o .wasm)
  4. Crear una sesión de transaction hacia un node
  5. Enviar una transaction DEPLOY_SMART_CONTRACT
info

En muchas chains, tu wallet debe estar registrado on-chain antes de poder desplegar contratos. Si obtienes REJECTED_BY_UNAUTHORIZED, registra el wallet primero (consulta la nota en el Paso 5).


1. Requisitos previos

Necesitas:

  • nodeEndpoint (ejemplo: http://localhost:8080)
  • blockchainId
  • Un wallet que pueda firmar transactions
  • El archivo fuente de tu contrato:
    • auction.wat (texto), o
    • auction.wasm (binario — la codificación depende de las reglas del node)

2. Inicializar el SDK y cargar un wallet

import { getULedgerSDK, KeyType } from "@uledgerinc/typescript-sdk";

const sdk = await getULedgerSDK();

// Opción A: generar un nuevo wallet
const wallet = sdk.generateWallet({ keyType: KeyType.Secp256k1 });

// Opción B: restaurar desde mnemonic / JSON (ejemplos)
// const wallet = sdk.walletFromMnemonic(mnemonic, { keyType: KeyType.Secp256k1 });
// const wallet = sdk.walletFromJson(walletJsonString);

3. Leer el código fuente del contrato

Opción A: Desplegar un archivo .wat (texto)

import { readFile } from "node:fs/promises";

const wat = await readFile("./auction.wat", "utf8");
const contractSource = wat;

Opción B: Desplegar un archivo .wasm (binario)

Tu node puede esperar bytes sin procesar, hex o base64. Un enfoque común es base64:

import { readFile } from "node:fs/promises";

const wasmBytes = await readFile("./auction.wasm");
const contractSource = Buffer.from(wasmBytes).toString("base64");

Usa el formato que tu node espera para DEPLOY_SMART_CONTRACT.


4. Elegir una dirección de contrato (esto va en to)

En el SDK de TS, deployContract requiere un contractAddress, que se convierte en el to de la transaction.

Aquí hay un helper simple que genera una cadena hex aleatoria de 32 bytes:

import { randomBytes } from "node:crypto";

function randomHex32(): string {
return randomBytes(32).toString("hex"); // 64 caracteres hex
}

const contractAddress = randomHex32();

5. Crear una sesión de transaction (se conecta al node)

Esta llamada inicializa la sesión (obtiene /health para conseguir el nodeId y verifica /blockchains):

const nodeEndpoint = "http://localhost:8080";
const session = await sdk.createSession(nodeEndpoint, wallet);

6. Desplegar el contrato

import { TransactionType } from "@uledgerinc/typescript-sdk";

const tx = await session.deployContract({
blockchainId,
sourceCode: contractSource,
contractAddress,
});

console.log("Deploy TX ID:", tx.transactionId);
console.log("Status:", tx.status);
console.log("Output:", tx.output);
console.log("Contract Address (to):", contractAddress);

Qué ocurre internamente (caso de despliegue)

TransactionSession.deployContract(...) delega en submitTransaction(...), que:

  • Construye un input de transaction con:

    • to = contractAddress
    • from = wallet.address (el despliegue no es una tx de creación de wallet)
    • payload = sourceCode
    • payloadType = TransactionType.DeploySmartContract
    • suggestor = nodeId (desde /health)
  • Firma el input de la transaction mediante el backend WASM

  • Hace POST a: POST {nodeEndpoint}/blockchains/{blockchainId}/transactions


7. Siguiente paso: Invocar el contrato

Para llamar al contrato desplegado, envía una transaction INVOKE_SMART_CONTRACT.

Continúa en: Invocar Smart Contracts (TS) (siguiente guía).


---

## Invocar Smart Contracts (TypeScript)

```mdx
---
id: invoke-smart-contract-ts
title: Invoca un Smart Contract con el SDK de TypeScript
sidebar_label: Invocar Smart Contract (TS)
sidebar_position: 5
---

# Invocar un Smart Contract (TypeScript)

Esta guía muestra la **lógica principal** para invocar una función de un smart contract ULVM usando el SDK de TypeScript.

✅ Objetivo: crear una transaction `INVOKE_SMART_CONTRACT` donde:

- `to` = la **dirección del contrato**
- payload = JSON `{ functionName, args, gasLimit }`
- los args se proporcionan como `string` o `Uint8Array`

---

## 1) Lo que necesitas antes de invocar

Necesitas:

1. Un wallet que pueda enviar txs en tu chain.
2. Una **dirección de contrato** desplegada (el mismo `contractAddress` que pasaste durante el despliegue).
3. `nodeEndpoint` y `blockchainId`.

:::info
La **dirección del contrato no es el transactionId del despliegue** en este SDK.
Usa el `contractAddress` que elegiste en el momento del despliegue (el `to` de la transaction).
:::

---

## 2) Inicializar el SDK y el wallet (ejemplo)

```ts
import { getULedgerSDK, KeyType } from "@uledgerinc/typescript-sdk";

const sdk = await getULedgerSDK();

// Ejemplo mínimo: generar un wallet
const wallet = sdk.generateWallet({ keyType: KeyType.Secp256k1 });

// O restaurar:
// const wallet = sdk.walletFromMnemonic(mnemonic, { keyType: KeyType.Secp256k1 });
// const wallet = sdk.walletFromJson(walletJsonString);

3) Crear una sesión

const nodeEndpoint = "http://localhost:8080";
const session = await sdk.createSession(nodeEndpoint, wallet);

4) Invocar una función del contrato

La sesión de TS expone:

invokeContract(options: {
blockchainId: string;
contractAddress: string;
functionName: string;
args?: Array<string | Uint8Array>;
gasLimit?: number;
}): Promise<ULTransaction>

Ejemplo A — llamar a testStoreAndRetrieve(...)

Si tu contrato acepta args de tipo string (o parsea strings), puedes pasar "123":

const tx = await session.invokeContract({
blockchainId,
contractAddress,
functionName: "testStoreAndRetrieve",
args: ["123"],
gasLimit: 100000,
});

console.log("Invoke TX ID:", tx.transactionId);
console.log("Status:", tx.status, "| Output:", tx.output);

Ejemplo B — llamar a testStoreAndRetrieveArray() (sin args)

const tx = await session.invokeContract({
blockchainId,
contractAddress,
functionName: "testStoreAndRetrieveArray",
args: [],
gasLimit: 100000,
});

console.log("Invoke TX ID:", tx.transactionId);
console.log("Status:", tx.status, "| Output:", tx.output);

5) Notas y errores comunes

El nombre de función debe coincidir exactamente

functionName debe coincidir exactamente con el nombre de la función ULVM exportada.

contractAddress debe ser correcto

Para llamadas a contratos:

  • contractAddress = la misma dirección usada en el momento del despliegue
  • firmante = tu wallet en la sesión

Los args deben coincidir con lo que el contrato espera

En el SDK de TS:

  • args puede ser string o Uint8Array
  • Usa Uint8Array cuando tu contrato espera argumentos binarios codificados por la VM

Si tu contrato espera codificación binaria con tipos fuertes (por ejemplo, i32 codificado para la VM), proporciona un Uint8Array producido por tus utilidades de serialización de contratos (documentadas por separado).

Valores predeterminados del gas limit

Si omites gasLimit, la sesión establece un valor predeterminado (la implementación usa actualmente un valor predeterminado grande). Si no estás seguro, comienza con 100000 para ejemplos básicos y ajusta según sea necesario.


Opcional: Consultar resultados después de invocar

Obtener una transaction por id

const loaded = await session.getTransaction(blockchainId, tx.transactionId);
console.log("Loaded status:", loaded.status, "| output:", loaded.output);

Obtener un block por altura

const block = await session.getBlock(blockchainId, tx.blockHeight);
console.log("Block height:", block.height);

Próximos pasos

Continúa en: **Invocar Smart Contracts (TS)