Enviar y recibir pagos de Cuentas de Contrato
Los pagos entre Cuentas de Contrato (direcciones C) y Cuentas Clásicas (direcciones G) están admitidos a nivel de protocolo, pero existen diferencias en las implementaciones necesarias para admitirlas. Esta guía cubrirá implementaciones para aplicaciones que usan cuentas clásicas G y desean admitir transacciones con Cuentas de Contrato.
Recibir pagos de Cuentas de Contrato (de C a G)
Si un remitente está usando una Cuenta de Contrato y envía un token SAC (como XLM, USDC, etc.), la transacción será recibida normalmente por la cuenta G ya que está soportada a nivel de protocolo.
Recibir pagos de Cuentas de Contrato que requieren un memo
Entidades como exchange y emisores de activos suelen usar cuentas omnibus, utilizando una dirección de recepción compartida y un memo identificador único, como:
- Cuenta:
GBLVHX33XGOBDOXK7ERDL34NVH6WW7VTT2OBAHPJ7G3D423HBG5NOMY7 - ID de Memo:
123456789
Las transacciones que involucran Cuentas de Contrato utilizan invocaciones de contrato para ejecutar una función 'transfer' en el contrato del activo. Este tipo de transacción no permite usar el campo 'memo'; en cambio, la aplicación emisora lo codificará en la dirección, generando una dirección multiplexada única que incluye la cuenta receptora (GBLVHX…) y el id proporcionado en el campo muxed id (123456789).
Para admitir depósitos provenientes de Cuentas de Contrato, no es necesario cambiar la información mostrada a los clientes ni las cuentas de depósito usadas por el exchange. Las billeteras seguirán usando la cuenta G y el memo proporcionado para enviar un pago a la cuenta G del exchange incluyendo el memo con el ID único.
Esa es la principal diferencia entre recibir de clientes usando cuentas G o de Contrato: en lugar de mirar el campo memo para identificar la cuenta individual, observarás el ID multiplexado. Todo lo demás permanece igual.
Ejemplo usando Horizon
Recibiendo de una dirección G
Usando el endpoint accounts/{acc_id}/transactions de Horizon (ejemplo)
El campo memo estará presente en la respuesta.
Ejemplo de respuesta desde una dirección G:
{
"memo": "123456789",
"memo_bytes": "MTIzNDU2Nzg5",
"source_account": "GCNG5JXJY3LNRMXCX23RIGKTURQACTSV5LL6NKL535BYRGOGWUX6J45Y",
"memo_type": "text"
}
Recibir desde una Cuenta de Contrato
Usando el endpoint accounts/{acc_id}/payments de Horizon (ejemplo)
Después de que se procesa la transacción, este detalle de pago estará presente en el endpoint '/payments', bajo una sección llamada 'asset_balance_changes', que mostrará el ID codificado y la dirección G subyacente por separado.
Es importante destacar que la sección 'asset_balance_changes' solo soporta activos Stellar y transacciones que usan la función transfer en el Contrato de Activos Stellar (SAC).
Respuesta de ejemplo desde una Cuenta de Contrato:
{
"asset_balance_changes": [
{
"asset_type": "native",
"type": "transfer",
"from": "CBP4GFAK4GDKCMVLNIHRZPEAPT7CFYTBKICOXCVMP2FEN3QFKCRZ27KS",
"to": "GBLVHX33XGOBDOXK7ERDL34NVH6WW7VTT2OBAHPJ7G3D423HBG5NOMY7",
"amount": "1.0000000",
"destination_muxed_id": "123456789"
}
]
}
Para un ejemplo de código detallado, consulta la sección 'Monitoreo de Pagos -> Usando la API de Horizon' de los ejemplos de este repositorio.
Ejemplo usando RPC
Desde el lanzamiento de los Eventos de Activos Unificados (CAP-67) en el Protocolo 23, varias transacciones que involucran activos Stellar emiten eventos estandarizados que pueden ser ingeridos tanto por la API de Horizon como por el Stellar RPC. Si los fondos se envían a través de una operación 'payment' o invocando la función 'transfer' del contrato de activos, se emite el mismo tipo de evento para ambos casos.
Para monitorear estos pagos, se usa el método 'getEvents' del RPC de Stellar para transmitir eventos emitidos por el Contrato de Activos Stellar. Se puede usar un filtro para especificar el activo objetivo (ID del contrato SAC) y las cuentas.
Desde una dirección G
Cuando el receptor es una dirección G normal, la parte valor del evento es simplemente la cantidad recibida.
{
"inSuccessfulContractCall": true,
"topicJson": [
{
"symbol": "transfer"
},
{
"address": "GD6MYLASTCZ3H4UFLH2YSIASHJNBFUCKC5YHGU44VCH2BGHN3WJQX6LG"
},
{
"address": "GA4PDUF3BLBSK47UTNY44AIZAP5EPHW2UIJRKB5HN76HHC55IWKSIHFD"
},
{
"string": "native"
}
],
"valueJson": {
"i128": "10000000"
}
}
Desde una Cuenta de Contrato
Cuando la transacción se envía usando una cuenta muxed, la parte valor del evento se desglosa en un objeto que contiene la cantidad y el ID único codificado en la dirección.
{
"inSuccessfulContractCall": true,
"topicJson": [
{
"symbol": "transfer"
},
{
"address": "GD6MYLASTCZ3H4UFLH2YSIASHJNBFUCKC5YHGU44VCH2BGHN3WJQX6LG"
},
{
"address": "GA4PDUF3BLBSK47UTNY44AIZAP5EPHW2UIJRKB5HN76HHC55IWKSIHFD"
},
{
"string": "native"
}
],
"valueJson": {
"map": [
{
"key": {
"symbol": "amount"
},
"val": {
"i128": "10000000"
}
},
{
"key": {
"symbol": "to_muxed_id"
},
"val": {
"u64": "123456789"
}
}
]
}
}
Para un ejemplo de código detallado, consulta la sección ‘Monitoreo de Pagos -> Uso del Stellar RPC’ de los ejemplos de este repositorio.
Envío de pagos desde Cuentas de Contrato a un destinatario que requiere un memo
Si un remitente está usando una Cuenta de Contrato y está enviando un token SAC (como XLM, USDC, etc.) a un destinatario que requiere un memo (por ejemplo, un exchange), debe crear una dirección muxed que incluya la cuenta receptora (GBLVHX…) y la id de memo proporcionada en el campo de id muxed (123456789). En la interfaz de usuario, la dirección de memo resultante no necesita mostrarse al usuario, debe usarse directamente en la transacción.
Si la parte receptora ya proporciona una dirección M, debe utilizarse directamente, sin necesitar un campo de memo. Como este es el valor proporcionado por el usuario, debe usarse en la transacción y mostrarse al usuario.
Envío de pagos a Cuentas de Contrato (de G a C)
Enviar un ‘transfer’ mediante Stellar RPC
Este método es más sencillo pero requiere el uso de un RPC e implica un flujo de transacciones algo diferente al de una operación nativa tradicional. Para un ejemplo de código detallado, consulta la sección ‘Enviando pagos a través del SAC -> Uso del Stellar RPC’ de los ejemplos de este repositorio.
Ensambla la operación y la transacción
Para realizar un ‘transfer’ a través de un SAC, es necesario ensamblar una operación ‘InvokeHostFunctionOp’ con argumentos similares a una operación de ‘payment’, junto con el identificador del contrato y el nombre de la función objetivo (‘transfer’).
Esto puede verse en detalle en la función ‘assembleTransferOperation’ del demo. Aunque el ejemplo muestra este proceso con mayor detalle, es posible usar el js-stellar-sdk y su cliente de Contrato de manera más simple.
Luego la transacción se desarrolla añadiendo esta operación y configurando los parámetros adicionales como en cualquier otra transacción ‘payment’.
Simular la transacción
Después de construir la transacción, se utiliza el método RPC ‘simulateTransaction’ para simular la ejecución de esta transacción contra el estado actual de la red, identificar si se espera que tenga éxito y, además, proporcionar varios parámetros adicionales sobre esta ejecución.
Este proceso es completamente manejado por el SDK en un paso muy simple usando la función ‘prepareTransaction’ del cliente del servidor RPC. Automáticamente simula y proporciona un objeto de transacción actualizado. Consulta este proceso en detalle en el demo.
Firmar
Cuando la misma cuenta se usa como ‘remitente’ de los fondos y también como ‘origen’ de la transacción, el paso de la firma será exactamente el mismo. Una vez que se recibe el objeto de transacción actualizado del paso anterior, solo debes firmarlo con la cuenta fuente/remitente y estará listo.
Cuando la cuenta ‘fuente’ de la transacción difiere de la cuenta ‘remitente’, será necesaria una entrada firmada adicional para autorizar explícitamente la invocación ‘transfer’. Consulta la documentación del Marco de Autorización Soroban para más detalles.
Enviar la transacción para procesamiento
Cuando una transacción se envía para procesamiento a través del RPC de Stellar, a diferencia de la API Horizon, se resolverá inmediatamente confirmando su envío pero no su procesamiento. Es necesario consultar el estado de la transacción periódicamente hasta obtener una confirmación de que fue procesada exitosamente o una actualización del estatus en caso de falla.
Envío de un ‘transfer’ vía API Horizon
Al enviar un ‘transfer’ vía API Horizon, este método introduce algunos pasos adicionales en comparación con el uso de un RPC. Para un ejemplo de código detallado, consulta la sección ‘Enviando pagos a través del SAC -> Uso de la API Horizon’ de los ejemplos de este repositorio.
Ensambla la operación y la transacción
Este proceso es casi el mismo que se describe en la sección anterior ‘Enviar un ‘transfer’ mediante Stellar RPC’ con algunas modificaciones menores. Dado que la API de Horizon no provee un endpoint para simular la ejecución de una transacción, esto significa que cuando se arma la transacción necesitamos asegurarnos también de que contiene:
- Las entradas de autorización Soroban que cumplen con los requisitos de autorización de los contratos inteligentes.
- El objeto Soroban data, que detalla la huella, los recursos y la tarifa de recursos esperada para esta invocación de contrato.
Estos normalmente se completan automáticamente basados en la salida de la simulación y simplemente firmando y agregando las entradas de autorización generadas por el RPC. Aquí, necesitamos incluirlos manualmente.
Las entradas de autenticación pueden predecirse y armarse fácilmente según la configuración. Asumiendo que la cuenta ‘remitente’ es la misma que la cuenta ‘fuente’ de la transacción, se necesita agregar una credencial de cuenta fuente a la operación, indicando que esta invocación usará la misma firma del sobre para autorizar el ‘transfer’. Consulta este proceso en detalle en la función ‘assembleSourceAuthEntry’ del demo.
Una vez que las entradas de autenticación están armadas y firmadas (cuando no son entradas ‘source-account’), deben incluirse en la operación, en el parámetro ‘auth’.
Por otro lado, el proceso para el Soroban Data puede ser un poco más difícil de ejecutar manualmente. Considerando que todos los contratos SAC usan la misma implementación nativa, podemos esperar que todas las invocaciones ‘transfer’ sean muy similares.
La cantidad de recursos consumidos no debería variar mucho salvo algunos casos excepcionales como transacciones que involucran entradas archivadas o una autorización personalizada para una billetera inteligente como remitente. Consulta este proceso de armado manual del Soroban Data en la función ’getSorobanData’ del demo.
Una vez armado el Soroban Data, se incluye en el Constructor de Transacciones.
Firmar
Después de construir la transacción, asumiendo que las ‘entradas de autorización’ del paso anterior fueron configuradas correctamente, la transacción puede firmarse normalmente por la cuenta origen.
Enviar la transacción para procesamiento
Este paso es el mismo que cualquier transacción enviada a través de la API Horizon.
Guías en esta categoría:
📄️ Crear una cuenta
Aprende sobre cómo crear cuentas Stellar, pares de llaves, financiamiento y conceptos básicos de las cuentas.
📄️ Enviar y recibir pagos de Cuentas de Contrato
Aprende a enviar pagos a y recibir pagos de Cuentas de Contrato en la red Stellar.
📄️ Enviar y recibir pagos
Aprende a enviar pagos y estar atento a los pagos recibidos en la red Stellar.
📄️ Cuentas canalizadas
Crea cuentas canalizadas para enviar transacciones a la red a una alta velocidad.
📄️ Saldos reclamables
Divide un pago en dos partes creando un saldo reclamable.
📄️ Recuperaciones
Usa las recuperaciones para quemar una cantidad específica de un activo habilitado para recuperación desde una trustline o un saldo reclamable.
📄️ Transacciones de suplemento de tarifa
Usa transacciones fee-bump para pagar las comisiones de transacción en nombre de otra cuenta sin volver a firmar la transacción.
📄️ Reservas patrocinadas
Utiliza las reservas patrocinadas para pagar las reservas base en nombre de otra cuenta.
📄️ Pagos con rutas
Enviar un pago donde el activo recibido sea diferente del activo enviado.
📄️ Cuentas agrupadas: cuentas muxed y memos
Usa cuentas muxed para diferenciar entre cuentas individuales dentro de una cuenta agrupada.
📄️ Instalar y desplegar un contrato inteligente con código
Instalar y desplegar un contrato inteligente con código.
📄️ Invocar una función de contrato en una transacción usando SDKs
Usa el Stellar SDK para crear, simular y ensamblar una transacción.
📄️ guía del método RPC simulateTransaction
Guía de ejemplos y tutoriales de simulateTransaction.
📄️ Enviar una transacción a Stellar RPC utilizando el SDK de JavaScript
Utiliza un mecanismo de repetición para enviar una transacción al RPC.
📄️ Subir código byte de WebAssembly (Wasm) usando código
Sube el Wasm del contrato usando js-stellar-sdk.