This commit is contained in:
Ekiserrepé
2026-02-21 20:10:06 +01:00
parent 7581571baf
commit e3156ca9cb
6 changed files with 340 additions and 671 deletions

View File

@@ -18,10 +18,9 @@ import m06 from './modules/m06-pagos.js'
import m07 from './modules/m07-tokens.js'
import m08 from './modules/m08-nfts.js'
import m09 from './modules/m09-smart-contracts.js'
import m10 from './modules/m10-dex.js'
import m11 from './modules/m11-escrows-cheques.js'
import m12 from './modules/m12-herramientas.js'
import m13 from './modules/m13-proyecto-final.js'
import m10 from './modules/m10-escrows-cheques.js'
import m11 from './modules/m11-herramientas.js'
import m12 from './modules/m12-proyecto-final.js'
export const COURSE_DATA = [
m00,
@@ -37,5 +36,4 @@ export const COURSE_DATA = [
m10,
m11,
m12,
m13,
]

View File

@@ -36,17 +36,17 @@ La diferencia más importante es el **modelo de ejecución**:
- En Ethereum, **tú llamas** al smart contract enviando una transacción al contrato
- En Xahau, los Hooks se **ejecutan automáticamente** cuando una transacción pasa por una cuenta que tiene un Hook instalado
Los Hooks son como **filtros** o **interceptores** que reaccionan a las transacciones. Pueden:
Los Hooks son como **filtros** o **interceptores** que reaccionan a las transacciones. Entre muchas opciones, pueden:
- **Aceptar** la transacción (\`accept()\`)
- **Rechazar** la transacción (\`rollback()\`)
- **Emitir** nuevas transacciones (\`emit()\`)
- **Leer y escribir** estado persistente (\`state()\`, \`state_set()\`)
### Límites
### Algunas datos curiosos
- Máximo **10 Hooks** por cuenta
- Cada Hook tiene su propio **namespace** para estado
- El WASM tiene un tamaño máximo permitido
- Cada Hook tiene su propio **namespace** para guardar información, pero puede utilizar otros que no son el propio si tiene permisos
- La primera vez que se instala un Hook, el código WASM se almacena en el ledger y se le asigna un hash. Si otro usuario quiere instalar el mismo Hook, puede hacer uso del identificador y no necesita tener acceso al código fuente para instalarlo.
### Funciones obligatorias
@@ -1087,5 +1087,323 @@ deployHookWithParams();`,
},
],
},
{
id: "m8l6",
title: {
es: "Hooks Builder: Desarrollo online",
en: "",
jp: "",
},
theory: {
es: `[Hooks Builder](https://builder.xahau.network) es el entorno de desarrollo online para Hooks en **Xahau Testnet**. Permite escribir, compilar, desplegar y probar Hooks directamente desde el navegador sin necesidad de instalar nada en tu equipo. **Nota:** Recuerda guardar tus avances y seeds antes de cerrar el navegador, puede que no se guarden una vez cerrada la sesión.
### Pestañas principales
El Builder tiene tres pestañas principales que cubren todo el flujo de desarrollo:
- **Develop**: Escribir y compilar Hooks en C
- **Deploy**: Gestionar cuentas y desplegar Hooks
- **Test**: Generar transacciones de prueba y ver logs
### Paso 1: Gestionar cuentas en Deploy
Antes de desarrollar, necesitas al menos una cuenta de testnet. En la pestaña **Deploy**:
**Crear una cuenta nueva**
1. Haz clic en **"Generate Account"** o el botón de crear cuenta
2. El Builder generará automáticamente un par de claves (dirección + seed) y fondeará la cuenta con XAH de testnet a través del faucet
3. Guarda el seed en un lugar seguro, lo necesitarás si cierras el navegador
**Importar una cuenta existente**
1. Haz clic en **"Import Account"** o el botón de importar
2. Introduce el **seed** (secret) de tu cuenta de testnet
3. La cuenta aparecerá en la lista con su balance y Hooks instalados
Es recomendable tener al menos **dos cuentas**: una para instalar el Hook y otra para enviarle transacciones de prueba. **No utilices seeds de cuentas de Xahau Mainnet en el Builder por seguridad**, si necesitas una nueva seed, genérala dentro del Builder o visita [xahau-test.net](https://xahau-test.net/).
### Paso 2: Desarrollar y compilar en Develop
En la pestaña **Develop**:
1. **Selecciona un ejemplo** del menú lateral o crea un archivo nuevo
2. **Escribe tu Hook en C**, el editor tiene resaltado de sintaxis y autocompletado básico
3. Haz clic en **"Compile To WASM"** para compilar el código C a WebAssembly
4. Si hay errores, aparecerán en la consola inferior, revisa la línea y el mensaje de error
5. Si la compilación es exitosa, recibirás el mensaje \`File xxxx.c compiled successfully. Ready to deploy.Go to deploy\`. El WASM resultante estará listo para desplegarse
**Consejos**:
- Empieza con los ejemplos incluidos para familiarizarte con la API
- Los errores de compilación más comunes son: olvidar incluir \`hookapi.h\`, no declarar el guard \`_g()\`, o errores de tipos en las funciones de la API
### Paso 3: Desplegar en Deploy
Una vez compilado tu Hook, vuelve a la pestaña **Deploy**:
1. **Selecciona la cuenta** donde quieres instalar el Hook y pulsa **Set Hook** para abrir el formulario de instalación
2. **Configura los parámetros**:
- **Account**: la cuenta donde se instalará el Hook (ya seleccionada)
- **Sequence**: deja que el Builder lo complete automáticamente
- **Invoke on transactions** (HookOn): elige los tipos de transacción que activarán el Hook (puedes elegir varias)
- **Hook Namespace Seed**: el nombre en string que quieres usar como seed para el Namespace.
- **Hook Namespace (sha256)**: El sha256 generado a partir de la Seed utilizada en el campo anterior (no tocar).
- **Hook Parameters**: si tu Hook usa parámetros, configúralos aquí (nombre y valor en hex)
- **Fee**: pulsa en **Suggest** si el Hook da error de fee insuficiente, el Builder calculará el fee recomendado.
3. Haz clic en **"Set Hook"** para enviar la transacción \`SetHook\`
4. Confirma que el resultado es \`tesSUCCESS\` en la consola
### Paso 4: Probar en Test
La pestaña **Test** es donde verificas que tu Hook funciona correctamente:
1. **Transaction type**: Elige el tipo de transacción que quieres enviar (Payment, OfferCreate, etc.).
2. **Account**: El emisor de la transacción.
3. **Sequence**: Deja que el Builder lo complete automáticamente.
4. **Flags**: Configura los flags necesarios para la transacción.
5. **Destination**: La dirección de destino de la transacción.
6. **Amount**: El monto a enviar y el tipo (XAH o IOU), si aplica para la transacción.
7. **Fee**: Pulsa en **Suggest** para que el Builder calcule el fee recomendado.
8. **Hook parameters**: Si tu Hook usa parámetros, configúralos aquí (nombre y valor en hex).
9. **Memos**: Si tu transacción necesita memos, añádelos aquí (opcional).
10. Haz click en **Run Test**.
Deberás estar atento en las pantallas de **Development Log** y **Debug Stream**. En **Debug Stream** puedes elegir que parte del escenario quieres revisar: eligiendo la cuenta si hay varias implicadas.
**Flujo de pruebas recomendado**:
- **Casos positivos**: envía transacciones que deberían ser aceptadas y verifica que pasa.
- **Casos negativos**: envía transacciones que no deberían influir y verifica que es así.
- **Casos límite**: prueba con montos exactos al límite, transacciones de tipos no esperados, etc.
- **Casos no esperados**: prueba transacciones que no esperes por si el Hook las maneja de forma inesperada.
- **Revisa el estado**: si tu Hook usa \`state()\`, verifica que los valores se guardan correctamente consultando \`account_objects\` o la información de estado en el Builder
Una gran y consistente batería de pruebas es clave para asegurar que tu Hook se comporta correctamente en todas las situaciones. Si puedes, pide a otras personas que tambièn prueben tu Hook con casos que tú no hayas considerado.
### Limitaciones del Builder
- Solo funciona con **Xahau Testnet**, no con Mainnet
- Para desarrollo más avanzado o despliegue en producción, necesitarás un entorno local
- El estado de tus cuentas y Hooks se mantiene entre sesiones si no limpias el navegador. No suele ocurrir lo mismo con los Hooks.`,
en: "",
jp: "",
},
codeBlocks: [],
slides: [
{
title: { es: "Hooks Builder — Pestañas", en: "", jp: "" },
content: {
es: "builder.xahau.network\n\n📝 Develop — Escribir y compilar Hooks\n🚀 Deploy — Gestionar cuentas y desplegar\n🧪 Test — Probar con transacciones reales\n\nTodo desde el navegador, sin instalar nada",
en: "",
jp: "",
},
visual: "🌐",
},
{
title: { es: "Flujo de trabajo en el Builder", en: "", jp: "" },
content: {
es: "1. Deploy → Crear o importar cuentas de testnet\n2. Develop → Escribir Hook en C y compilar\n3. Deploy → Instalar Hook en la cuenta\n4. Test → Enviar transacciones de prueba\n5. Revisar logs y mensajes del Hook",
en: "",
jp: "",
},
visual: "🔄",
},
{
title: { es: "Pestaña Test — Verificar tu Hook", en: "", jp: "" },
content: {
es: "• Seleccionar cuenta de origen (distinta al Hook)\n• Elegir tipo de transacción\n• Configurar campos y enviar\n• Revisar logs: accept(), rollback(), trace()\n\nProbar: caso positivo, negativo y límites",
en: "",
jp: "",
},
visual: "🧪",
},
],
},
{
id: "m8l7",
title: {
es: "Desarrollo local de Hooks con hooks-cli",
en: "",
jp: "",
},
theory: {
es: `Para desarrollo profesional, despliegue en **Xahau Mainnet** o proyectos que requieran mayor control, necesitas un entorno de desarrollo local. La herramienta principal es [hooks-cli](https://github.com/Xahau/hooks-cli), una CLI oficial que permite compilar Hooks en C a WebAssembly desde tu terminal.
### ¿Qué es hooks-cli?
**hooks-cli** es una herramienta de línea de comandos que simplifica todo el proceso de compilación de Hooks:
- Compila código C a WebAssembly (.wasm) listo para desplegar
- Incluye todas las dependencias necesarias (compilador, headers, hookapi.h)
- No necesitas configurar manualmente clang, wasm-ld ni las cabeceras del API de Hooks
- Funciona en macOS, Linux y Windows
### Instalación
\`\`\`bash
# Instalar hooks-cli globalmente con npm
npm install -g hooks-cli
\`\`\`
Una vez instalado, el comando \`hooks-cli\` estará disponible en tu terminal.
### Crear carpeta de tu proyecto Hook
\`\`\`bash
# Crear una carpeta para tu proyecto Hook
hooks-cli init c mi-proyecto-hook
\`\`\`
El comando generará una estructura básica de proyecto con un ejemplo de Hook en C, un archivo .env para configuración, y archivos de configuración de TypeScript y npm:
\`\`\`bash
mi-proyecto-hook/
├── contracts/
│ ├── base.c
├── .env
├── package.json
├── tsconfig.json
└── src/
└── index.ts
\`\`\`
### Instalar dependencias de tu proyecto
\`\`\`bash
# Crear una carpeta para tu proyecto Hook
cd mi-proyecto-hook
yarn install
\`\`\`
Dentro de esta carpeta, puedes organizar tu código fuente, archivos compilados y scripts de despliegue como prefieras. Una estructura común es tener una carpeta \`src/\` para el código C, una carpeta \`build/\` para los archivos .wasm compilados, y una carpeta \`scripts/\` para scripts de despliegue.
### Compilar un Hook
Para compilar un archivo C a WebAssembly (.wasm):
\`\`\`bash
# Compilar un Hook
yarn run build
#Otra opción
# hooks-cli compile-c contracts build/
# El resultado será my_hook.wasm en el /build de tu proyecto
\`\`\`
El archivo \`.wasm\` resultante es el binario que desplegarás en Xahau usando una transacción \`SetHook\`.
### Despliegue del Hook en Xahau
Una vez tengamos nuestro Hook en formato .wasm, necesitamos desplegarlo en Xahau. Para automatizar este proceso, puedes usar la librería \`xahau\` y generar una transacción \`SetHook\` que incluya el código del Hook en formato .wasm:
\`\`\`javascript
const createHook = {
"TransactionType": "SetHook",
"Account": mywallet.address,
"Flags": 0,
"Hooks": [
{
"Hook": {
"CreateCode": fs.readFileSync('base.wasm').toString('hex').toUpperCase(),
"HookOn": 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFBFFFFF', //https://richardah.github.io/xrpl-hookon-calculator/
"HookCanEmit": "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBFFFFFFFFFFFFFFFFFFFBFFFFF", //Can emit ClaimReward
"HookNamespace": crypto.createHash('sha256').update('base').digest('hex').toUpperCase(),
"Flags": 1,
"HookApiVersion": 0
}
}
],
};
\`\`\`
### Referencia y documentación
Para información completa sobre hooks-cli, opciones avanzadas de compilación y la API completa de Hooks, consulta:
- **hooks-cli**: [github.com/Xahau/hooks-cli](https://github.com/Xahau/hooks-cli) — Repositorio oficial con instrucciones de instalación y uso
- **Hooks Toolkit**: [hooks-toolkit.com](https://hooks-toolkit.com/) — Documentación completa del toolkit, incluye guías, referencia de la API de Hooks (\`hookapi.h\`), ejemplos y herramientas adicionales para el desarrollo de Hooks`,
en: "",
jp: "",
},
codeBlocks: [
{
title: {
es: "Script de despliegue de un Hook en .wasm",
en: "",
jp: "",
},
language: "javascript",
code: `require("dotenv").config();
const { Client, Wallet } = require("xahau");
async function createHook() {
const client = new Client("wss://xahau-test.net");
await client.connect();
const mywallet = Wallet.fromSeed(process.env.WALLET_SEED, {algorithm: 'secp256k1'});
// Comprar el URIToken pagando el precio de venta
const createHook = {
"TransactionType": "SetHook",
"Account": mywallet.address,
"Flags": 0,
"Hooks": [
{
"Hook": {
"CreateCode": fs.readFileSync('base.wasm').toString('hex').toUpperCase(),
"HookOn": 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFBFFFFF', //https://richardah.github.io/xrpl-hookon-calculator/
"HookCanEmit": "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBFFFFFFFFFFFFFFFFFFFBFFFFF", //Can emit ClaimReward
"HookNamespace": crypto.createHash('sha256').update('base').digest('hex').toUpperCase(),
"Flags": 1,
"HookApiVersion": 0
}
}
],
};
const prepared = await client.autofill(createHook);
const signed = mywallet.sign(prepared);
const result = await client.submitAndWait(signed.tx_blob);
console.log("Resultado:", result.result.meta.TransactionResult);
if (result.result.meta.TransactionResult === "tesSUCCESS") {
console.log("¡La instalación del Hook fue exitosa! para ", mywallet.address); }
await client.disconnect();
}
createHook();`,
},
],
slides: [
{
title: { es: "hooks-cli — Compilación local", en: "", jp: "" },
content: {
es: "Herramienta oficial para compilar Hooks\n\nnpm install -g hooks-cli\nhooks-cli build my_hook.c\n\n• Compila C → WebAssembly\n• Incluye todas las dependencias\n• macOS, Linux y Windows",
en: "",
jp: "",
},
visual: "🔨",
},
{
title: { es: "Estructura de proyecto", en: "", jp: "" },
content: {
es: "mi-proyecto-hook/\n├── src/my_hook.c\n├── build/my_hook.wasm\n├── scripts/deploy.js\n├── package.json\n└── .env\n\nFlujo: escribir → compilar → desplegar → probar",
en: "",
jp: "",
},
visual: "📁",
},
{
title: { es: "Recursos de referencia", en: "", jp: "" },
content: {
es: "• hooks-cli: github.com/Xahau/hooks-cli\n Repositorio oficial y guía de uso\n\n• Hooks Toolkit: hooks-toolkit.com\n Documentación completa, API reference y ejemplos\n\n• Builder (testnet): builder.xahau.network",
en: "",
jp: "",
},
visual: "📚",
},
],
},
],
}

View File

@@ -1,647 +0,0 @@
export default {
id: "m9",
icon: "📊",
title: {
es: "El DEX nativo de Xahau",
en: "",
jp: "",
},
lessons: [
{
id: "m9l1",
title: {
es: "¿Qué es un DEX y cómo funciona en Xahau?",
en: "",
jp: "",
},
theory: {
es: `Un **DEX** (Decentralized Exchange) es un exchange descentralizado que permite intercambiar tokens sin intermediarios. Lo que hace especial al DEX de Xahau es que está **integrado directamente en el protocolo** — no necesitas smart contracts para operar.
### DEX nativo vs DEX basado en contratos
| Característica | DEX EVM (Uniswap, etc.) | DEX Xahau |
|---|---|---|
| Implementación | Smart contract | Nativo del protocolo |
| Modelo | AMM (Automated Market Maker) | Order Book (libro de órdenes) |
| Despliegue | Necesitas desplegar contratos | Ya existe en cada cuenta |
| Fees de swap | Fee del protocolo + fee del contrato | Solo fee de transacción estándar |
| Liquidez | Pools de liquidez | Órdenes individuales |
### Modelo de libro de órdenes (Order Book)
A diferencia de los AMM populares en Ethereum, Xahau usa un **modelo de libro de órdenes**:
- Los **makers** colocan órdenes en el libro (ofertas de compra o venta)
- Los **takers** llenan esas órdenes al operar contra ellas
- Las órdenes se emparejan automáticamente por el protocolo cuando los precios coinciden
### Pares de divisas
En el DEX de Xahau puedes operar:
- **Token contra XAH** (ej: USD/XAH, EUR/XAH)
- **Token contra token** (ej: USD/EUR)
- Cualquier token emitido en Xahau puede ser intercambiado
### Auto-bridging
Cuando no hay liquidez directa entre dos tokens, Xahau usa **auto-bridging**:
- El protocolo enruta automáticamente a través de XAH como intermediario
- Ejemplo: Si quieres vender EUR por USD pero no hay ofertas directas, el DEX busca EUR→XAH y luego XAH→USD
- Esto sucede automáticamente — no necesitas hacer nada especial
### Fees
El DEX de Xahau es extremadamente eficiente en costos:
- Solo pagas el **fee de transacción estándar** (fracciones de XAH)
- No hay fees de swap adicionales como en Uniswap (0.3%)
- No hay fees de proveedor de liquidez
- Esto hace que el trading sea mucho más barato que en DEXs basados en contratos`,
en: "",
jp: "",
},
codeBlocks: [],
slides: [
{
title: { es: "¿Qué es el DEX de Xahau?", en: "", jp: "" },
content: {
es: "Exchange descentralizado nativo del protocolo\n\n• No necesita smart contracts\n• Modelo de libro de órdenes (Order Book)\n• Cualquier token puede ser intercambiado\n• Solo fee de transacción estándar",
en: "",
jp: "",
},
visual: "📊",
},
{
title: { es: "Order Book vs AMM", en: "", jp: "" },
content: {
es: "Xahau: Order Book\n• Makers colocan órdenes\n• Takers llenan órdenes\n• Emparejamiento automático\n\nEVM (Uniswap): AMM\n• Pools de liquidez\n• Fórmula matemática (x*y=k)\n• Fees de swap del 0.3%+",
en: "",
jp: "",
},
visual: "📖",
},
{
title: { es: "Auto-bridging", en: "", jp: "" },
content: {
es: "Xahau enruta automáticamente a través de XAH\n\n• EUR → XAH → USD (automático)\n• Aumenta la liquidez efectiva\n• No requiere acción del usuario\n• El protocolo busca la mejor ruta",
en: "",
jp: "",
},
visual: "🌉",
},
],
},
{
id: "m9l2",
title: {
es: "Consultar el libro de órdenes",
en: "",
jp: "",
},
theory: {
es: `Antes de operar en el DEX, necesitas poder **consultar el libro de órdenes** para ver qué ofertas existen y a qué precios.
### El comando book_offers
El comando \`book_offers\` te permite consultar las órdenes disponibles para un par de divisas:
- **taker_pays**: lo que el taker paga (lo que tú ofreces)
- **taker_gets**: lo que el taker recibe (lo que tú quieres)
Si quieres **comprar USD con XAH**, entonces:
- \`taker_pays\` = XAH (lo que ofreces)
- \`taker_gets\` = USD (lo que quieres)
### Bids y Asks
El libro de órdenes tiene dos lados:
- **Bids (ofertas de compra)**: personas que quieren comprar el token base
- **Asks (ofertas de venta)**: personas que quieren vender el token base
### Estructura de una oferta
Cada oferta en el libro tiene:
- **TakerPays**: lo que el creador de la oferta quiere recibir
- **TakerGets**: lo que el creador ofrece dar
- **quality**: la relación TakerPays/TakerGets (el precio)
- **Account**: la cuenta que creó la oferta
- **Sequence**: número de secuencia de la oferta (su identificador)
### Calcular el precio
El precio efectivo de una oferta se calcula como:
\`\`\`
precio = TakerPays / TakerGets
\`\`\`
Para tokens con decimales, necesitas tener en cuenta que XAH se expresa en **drops** (1 XAH = 1,000,000 drops) y los tokens IOU tienen su propia precisión.
### Top of Book
La **mejor oferta** (top of book) es:
- Para compras: la oferta con el **precio más bajo** (comprar barato)
- Para ventas: la oferta con el **precio más alto** (vender caro)
Las ofertas se devuelven ordenadas por calidad (precio), así que la primera oferta es siempre la mejor disponible.`,
en: "",
jp: "",
},
codeBlocks: [
{
title: {
es: "Consultar el libro de órdenes para un par token/XAH",
en: "",
jp: "",
},
language: "javascript",
code: `const { Client } = require("xahau");
async function getOrderBook() {
const client = new Client("wss://xahau-test.net");
await client.connect();
// Consultar ofertas: comprar USD (del emisor rIssuer...)
// pagando con XAH
const response = await client.request({
command: "book_offers",
taker_pays: {
currency: "XAH",
},
taker_gets: {
currency: "USD",
issuer: "rIssuerAddressHere",
},
limit: 10,
ledger_index: "validated",
});
const offers = response.result.offers;
console.log("=== Libro de órdenes: USD/XAH ===");
console.log("Ofertas disponibles:", offers.length);
console.log();
for (const offer of offers) {
// TakerPays = XAH (en drops)
const paysDrops = typeof offer.TakerPays === "string"
? Number(offer.TakerPays)
: Number(offer.TakerPays.value);
// TakerGets = USD
const getsValue = typeof offer.TakerGets === "string"
? Number(offer.TakerGets) / 1000000
: Number(offer.TakerGets.value);
const paysXAH = paysDrops / 1000000;
const price = paysXAH / getsValue;
console.log("Cuenta:", offer.Account);
console.log(" Ofrece:", getsValue, "USD");
console.log(" Pide:", paysXAH, "XAH");
console.log(" Precio:", price.toFixed(4), "XAH por USD");
console.log();
}
await client.disconnect();
}
getOrderBook();`,
},
{
title: {
es: "Top 5 mejores ofertas de compra y venta",
en: "",
jp: "",
},
language: "javascript",
code: `const { Client } = require("xahau");
async function showTopOfBook() {
const client = new Client("wss://xahau-test.net");
await client.connect();
const issuer = "rIssuerAddressHere";
const currency = "USD";
// Lado de compra: ofertas que venden USD por XAH
// (taker paga XAH, recibe USD)
const buyBook = await client.request({
command: "book_offers",
taker_pays: { currency: "XAH" },
taker_gets: { currency, issuer },
limit: 5,
ledger_index: "validated",
});
// Lado de venta: ofertas que compran USD con XAH
// (taker paga USD, recibe XAH)
const sellBook = await client.request({
command: "book_offers",
taker_pays: { currency, issuer },
taker_gets: { currency: "XAH" },
limit: 5,
ledger_index: "validated",
});
// Función para calcular precio
function calcPrice(pays, gets) {
const paysVal = typeof pays === "string"
? Number(pays) / 1000000
: Number(pays.value);
const getsVal = typeof gets === "string"
? Number(gets) / 1000000
: Number(gets.value);
return { paysVal, getsVal };
}
console.log("=== TOP 5 OFERTAS DE COMPRA (Buy USD) ===");
for (let i = 0; i < buyBook.result.offers.length; i++) {
const o = buyBook.result.offers[i];
const { paysVal, getsVal } = calcPrice(o.TakerPays, o.TakerGets);
console.log(
\` #\${i + 1} | \${getsVal.toFixed(2)} USD a \${(paysVal / getsVal).toFixed(4)} XAH/USD\`
);
}
console.log();
console.log("=== TOP 5 OFERTAS DE VENTA (Sell USD) ===");
for (let i = 0; i < sellBook.result.offers.length; i++) {
const o = sellBook.result.offers[i];
const { paysVal, getsVal } = calcPrice(o.TakerPays, o.TakerGets);
console.log(
\` #\${i + 1} | \${paysVal.toFixed(2)} USD a \${(getsVal / paysVal).toFixed(4)} XAH/USD\`
);
}
const bestBuy = buyBook.result.offers[0];
const bestSell = sellBook.result.offers[0];
if (bestBuy && bestSell) {
const buy = calcPrice(bestBuy.TakerPays, bestBuy.TakerGets);
const sell = calcPrice(bestSell.TakerPays, bestSell.TakerGets);
const buyPrice = buy.paysVal / buy.getsVal;
const sellPrice = sell.getsVal / sell.paysVal;
const spread = ((buyPrice - sellPrice) / sellPrice * 100).toFixed(2);
console.log(\`\\nSpread: \${spread}%\`);
}
await client.disconnect();
}
showTopOfBook();`,
},
],
slides: [
{
title: { es: "Consultar el libro de órdenes", en: "", jp: "" },
content: {
es: "Comando: book_offers\n\n• taker_pays → Lo que ofreces\n• taker_gets → Lo que quieres\n• Resultado: lista de ofertas ordenadas por precio\n• La primera oferta = mejor precio",
en: "",
jp: "",
},
visual: "🔍",
},
{
title: { es: "Anatomía de una oferta", en: "", jp: "" },
content: {
es: "Cada oferta contiene:\n\n• TakerPays → Lo que el maker quiere recibir\n• TakerGets → Lo que el maker ofrece\n• quality → Precio (TakerPays / TakerGets)\n• Account → Creador de la oferta\n• Sequence → Identificador de la oferta",
en: "",
jp: "",
},
visual: "📄",
},
{
title: { es: "Precio, top of book y spread", en: "", jp: "" },
content: {
es: "Calcular el precio:\n• precio = TakerPays / TakerGets\n• XAH en drops (1 XAH = 1,000,000 drops)\n\nTop of book:\n• Primera oferta = mejor precio disponible\n• Compra: precio más bajo\n• Venta: precio más alto\n\nBid/Ask spread = diferencia entre mejor compra y mejor venta",
en: "",
jp: "",
},
visual: "💹",
},
],
},
{
id: "m9l3",
title: {
es: "Crear y gestionar ofertas",
en: "",
jp: "",
},
theory: {
es: `Para operar en el DEX de Xahau, creas ofertas usando la transacción **OfferCreate**. Estas ofertas se publican en el libro de órdenes y pueden ser llenadas por otros participantes.
### OfferCreate — Crear una oferta
La transacción \`OfferCreate\` tiene dos campos principales:
- **TakerPays**: lo que quieres recibir (tu lado de compra)
- **TakerGets**: lo que ofreces dar (tu lado de venta)
Si quieres **comprar 100 USD pagando con XAH a un precio de 2 XAH por USD**:
- \`TakerPays\` = 100 USD (lo que quieres)
- \`TakerGets\` = 200 XAH (lo que ofreces)
### Matching automático
Cuando creas una oferta, el protocolo busca automáticamente ofertas existentes que coincidan:
- Si hay ofertas al precio que pides (o mejor), tu oferta se **llena inmediatamente**
- Si no hay coincidencias, tu oferta queda en el libro esperando
- Las ofertas pueden llenarse **parcialmente**: si pides 100 USD pero solo hay 50 disponibles, recibes 50 y el resto queda como oferta abierta
### Flags importantes
| Flag | Efecto |
|---|---|
| **tfImmediateOrCancel** | Si no se llena inmediatamente (total o parcial), se cancela el resto |
| **tfFillOrKill** | Si no se puede llenar completamente de inmediato, se cancela toda la oferta |
| **tfPassive** | No consume ofertas existentes; solo se publica en el libro |
| **tfSell** | Trata TakerGets como la cantidad exacta a vender (el resto puede variar) |
### OfferCancel — Cancelar una oferta
Para cancelar una oferta abierta, usas \`OfferCancel\` con el \`OfferSequence\` (número de secuencia) de la oferta que quieres cancelar.
### Consultar tus ofertas abiertas
Usa el comando \`account_offers\` para ver todas las ofertas abiertas de una cuenta.
### Expiración automática
Puedes agregar un campo **Expiration** a tu oferta con un timestamp. Cuando el ledger supere ese tiempo, la oferta se elimina automáticamente. El timestamp es en formato "Ripple epoch" (segundos desde el 1 de enero del 2000).`,
en: "",
jp: "",
},
codeBlocks: [
{
title: {
es: "Crear una oferta de compra (comprar USD con XAH)",
en: "",
jp: "",
},
language: "javascript",
code: `const { Client, Wallet } = require("xahau");
async function createBuyOffer() {
const client = new Client("wss://xahau-test.net");
await client.connect();
const wallet = Wallet.fromSeed("sEdVxxxTuSeedDeTestnet", {algorithm: 'secp256k1'});
// Crear oferta: comprar 50 USD a 2 XAH por USD
// TakerPays = lo que quiero (50 USD)
// TakerGets = lo que ofrezco (100 XAH = 100000000 drops)
const offerCreate = {
TransactionType: "OfferCreate",
Account: wallet.address,
TakerPays: {
currency: "USD",
issuer: "rIssuerAddressHere",
value: "50",
},
TakerGets: "100000000", // 100 XAH en drops
};
const prepared = await client.autofill(offerCreate);
const signed = wallet.sign(prepared);
const result = await client.submitAndWait(signed.tx_blob);
console.log("Resultado:", result.result.meta.TransactionResult);
if (result.result.meta.TransactionResult === "tesSUCCESS") {
// Verificar si la oferta se llenó o quedó abierta
const affectedNodes = result.result.meta.AffectedNodes;
const createdOffer = affectedNodes.find(
(n) => n.CreatedNode && n.CreatedNode.LedgerEntryType === "Offer"
);
if (createdOffer) {
console.log("Oferta publicada en el libro de órdenes.");
console.log("Sequence:", result.result.Sequence);
} else {
console.log("¡Oferta llenada inmediatamente!");
}
}
await client.disconnect();
}
createBuyOffer();`,
},
{
title: {
es: "Listar todas las ofertas abiertas de tu cuenta",
en: "",
jp: "",
},
language: "javascript",
code: `const { Client } = require("xahau");
async function listMyOffers(address) {
const client = new Client("wss://xahau-test.net");
await client.connect();
const response = await client.request({
command: "account_offers",
account: address,
ledger_index: "validated",
});
const offers = response.result.offers;
console.log(\`=== Ofertas abiertas de \${address} ===\`);
console.log(\`Total: \${offers.length}\\n\`);
for (const offer of offers) {
// Parsear TakerPays
let paysStr;
if (typeof offer.taker_pays === "string") {
paysStr = (Number(offer.taker_pays) / 1000000).toFixed(2) + " XAH";
} else {
paysStr = offer.taker_pays.value + " " + offer.taker_pays.currency;
}
// Parsear TakerGets
let getsStr;
if (typeof offer.taker_gets === "string") {
getsStr = (Number(offer.taker_gets) / 1000000).toFixed(2) + " XAH";
} else {
getsStr = offer.taker_gets.value + " " + offer.taker_gets.currency;
}
console.log(\`Oferta #\${offer.seq}:\`);
console.log(\` Quiero: \${paysStr}\`);
console.log(\` Ofrezco: \${getsStr}\`);
if (offer.expiration) {
const expDate = new Date((offer.expiration + 946684800) * 1000);
console.log(\` Expira: \${expDate.toISOString()}\`);
}
console.log();
}
await client.disconnect();
}
listMyOffers("rTuDireccionAqui");`,
},
{
title: {
es: "Cancelar una oferta por su número de secuencia",
en: "",
jp: "",
},
language: "javascript",
code: `const { Client, Wallet } = require("xahau");
async function cancelOffer(offerSequence) {
const client = new Client("wss://xahau-test.net");
await client.connect();
const wallet = Wallet.fromSeed("sEdVxxxTuSeedDeTestnet", {algorithm: 'secp256k1'});
const offerCancel = {
TransactionType: "OfferCancel",
Account: wallet.address,
OfferSequence: offerSequence,
};
const prepared = await client.autofill(offerCancel);
const signed = wallet.sign(prepared);
const result = await client.submitAndWait(signed.tx_blob);
console.log("Resultado:", result.result.meta.TransactionResult);
if (result.result.meta.TransactionResult === "tesSUCCESS") {
console.log(\`Oferta #\${offerSequence} cancelada con éxito.\`);
} else {
console.log("Error al cancelar la oferta.");
}
await client.disconnect();
}
// Cancelar la oferta con sequence 12345
cancelOffer(12345);`,
},
],
slides: [
{
title: { es: "OfferCreate", en: "", jp: "" },
content: {
es: "Crear ofertas en el DEX\n\n• TakerPays → Lo que quieres recibir\n• TakerGets → Lo que ofreces dar\n• Matching automático si hay coincidencia\n• Las ofertas pueden llenarse parcialmente",
en: "",
jp: "",
},
visual: "📝",
},
{
title: { es: "Flags de ofertas", en: "", jp: "" },
content: {
es: "• tfImmediateOrCancel → Llena o cancela\n• tfFillOrKill → Todo o nada\n• tfPassive → Solo publica, no consume\n• tfSell → Cantidad exacta de venta\n\nExpiration → Cancelación automática por tiempo",
en: "",
jp: "",
},
visual: "🚩",
},
{
title: { es: "Gestionar ofertas", en: "", jp: "" },
content: {
es: "• account_offers → Ver tus ofertas abiertas\n• OfferCancel → Cancelar por OfferSequence\n• Expiration → Auto-cancelación por tiempo\n• Cada oferta abierta aumenta tu reserva",
en: "",
jp: "",
},
visual: "🗂️",
},
],
},
{
id: "m9l4",
title: {
es: "Estrategias de trading y auto-bridging",
en: "",
jp: "",
},
theory: {
es: `En esta lección veremos cómo funciona el **auto-bridging** en detalle, y las mejores prácticas para operar en el DEX de Xahau.
### Auto-bridging en detalle
Cuando operas con un par de tokens que no tiene liquidez directa, Xahau busca una ruta a través de **XAH**:
**Ejemplo**: Quieres vender EUR por USD
1. El DEX busca ofertas directas EUR/USD
2. Si no hay suficiente liquidez, busca EUR→XAH y XAH→USD
3. Combina ambas rutas para darte el mejor precio posible
4. Todo esto ocurre en una sola transacción
El auto-bridging **aumenta significativamente la liquidez** del DEX porque todos los pares de tokens se benefician de la liquidez XAH.
### Órdenes de mercado vs órdenes límite
- **Orden de mercado**: Quieres ejecutar inmediatamente al mejor precio disponible
- Usa el flag \`tfImmediateOrCancel\`
- La oferta se llena con las mejores ofertas del libro y el resto se cancela
- **Orden límite**: Quieres un precio específico y estás dispuesto a esperar
- Crea una oferta sin flags especiales
- La oferta permanece en el libro hasta que alguien la llene
### Spread y slippage
- **Spread**: La diferencia entre el mejor precio de compra y el mejor precio de venta
- Un spread bajo indica buena liquidez
- Un spread alto indica poca liquidez o volatilidad
- **Slippage**: La diferencia entre el precio esperado y el precio real de ejecución
- Ocurre cuando tu orden es grande relativa a la liquidez disponible
- Para órdenes grandes, puedes consultar el libro primero para estimar el slippage
### Mejores prácticas
1. **Consulta el libro antes de operar**: Usa \`book_offers\` para ver los precios actuales y estimar el slippage
2. **Usa tfImmediateOrCancel para órdenes de mercado**: Así evitas que una oferta parcialmente llenada quede abierta indefinidamente
3. **Monitorea tus ofertas abiertas**: Las ofertas que dejas en el libro pueden ejecutarse en cualquier momento. Usa \`account_offers\` regularmente
4. **Reservas de cuenta**: Cada oferta abierta en el DEX aumenta la **reserva** requerida de tu cuenta. Si tienes muchas ofertas abiertas, necesitarás más XAH en tu cuenta
- Reserva base de cuenta: 1 XAH
- Reserva por objeto (incluyendo ofertas): 0.2 XAH adicionales por oferta
5. **Expiración como protección**: Para ofertas límite, usa el campo \`Expiration\` para evitar que ofertas viejas se ejecuten a precios desactualizados
6. **Cuidado con el auto-bridging en tokens ilíquidos**: Si el par XAH intermedio también tiene poca liquidez, el precio final puede ser desfavorable`,
en: "",
jp: "",
},
codeBlocks: [],
slides: [
{
title: { es: "Auto-bridging en detalle", en: "", jp: "" },
content: {
es: "Ruta automática a través de XAH\n\n• EUR → XAH → USD (automático)\n• Una sola transacción\n• Combina liquidez de ambos pares\n• Aumenta la liquidez efectiva del DEX",
en: "",
jp: "",
},
visual: "🌉",
},
{
title: { es: "Tipos de órdenes", en: "", jp: "" },
content: {
es: "Orden de mercado:\n• tfImmediateOrCancel\n• Ejecución inmediata al mejor precio\n\nOrden límite:\n• Sin flags especiales\n• Espera en el libro al precio deseado\n• Usa Expiration como protección",
en: "",
jp: "",
},
visual: "⚖️",
},
{
title: { es: "Mejores prácticas", en: "", jp: "" },
content: {
es: "• Consulta book_offers antes de operar\n• Monitorea tus ofertas abiertas\n• Cada oferta abierta = +0.2 XAH de reserva\n• Usa Expiration en ofertas límite\n• Cuidado con tokens ilíquidos",
en: "",
jp: "",
},
visual: "✅",
},
],
},
],
}

View File

@@ -1,5 +1,5 @@
export default {
id: "m11",
id: "m10",
icon: "🔐",
title: {
es: "Escrows, Cheques y Tickets",
@@ -8,7 +8,7 @@ export default {
},
lessons: [
{
id: "m11l1",
id: "m10l1",
title: {
es: "Escrows: pagos condicionales",
en: "",
@@ -247,7 +247,7 @@ finishEscrow("rDireccionDelCreador", 12345);`,
],
},
{
id: "m11l2",
id: "m10l2",
title: {
es: "Cheques: pagos diferidos",
en: "",
@@ -471,7 +471,7 @@ cashCheck("TU_CHECK_ID_AQUI");`,
],
},
{
id: "m11l3",
id: "m10l3",
title: {
es: "Tickets: secuencias fuera de orden",
en: "",

View File

@@ -1,5 +1,5 @@
export default {
id: "m12",
id: "m11",
icon: "🧰",
title: {
es: "Herramientas del ecosistema Xahau",
@@ -8,7 +8,7 @@ export default {
},
lessons: [
{
id: "m12l1",
id: "m11l1",
title: {
es: "Xaman: la wallet principal de Xahau",
en: "",
@@ -122,7 +122,7 @@ Las dApps se conectan a Xaman de dos formas:
],
},
{
id: "m12l2",
id: "m11l2",
title: {
es: "Exploradores de bloques",
en: "",
@@ -311,7 +311,7 @@ explorarTransaccion("TU_HASH_DE_TRANSACCION_AQUI");`,
],
},
{
id: "m12l3",
id: "m11l3",
title: {
es: "Hooks Builder: IDE online para smart contracts",
en: "",
@@ -438,7 +438,7 @@ Considera migrar a un entorno local cuando:
],
},
{
id: "m12l4",
id: "m11l4",
title: {
es: "Recursos para desarrolladores",
en: "",

View File

@@ -1,5 +1,5 @@
export default {
id: "m13",
id: "m12",
icon: "🎓",
title: {
es: "Proyecto final",
@@ -8,7 +8,7 @@ export default {
},
lessons: [
{
id: "m13l1",
id: "m12l1",
title: {
es: "Diseño del proyecto",
en: "",
@@ -108,7 +108,7 @@ Todo el proyecto se ejecuta en **testnet**. Los tokens y NFTs no tienen valor re
],
},
{
id: "m13l2",
id: "m12l2",
title: {
es: "Paso 1: Crear y financiar wallets",
en: "",
@@ -254,7 +254,7 @@ setup().catch(console.error);`,
],
},
{
id: "m13l3",
id: "m12l3",
title: {
es: "Paso 2: Enviar pagos y emitir tokens",
en: "",
@@ -470,7 +470,7 @@ pagosYTokens().catch(console.error);`,
],
},
{
id: "m13l4",
id: "m12l4",
title: {
es: "Paso 3: NFTs y trading",
en: "",
@@ -715,7 +715,7 @@ nftsYDex().catch(console.error);`,
],
},
{
id: "m13l5",
id: "m12l5",
title: {
es: "Resumen y próximos pasos",
en: "",