Zum Hauptinhalt springen
Echtzeit-Radar & Feeds
Alle RSS Feeds ➔
👥 Community & Social
••••••••••••••••••••
Intelligence View
⚡ tsecurity.de Intelligence

Tutorial: Midnight Wallet SDK - Guía Completa para Desarrolladores

Índice Introducción Instalación Conceptos Clave Crear Instancias de Billetera Gestión de Direcciones Trabajar con Transacciones Conectar con DApps Ejemplos Prá…

Beitrag
0
Seite
0
↗ Quelle (dev.to)
Social ReaktionenReagiere als Erste:r — dein Feedback zählt!

Índice



Introducción

Instalación

Conceptos Clave

Crear Instancias de Billetera

Gestión de Direcciones

Trabajar con Transacciones

Conectar con DApps

Ejemplos Prácticos



Introducción

Midnight Wallet SDK es un conjunto de herramientas que permite integrar funcionalidad de billetera en aplicaciones blockchain. El SDK proporciona abstracciones de alto nivel para gestionar operaciones comunes como:



Derivación de claves - Generar claves criptográficas a partir de una semilla

Balance de tokens - Obtener el saldo de tokens desde datos de la cadena

Gestión de monedas - Administrar monedas y datos para pruebas de conocimiento cero

Conexión con indexadores - Sincronizar estado con servidores indexadores

Creación de transacciones - Preparar y enviar transferencias de tokens



Paquetes Principales

PaqueteDescripción@midnight-ntwrk/wallet-apiInterfaces de alto nivel para billeteras@midnight-ntwrk/walletImplementación de wallet-api con herramientas adicionales@midnight-ntwrk/zswapConstrucción de bloques de Zswap@midnight-ntwrk/wallet-sdk-hdSoporte para billeteras jerárquico-determinísticas (HD)@midnight-ntwrk/wallet-sdk-address-formatSoporte para formato de dirección Bech32m



Instalación

Requisitos Previos



Node.js instalado

Yarn o npm como gestor de paquetes



Instalación del SDK

Usa Yarn para instalar el paquete:

bashyarn add @midnight-ntwrk/wallet/

Reemplaza con la versión requerida según la matriz de compatibilidad de versiones.

⚠️ Importante: A partir de la versión 4.0.0 hay cambios significativos. Consulta la matriz de compatibilidad para asegurar que usas la versión correcta.

Información Crítica sobre v4.0.0



Cambio importante: Las claves secretas ya no se incluyen en el estado serializado de la billetera

Restauración: Si restauras una billetera desde una instantánea, debes proporcionar la semilla original

Seguridad: Asegúrate de gestionar datos sensibles de forma segura



Conceptos Clave

Semilla de Billetera (Wallet Seed)

La semilla es un valor aleatorio (usualmente 256 bits) que se usa para derivar todas las claves criptográficas de tu billetera. Es esencial para:



Recuperar una billetera

Generar direcciones determinísticas

Restaurar estado desde instantáneas



Billeteras HD (Jerárquico-Determinísticas)

El SDK utiliza derivación BIP-32 siguiendo la ruta:

m / 44' / 2400' / account' / role / index

Donde:



account - Número de cuenta (recomendación BIP-44)

role - Tipo de rol (3 para Zswap)

index - Índice específico (recomendación BIP-44)



Ciclo de Vida de la Billetera




  1. Crear instancia → 2. Iniciar sincronización → 3. Usar billetera → 4. Cerrar
    NetworkId (Identificador de Red)
    Define la red blockchain objetivo:



NetworkId.TestNet - Red de prueba

NetworkId.MainNet - Red principal

NetworkId.DevNet - Red de desarrollo



Crear Instancias de Billetera

Paso 1: Importar el Constructor

javascriptimport { WalletBuilder } from '@midnight-ntwrk/wallet';

import { NetworkId } from '@midnight-ntwrk/zswap';

Paso 2: Generar una Semilla

Para testing, puedes generar una semilla aleatoria:

javascriptimport { generateRandomSeed } from '@midnight-ntwrk/wallet-sdk-hd';



const semillaAleatoria = generateRandomSeed();

console.log('Semilla generada:', semillaAleatoria);

Para producción, usa derivación HD:

javascriptimport {

generateRandomSeed,

HDWallet,

Roles,

} from "@midnight-ntwrk/wallet-sdk-hd";



const semilla = generateRandomSeed();



function derivarSemillaDerivacion(semilla) {

const billetera = HDWallet.fromSeed(semilla);



if (billetera.type != "seedOk") {

throw new Error("Error inicializando HD Wallet");

}



const zswapKey = billetera.hdWallet

.selectAccount(0)

.selectRole(Roles.Zswap)

.deriveKeyAt(0);



if (zswapKey.type === "keyDerived") {

return zswapKey.key;

} else {

throw new Error("Error derivando clave");

}

}



const semillaFinal = derivarSemillaDerivacion(semilla);

console.log('Semilla derivada:', semillaFinal);

Paso 3: Construir la Instancia

Opción A: Desde una Semilla Específica

javascriptimport { WalletBuilder } from '@midnight-ntwrk/wallet';

import { NetworkId } from '@midnight-ntwrk/zswap';



const billetera = await WalletBuilder.build(

'https://indexer.testnet-02.midnight.network/api/v1/graphql', // URL del Indexador

'wss://indexer.testnet-02.midnight.network/api/v1/graphql/ws', // WebSocket del Indexador

'http://localhost:6300', // URL del Servidor de Pruebas

'https://rpc.testnet-02.midnight.network', // URL del Nodo

'0000000000000000000000000000000000000000000000000000000000000000', // Semilla

NetworkId.TestNet, // Red

'error' // Nivel de Log (opcional)

);

Opción B: Con Semilla Aleatoria (Testing)

javascriptimport { WalletBuilder } from '@midnight-ntwrk/wallet';

import { NetworkId } from '@midnight-ntwrk/zswap';

import { generateRandomSeed } from '@midnight-ntwrk/wallet-sdk-hd';



const semillaAleatoria = generateRandomSeed();



const billetera = await WalletBuilder.build(

'https://indexer.testnet-02.midnight.network/api/v1/graphql',

'wss://indexer.testnet-02.midnight.network/api/v1/graphql/ws',

'http://localhost:6300',

'https://rpc.testnet-02.midnight.network',

semillaAleatoria, // Semilla aleatoria

NetworkId.TestNet,

'error'

);

Paso 4: Iniciar la Sincronización

javascript// Inicia la sincronización con la cadena

billetera.start();



console.log('Billetera iniciada y sincronizando...');

Paso 5: Cerrar la Billetera

javascript// Cuando termines, cierra la billetera adecuadamente

await billetera.close();



console.log('Billetera cerrada y recursos liberados');



Instantáneas de Estado (State Snapshots)

Las instantáneas permiten guardar y restaurar el estado de una billetera rápidamente, ideal para extensiones de navegador o aplicaciones móviles.

Crear una Instantánea

javascriptconst estadoSerializado = await billetera.serialize();



console.log('Instantánea creada:', estadoSerializado);

Restaurar desde una Instantánea

⚠️ Importante: Debes proporcionar la semilla original para restaurar.

javascriptconst billetera_restaurada = await WalletBuilder.restore(

'https://indexer.testnet-02.midnight.network/api/v1/graphql',

'wss://indexer.testnet-02.midnight.network/api/v1/graphql/ws',

'http://localhost:6300',

'https://rpc.testnet-02.midnight.network',

'0000000000000000000000000000000000000000000000000000000000000000', // DEBES proporcionar la semilla

estadoSerializado,

'error'

);



billetera_restaurada.start();



Gestión de Direcciones

Formato Bech32m

Midnight utiliza direcciones en formato Bech32m con el prefijo personalizado mn_.

La estructura del prefijo es:

mn__

Ejemplos:



mn_shield-addr_test1... - Dirección de pago en TestNet

mn_shield-addr_test1... - Dirección escudada en TestNet (ESK para indexador)



Codificar una Dirección

javascriptimport {

ShieldedAddress,

ShieldedCoinPublicKey,

ShieldedEncryptionPublicKey,

MidnightBech32m,

} from "@midnight-ntwrk/wallet-sdk-address-format";

import { NetworkId } from "@midnight-ntwrk/zswap";

import { Buffer } from "buffer";



// Crear claves públicas

const claveCoinPublica = new ShieldedCoinPublicKey(

Buffer.from(

"064e092a80b33bee23404c46cfc48fec75a2356a9b01178dd6a62c29f5896f67",

"hex"

)

);



const claveEncriptacionPublica = new ShieldedEncryptionPublicKey(

Buffer.from(

"0300063c7753854aea18aa11f04d77b3c7eaa0918e4aa98d5eaf0704d8f4c2fc272899efbb8a71275f2a1aedd29f879021e0962b4730f9b47e1a",

"hex"

)

);



// Crear dirección

const direccion = new ShieldedAddress(claveCoinPublica, claveEncriptacionPublica);



// Codificar en Bech32m

const direccionCodificada = ShieldedAddress.codec

.encode(NetworkId.TestNet, direccion)

.asString();



console.log('Dirección codificada:', direccionCodificada);

// Salida: mn_shield-addr_test1qe8qj25qkva7ug6qf3rvl3y0a366ydt2nvq30rwk5ckznavfdansxqqx83m48p22agv25y0sf4mm83l25zgcuj4f34027pcymr6v9lp89zv7lwu2wyn472s6ahfflpusy8sfv268xrumgls62hqz4u

Decodificar una Dirección

javascriptconst direccionCodificada = "mn_shield-addr_test1qe8qj25qkva7ug6qf3rvl3y0a366ydt2nvq30rwk5ckznavfdansxqqx83m48p22agv25y0sf4mm83l25zgcuj4f34027pcymr6v9lp89zv7lwu2wyn472s6ahfflpusy8sfv268xrumgls62hqz4u";



// Parsear

const direccionParseada = MidnightBech32m.parse(direccionCodificada);



// Decodificar

const direccionDecodificada = ShieldedAddress.codec.decode(

NetworkId.TestNet,

direccionParseada

);



console.log('Clave pública de coin:', direccionDecodificada.coinPublicKeyString());

console.log('Clave pública de encriptación:', direccionDecodificada.encryptionPublicKeyString());



Trabajar con Transacciones

Ciclo de Vida de una Transacción




  1. Preparar transacción sin prueba
    ↓

  2. Calcular pruebas de conocimiento cero
    ↓

  3. Enviar transacción comprobada
    Acceder al Estado de la Billetera
    El estado se proporciona a través de un observable de RxJS:
    javascriptimport { Observable } from 'rxjs';



// Suscribirse a cambios de estado

billetera.state().subscribe((estado) => {

console.log('Estado actual:', estado);

console.log('Saldo:', estado.coins);

console.log('Historial de transacciones:', estado.transactionHistory);

});

Paso 1: Preparar una Transferencia

javascriptimport { nativeToken } from '@midnight-ntwrk/zswap';



// ⚠️ IMPORTANTE: Asegúrate que la billetera haya sincronizado completamente

// antes de preparar una transacción. De lo contrario, podrías intentar gastar

// una moneda que ya fue gastada pero tu billetera aún no lo sabe.



const recetaTransferencia = await billetera.transferTransaction([

{

amount: 1n, // Cantidad en satoshis (BigInt)

type: nativeToken(), // Tipo de token (tDUST)

receiverAddress: 'mn_shield-addr_test1kj...' // Dirección del receptor

}

]);



console.log('Receta de transferencia preparada');

Paso 2: Balancear una Transacción Existente

Balancear una transacción significa ajustarla para cubrir las comisiones y equilibrar entradas/salidas:

javascriptconst transaccionBalanceada = await billetera.balanceTransaction(

transaccionExistente,

[] // newCoins (opcional) - para monedas nuevas creadas por DApps

);



console.log('Transacción balanceada');

Paso 3: Generar Pruebas de Conocimiento Cero

Este paso es computacionalmente intensivo y puede tomar varios segundos:

javascriptimport { TRANSACTION_TO_PROVE } from '@midnight-ntwrk/wallet-api';



// Crear la receta (wrapper) de la transacción

const receta = {

type: TRANSACTION_TO_PROVE,

transaction: recetaTransferencia

};



// Generar pruebas (⚠️ Esto es MUY lento - puede tomar decenas de segundos)

console.time('Generación de pruebas');

const transaccionComprobada = await billetera.proveTransaction(receta);

console.timeEnd('Generación de pruebas');



console.log('Pruebas generadas exitosamente');

Paso 4: Enviar la Transacción

javascript// La transacción debe estar:

// 1. Balanceada (entradas ≥ salidas + comisiones)

// 2. Comprobada (pruebas generadas)



const transaccionEnviada = await billetera.submitTransaction(

transaccionComprobada

);



console.log('Transacción enviada:', transaccionEnviada);

console.log('Hash de transacción:', transaccionEnviada.id);



Conectar con DApps

Las aplicaciones descentralizadas se conectan a la billetera a través del API de DApp Connector. La billetera se inyecta en el contexto del navegador, permitiendo que las DApps soliciten operaciones como:



Obtener dirección del usuario

Firmar transacciones

Enviar tokens

Ejecutar contratos inteligentes



Consulta:



DApp Connector Overview

Wallet Provider para más detalles técnicos



Ejemplos Prácticos

Ejemplo 1: Transferencia Básica de tDUST

Este ejemplo crea una billetera, sincroniza con la cadena y envía 1 tDUST a otra dirección:

javascriptimport { WalletBuilder } from '@midnight-ntwrk/wallet';

import { NetworkId, nativeToken } from '@midnight-ntwrk/zswap';



async function transferirTDUST() {

try {

// 1. Crear billetera

console.log('📱 Creando billetera...');

const billetera = await WalletBuilder.build(

'https://indexer.testnet-02.midnight.network/api/v1/graphql',

'wss://indexer.testnet-02.midnight.network/api/v1/graphql/ws',

'http://localhost:6300',

'https://rpc.testnet-02.midnight.network',

'0000000000000000000000000000000000000000000000000000000000000000',

NetworkId.TestNet

);




// 2. Iniciar sincronización
console.log('🔄 Iniciando sincronización...');
billetera.start();

// Esperar a que sincronice (en producción, implementa mejor lógica de espera)
await new Promise(resolve => setTimeout(resolve, 5000));

// 3. Preparar transferencia
console.log('💸 Preparando transferencia...');
const recetaTransferencia = await billetera.transferTransaction([
{
amount: 1n,
type: nativeToken(),
receiverAddress: 'mn_shield-addr_test1kjwksfp8x2tachehsfvufsdl35ljg5cxzdcysjdn6ntadspyxn3qxqrxypgjm055c2azrpuyn7un0ge2vm25vkfv38d24rj3ewcku5wmdc94gjr9'
}
]);

// 4. Generar pruebas
console.log('⚙️ Generando pruebas de conocimiento cero (esto puede tomar un tiempo)...');
const transaccionComprobada = await billetera.proveTransaction(recetaTransferencia);

// 5. Enviar transacción
console.log('📤 Enviando transacción...');
const resultado = await billetera.submitTransaction(transaccionComprobada);

console.log('✅ ¡Transacción enviada exitosamente!');
console.log('ID de transacción:', resultado.id);

// 6. Cerrar billetera
await billetera.close();
console.log('🔐 Billetera cerrada');




} catch (error) {

console.error('❌ Error:', error.message);

}

}



// Ejecutar

transferirTDUST();

Ejemplo 2: Guardar y Restaurar Billetera

javascriptimport { WalletBuilder } from '@midnight-ntwrk/wallet';

import { NetworkId } from '@midnight-ntwrk/zswap';

import { generateRandomSeed } from '@midnight-ntwrk/wallet-sdk-hd';

import * as fs from 'fs';



async function guardarYRestaurarBilletera() {

const ruutaArchivo = './billetera_snapshot.json';

const semilla = generateRandomSeed();



try {

// 1. Crear billetera original

console.log('📱 Creando billetera original...');

const billetera = await WalletBuilder.build(

'https://indexer.testnet-02.midnight.network/api/v1/graphql',

'wss://indexer.testnet-02.midnight.network/api/v1/graphql/ws',

'http://localhost:6300',

'https://rpc.testnet-02.midnight.network',

semilla,

NetworkId.TestNet

);




billetera.start();

// Esperar sincronización
await new Promise(resolve => setTimeout(resolve, 3000));

// 2. Guardar instantánea
console.log('💾 Guardando instantánea...');
const estadoSerializado = await billetera.serialize();
fs.writeFileSync(ruutaArchivo, JSON.stringify({
estado: estadoSerializado,
semilla: Buffer.from(semilla).toString('hex')
}, null, 2));

await billetera.close();
console.log('✅ Instantánea guardada en:', ruutaArchivo);

// 3. Restaurar desde instantánea
console.log('📂 Leyendo instantánea...');
const datos = JSON.parse(fs.readFileSync(ruutaArchivo, 'utf-8'));

console.log('🔄 Restaurando billetera...');
const billetera_restaurada = await WalletBuilder.restore(
'https://indexer.testnet-02.midnight.network/api/v1/graphql',
'wss://indexer.testnet-02.midnight.network/api/v1/graphql/ws',
'http://localhost:6300',
'https://rpc.testnet-02.midnight.network',
Buffer.from(datos.semilla, 'hex'),
datos.estado
);

billetera_restaurada.start();
console.log('✅ Billetera restaurada exitosamente');

// Verificar estado
billetera_restaurada.state().subscribe((estado) => {
console.log('Estado restaurado - Monedas:', estado.coins);
});

await billetera_restaurada.close();




} catch (error) {

console.error('❌ Error:', error.message);

}

}



guardarYRestaurarBilletera();

Ejemplo 3: Monitorear Estado en Tiempo Real

javascriptimport { WalletBuilder } from '@midnight-ntwrk/wallet';

import { NetworkId } from '@midnight-ntwrk/zswap';

import { debounceTime, distinctUntilChanged } from 'rxjs/operators';



async function monitorearBilletera() {

try {

const billetera = await WalletBuilder.build(

'https://indexer.testnet-02.midnight.network/api/v1/graphql',

'wss://indexer.testnet-02.midnight.network/api/v1/graphql/ws',

'http://localhost:6300',

'https://rpc.testnet-02.midnight.network',

'0000000000000000000000000000000000000000000000000000000000000000',

NetworkId.TestNet

);




billetera.start();

// Monitorear cambios de estado con debounce
billetera.state()
.pipe(
debounceTime(1000), // Esperar 1 segundo sin cambios
distinctUntilChanged((a, b) => // Solo si realmente cambió
JSON.stringify(a) === JSON.stringify(b)
)
)
.subscribe((estado) => {
console.log('\n📊 === ESTADO ACTUALIZADO ===');
console.log('Monedas disponibles:', estado.coins.length);
console.log('Saldo total:', estado.coins.reduce((sum, c) => sum + c.amount, 0n));
console.log('Transacciones procesadas:', estado.transactionHistory.length);
console.log('Última transacción:',
estado.transactionHistory[0]?.date || 'Ninguna');
});

// Mantener proceso activo
console.log('👀 Monitoreando billetera (Ctrl+C para salir)...');




} catch (error) {

console.error('❌ Error:', error.message);

}

}



monitorearBilletera();



Buenas Prácticas y Recomendaciones




  1. Sincronización Completa Antes de Transacciones
    javascript// ❌ INCORRECTO
    const receta = await billetera.transferTransaction([...]);



// ✅ CORRECTO

// Esperar a que la billetera esté sincronizada

await new Promise(resolve =>

billetera.state()

.pipe(filter(s => s.isSynced))

.subscribe(() => resolve())

);

const receta = await billetera.transferTransaction([...]);




  1. Gestión Segura de Semillas
    javascript// ❌ INCORRECTO
    const semilla = "0000000000..."; // Hardcodeada



// ✅ CORRECTO

const semilla = process.env.WALLET_SEED; // Variables de entorno

// O

const semilla = await obtenerDelAlfiler(); // Sistema seguro de almacenamiento




  1. Manejo de Errores Robusto
    javascripttry {
    const transaccion = await billetera.proveTransaction(receta);
    } catch (error) {
    if (error.message.includes('insufficient')) {
    console.error('Saldo insuficiente');
    } else if (error.message.includes('timeout')) {
    console.error('Servidor de pruebas no disponible');
    } else {
    console.error('Error desconocido:', error);
    }
    }

  2. Cierre Adecuado de Recursos
    javascriptasync function operacionConBilletera() {
    const billetera = await WalletBuilder.build(...);
    try {
    billetera.start();
    // Tu código aquí
    } finally {
    await billetera.close(); // Siempre cerrar
    }
    }

  3. Timeouts en Operaciones Largas
    javascriptimport { timeout } from 'rxjs/operators';



const transaccionConTimeout = billetera.proveTransaction(receta)

.pipe(timeout(60000)); // 60 segundos máximo



Parámetros de Configuración

WalletBuilder.build() - Parámetros Obligatorios

ParámetroTipoDescripciónIndexer URLStringURL del API GraphQL del indexadorIndexer WebSocket URLStringURL WebSocket del indexadorProving Server URLStringURL del servidor de pruebasNode URLStringURL del nodo RPCSeedStringSemilla de 256 bits en hexNetwork IDNetworkIdTestNet, MainNet, etc.

Parámetros Opcionales

ParámetroTipoDefaultDescripciónLog LevelLogLevelwarnerror, warn, info, debugDiscard Transaction HistoryBooleanfalseDescartar historial de transacciones



Troubleshooting

Problema: "Error derivando clave"

Solución: Verifica que la semilla sea de 256 bits (64 caracteres hex)

Problema: Transacción rechazada por "double spend"

Solución: Asegúrate de que la billetera esté completamente sincronizada

antes de preparar la transacción

Problema: Servidor de pruebas no disponible

Solución: Verifica que el servidor de pruebas esté corriendo en localhost:6300

o usa URL correcta en la configuración

Problema: "secret keys are no longer included"

Solución: Proporciona la semilla original al restaurar desde instantánea



Recursos Adicionales



Documentación Oficial: https://docs.midnight.network

GitHub: https://github.com/midnight-ntwrk

API Reference: Consulta la documentación de @midnight-ntwrk/wallet

Ejemplos: Revisa los ejemplos incluidos en el repositorio



Conclusión

El Midnight Wallet SDK proporciona una forma robusta y segura de integrar funcionalidad de billetera en aplicaciones blockchain. Recuerda siempre:



✅ Gestiona las semillas de forma segura

✅ Sincroniza completamente antes de transacciones

✅ Cierra recursos adecuadamente

✅ Implementa manejo robusto de errores

✅ Prueba ampliamente antes de producción

2. Cyber Threat Intelligence & Forensik

IoC Intelligence (2 Indikatoren)
0000000000000000000000000000000000000000000000000000000000000000064e092a80b33bee23404c46cfc48fec75a2356a9b01178dd6a62c29f5896f67
CTI Threat Relationship Graph4 Knoten / 3 Relationen
CVE / Incident Software MITRE ATT&CK CWE Weakness IoC
Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten Tutorial: Midnight Wallet SDK - Guía Completa para Desarrolladores

Thematisch verwandte Begriffe: Tutorial, Midnight, Wallet, Guía · 6 Treffer

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

💬 Kommentare werden geladen…
Zum Aktualisieren ziehen
tsecurity.de Icon
Offline-Lesen, Eilmeldungen & 0ms Ladezeit

Installiere tsecurity.de direkt auf deinen Home-Bildschirm für das ultimative Vollbild-Magazinerlebnis ohne Browser-Leisten.

Nächster Beitrag