Pular para o conteúdo principal

Self-Custody

Self-Custody é o modelo de execução real, em operação hoje na plataforma — o único ExecutionCustodyMode que pode de fato ser selecionado para qualquer Environment, Sandbox ou Production. Sob Self-Custody, a plataforma nunca guarda uma chave privada em seu nome — a wallet é gerada e controlada inteiramente do seu lado, através de um dos SDKs oficiais.

ExecutionCustodyMode também declara ManagedCustody, ExternalCustody e SmartContractEscrow no nível de domínio — preservados arquiteturalmente (para que o histórico da própria plataforma e ferramentas internas, como TreasuryReconciliation, continuem funcionando contra esse vocabulário), mas nenhum deles pode ser ativado: configurar o modo de um Environment para qualquer valor diferente de Self-Custody é rejeitado de imediato. Trate esses três como reservados, não como opções de configuração disponíveis hoje.

Como funciona

  1. Geração local da wallet. O SDK gera um mnemonic BIP39 e deriva uma chave estendida BIP32 localmente (path BIP44 m/44'/195'/0', coin_type TRON = 195). A chave privada é criada e usada inteiramente dentro do seu processo — nunca é transmitida, logada, ou persistida pelo SDK por conta própria (INV-SC-01).
  2. Registro público. Só a chave pública estendida (xpub) resultante é enviada à API — POST /v1/applications/{applicationId}/wallets. A plataforma consegue derivar endereços a partir dela, mas nunca consegue assinar com ela.
  3. Alocação de endereço de depósito. A plataforma deriva um endereço TRON real de depósito a partir do xpub registrado (POST .../wallets/deposit-addresses) — o mesmo SDK consegue re-derivar e verificar esse endereço localmente, de forma independente, como uma verificação de defesa em profundidade contra um backend comprometido.
  4. Assinatura de múltiplas Legs. Um SigningRequest descreve uma ou mais ExecutionLegs (por exemplo, uma Leg do Seller e uma Leg de Platform Fee do mesmo Settlement). Para cada Leg, o backend calcula um hash canônico determinístico do conteúdo exato da transação; o SDK assina esse hash localmente com a chave privada e submete a assinatura de volta (POST .../legs/{executionLegId}/submit). O backend verifica cada assinatura de forma independente contra o mesmo hash canônico antes de aceitá-la — um valor ou destino adulterado produz um hash diferente e é rejeitado de imediato.
  5. All-signatures gate. Nenhuma Leg é transmitida (broadcast) para a rede até que todas as Legs do SigningRequest tenham uma assinatura verificada. A primeira assinatura sozinha nunca dispara um broadcast — só a última dispara, para todas as Legs de uma vez.

Financiamento multi-source

Um Settlement pode ser financiado por mais de um endereço de depósito confirmado — suportado: produz um SigningRequest por fonte física de financiamento (SettlementResponse.signingRequestIds, plural), assine e confirme cada um. Um Withdrawal sempre vem de um único SigningRequest — financiamento multi-source não é suportado para Withdrawal hoje (Withdrawal.signingRequestId continua só singular); não construa uma integração que presuma paridade aqui.

O que nunca acontece

  • A chave privada nunca é enviada à API, em nenhuma requisição, em nenhuma etapa.
  • Nenhuma Leg é transmitida antes de todas as Legs estarem assinadas e verificadas.
  • Uma assinatura nunca é aceita sem recalcular e comparar o hash canônico de forma independente no lado do servidor.

Erros

Uma assinatura submetida para uma Leg cujo hash recalculado não corresponde é rejeitada com SIGNED_TRANSACTION_MISMATCH — a Leg nunca é transmitida. Uma razão de mismatch mais granular (valor, participante, rede ou ativo) é uma extensão futura documentada; hoje a verificação é uma única comparação de hash opaco, que já cobre a invariante de segurança central: uma transação adulterada nunca passa pela verificação, seja qual for o campo específico alterado.

Disponível hoje

Geração de wallet Self-Custody, registro, alocação de endereço de depósito e o protocolo completo de assinatura de múltiplas Legs — hash canônico, verificação de assinatura, gate de todas-as-assinaturas e broadcast — estão implementados e validados de ponta a ponta em Sandbox, através dos quatro SDKs oficiais (Java, Node.js/TypeScript, Python, Go) — cada um traz um exemplo completo e executável (13-self-custody-signing). Veja o guia da jornada de marketplace para esse protocolo conectado de ponta a ponta com um pagamento real — cadastro, Payment Intent, depósito, e um payout assinado localmente — não apenas a etapa de assinatura isolada.

A criação de SigningRequest já está conectada automaticamente tanto a Settlement quanto a Withdrawals — confirmado ao vivo: executeSettlement() e withdrawals.request() constroem o SigningRequest/as ExecutionLegs por conta própria, a partir dos beneficiários e valores já presentes no Settlement/Withdrawal; um integrador nunca constrói um SigningRequest manualmente para esses fluxos (a rota direta POST .../signing-requests abaixo ainda existe para outros usos, de nível mais baixo). O acompanhamento de confirmação de broadcast também é automático, orientado a eventos de ponta a ponta — assim que todas as Legs estão assinadas e o all-signatures gate dispara o broadcast, a própria plataforma observa a confirmação (simulada em Sandbox) e move o Settlement/Withdrawal para seu estado terminal; o integrador nunca faz polling direto em um nó de blockchain para isso.

Duas coisas precisam ser registradas uma vez por Organization/AssetNetwork antes que a primeira execução real em Self-Custody possa se completar: um ExecutionDestination para cada beneficiário que recebe pagamento (incluindo o próprio Fee da plataforma, sob um Settlement), e um NetworkCostPayerAccount para cobrir os recursos de rede reais que um broadcast consome (ver Transaction, Settlement, Split e Refund para ambos, e Network Execution para ExecutionSource — um terceiro registro relacionado, fácil de confundir com os outros dois). Execução real de blockchain — uma transação de fato chegando a uma rede real — é exclusiva de Production e ainda não está disponível; o broadcast e a confirmação em Sandbox são simulados de ponta a ponta.

Rotas

  • Registrar uma wallet: POST /v1/applications/{applicationId}/wallets
  • Alocar um endereço de depósito: POST /v1/applications/{applicationId}/wallets/deposit-addresses
  • Obter uma wallet: GET /v1/wallets/{walletId} (e /public-material)
  • Criar um signing request: POST /v1/environments/{environmentId}/signing-requests
  • Obter um signing request: GET /v1/signing-requests/{signingRequestId}
  • Submeter uma Leg assinada: POST /v1/signing-requests/{signingRequestId}/legs/{executionLegId}/submit