Saltar al contenido principal

Self-Custody

Self-Custody es el modelo de ejecución real, en operación hoy en la plataforma — el único ExecutionCustodyMode que realmente puede seleccionarse para cualquier Environment, Sandbox o Production. Bajo Self-Custody, la plataforma nunca guarda una clave privada en su nombre — la wallet se genera y controla enteramente de su lado, a través de uno de los SDKs oficiales.

ExecutionCustodyMode también declara ManagedCustody, ExternalCustody y SmartContractEscrow a nivel de dominio — preservados arquitectónicamente (para que el historial propio de la plataforma y herramientas internas, como TreasuryReconciliation, sigan funcionando contra ese vocabulario), pero ninguno de ellos puede activarse: configurar el modo de un Environment en cualquier valor distinto de Self-Custody se rechaza de inmediato. Trate esos tres como reservados, no como opciones de configuración disponibles hoy.

Cómo funciona

  1. Generación local de la wallet. El SDK genera un mnemonic BIP39 y deriva una clave extendida BIP32 localmente (ruta BIP44 m/44'/195'/0', coin_type de TRON = 195). La clave privada se crea y se usa enteramente dentro de su proceso — nunca se transmite, registra, ni persiste por el SDK por su cuenta (INV-SC-01).
  2. Registro público. Solo la clave pública extendida (xpub) resultante se envía a la API — POST /v1/applications/{applicationId}/wallets. La plataforma puede derivar direcciones a partir de ella, pero nunca puede firmar con ella.
  3. Asignación de dirección de depósito. La plataforma deriva una dirección TRON real de depósito a partir del xpub registrado (POST .../wallets/deposit-addresses) — el mismo SDK puede re-derivar y verificar esa dirección localmente, de forma independiente, como una verificación de defensa en profundidad contra un backend comprometido.
  4. Firma de múltiples Legs. Un SigningRequest describe una o más ExecutionLegs (por ejemplo, una Leg de Seller y una Leg de Platform Fee del mismo Settlement). Para cada Leg, el backend calcula un hash canónico determinístico del contenido exacto de la transacción; el SDK firma ese hash localmente con la clave privada y envía la firma de vuelta (POST .../legs/{executionLegId}/submit). El backend verifica cada firma de forma independiente contra el mismo hash canónico antes de aceptarla — un monto o destino alterado produce un hash distinto y es rechazado de inmediato.
  5. All-signatures gate. Ninguna Leg se transmite (broadcast) a la red hasta que todas las Legs del SigningRequest tengan una firma verificada. La primera firma sola nunca dispara un broadcast — solo la última lo dispara, para todas las Legs a la vez.

Financiamiento multi-source

Un Settlement puede financiarse con más de una dirección de depósito confirmada — soportado: produce un SigningRequest por cada fuente física de financiamiento (SettlementResponse.signingRequestIds, plural), firma y confirma cada uno. Un Withdrawal siempre proviene de un único SigningRequest — el financiamiento multi-source no está soportado para Withdrawal hoy (Withdrawal.signingRequestId sigue siendo solo singular); no construyas una integración que asuma paridad aquí.

Lo que nunca sucede

  • La clave privada nunca se envía a la API, en ninguna solicitud, en ninguna etapa.
  • Ninguna Leg se transmite antes de que todas las Legs estén firmadas y verificadas.
  • Una firma nunca se acepta sin recalcular y comparar el hash canónico de forma independiente en el servidor.

Errores

Una firma enviada para una Leg cuyo hash recalculado no coincide se rechaza con SIGNED_TRANSACTION_MISMATCH — la Leg nunca se transmite. Una razón de discrepancia más granular (monto, participante, red o activo) es una extensión futura documentada; hoy la verificación es una única comparación de hash opaco, que ya cubre la invariante de seguridad central: una transacción alterada nunca pasa la verificación, sea cual sea el campo específico modificado.

Disponible hoy

La generación de wallets Self-Custody, el registro, la asignación de dirección de depósito y el protocolo completo de firma de múltiples Legs — hash canónico, verificación de firma, el gate de todas-las-firmas y el broadcast — están implementados y validados de extremo a extremo en Sandbox, a través de los cuatro SDKs oficiales (Java, Node.js/TypeScript, Python, Go) — cada uno incluye un ejemplo completo y ejecutable (13-self-custody-signing). Vea la guía del recorrido de marketplace para este protocolo conectado de extremo a extremo con un pago real — registro, Payment Intent, depósito, y un payout firmado localmente — no solo el paso de firma de forma aislada.

La creación de SigningRequest ya está conectada automáticamente tanto a Settlement como a Withdrawals — confirmado en vivo: executeSettlement() y withdrawals.request() construyen el SigningRequest/las ExecutionLegs por su cuenta, a partir de los beneficiarios y montos ya presentes en el Settlement/Withdrawal; un integrador nunca construye un SigningRequest manualmente para esos flujos (la ruta directa POST .../signing-requests de abajo sigue existiendo para otros usos, de nivel más bajo). El seguimiento de confirmación de broadcast también es automático, orientado a eventos de extremo a extremo — en cuanto todas las Legs están firmadas y el all-signatures gate dispara el broadcast, la propia plataforma observa la confirmación (simulada en Sandbox) y mueve el Settlement/Withdrawal a su estado terminal; el integrador nunca hace polling directo a un nodo de blockchain para esto.

Dos cosas deben registrarse una vez por Organization/AssetNetwork antes de que la primera ejecución real en Self-Custody pueda completarse: un ExecutionDestination para cada beneficiario que recibe pago (incluyendo el propio Fee de la plataforma, bajo un Settlement), y un NetworkCostPayerAccount para cubrir los recursos de red reales que consume un broadcast (vea Transaction, Settlement, Split y Refund para ambos, y Network Execution para ExecutionSource — un tercer registro relacionado, fácil de confundir con los otros dos). La ejecución real de blockchain — una transacción que efectivamente llega a una red real — es exclusiva de Production y todavía no está disponible; el broadcast y la confirmación en Sandbox se simulan de extremo a extremo.

Rutas

  • Registrar una wallet: POST /v1/applications/{applicationId}/wallets
  • Asignar una dirección de depósito: POST /v1/applications/{applicationId}/wallets/deposit-addresses
  • Obtener una wallet: GET /v1/wallets/{walletId} (y /public-material)
  • Crear un signing request: POST /v1/environments/{environmentId}/signing-requests
  • Obtener un signing request: GET /v1/signing-requests/{signingRequestId}
  • Enviar una Leg firmada: POST /v1/signing-requests/{signingRequestId}/legs/{executionLegId}/submit