Conta TRON não ativada: o que ela trava e como resolver
Um endereço é um par de chaves até a rede ter uma conta para ele. É isso a “conta TRON não ativada” por inteiro, e é a resposta que surpreende as pessoas: o endereço está bem formado, a carteira o exibe, o QR code lê, e a cadeia nunca ouviu falar dele. Para uma mesa de pagamentos o estado aparece em dois lugares diferentes — a carteira que envia e o endereço que está sendo pago — e só um dos dois é uma recusa.
O que ativação realmente é
Um endereço TRON é derivado de um par de chaves off-line. Nada é registrado em lugar nenhum quando ele é feito, e a rede só toma conhecimento dele quando uma transação cria um registro de conta para ele. A nossa própria verificação é literal quanto a isso: pedimos a um nó a conta por trás do endereço, e uma resposta vazia é o que activated: false quer dizer. Não “não conseguimos encontrar” e não “parece novo” — não há conta ali.
O jeito comum de uma conta passar a existir é uma transferência de TRX recebida: mande TRX para o endereço e a rede cria a conta enquanto executa essa transferência. Criar uma conta não é de graça. Quanto custa é um parâmetro da cadeia e não um valor que valha imprimir numa página, então leia da rede em vez de qualquer lugar que possa estar um ano atrasado. O que importa aqui é que se trata de uma transação comum, e depois dela o endereço é uma conta como qualquer outra.
O que ela trava: a carteira que vai enviar
Energia é delegada a uma conta, e não há a que delegar quando conta nenhuma existe. É isso a recusa por inteiro. Um pedido no mode A ou no mode C que nomeie uma carteira dessas como from volta com 422 invalid_address e details.reason em inactive_wallet, junto com details.index — qual transferência do lote — e details.address. É uma das quatro falhas que uma mesa de pagamentos encontra sem parar, e uma das duas que um pedido recusa de saída em vez de precificar.
Três propriedades dessa recusa importam antes de o tratamento ser escrito.
Ela não gasta a Idempotency-Key. Nenhuma das recusas dessa família gasta: a requisição está bem formada e nós simplesmente não podemos aceitá-la nesses endereços. Assim que a carteira existir, a mesma chave com corpo idêntico byte a byte é uma repetição válida e não um conflito, então nada precisa ser derivado de novo do seu lado.
Ela não é respondida a partir de um cache. O estado de endereço é cacheado aqui, mas a ativação é relida por fora do cache antes de um pedido ser recusado por ela — uma carteira ativada segundos atrás é aceita na hora, e não quando alguma entrada expirar. Repita na hora; não há o que esperar passar.
Ela não existe no mode B. Ali a transação chega já assinada pelo dono do endereço remetente, então a conta está lá por construção e a verificação estaria fazendo uma pergunta que já se respondeu.
Não ativada não é malformada
Duas respostas trazem o mesmo código de erro e querem dizer coisas opostas. 400 invalid_address, sem details.reason nenhum, é sobre o formato da string: não é um endereço TRON, e nada que aconteça na cadeia vai fazer dele um. 422 invalid_address com um details.reason é sobre o estado de um endereço perfeitamente bom, e uma única transação resolve. Um pipeline que trata os dois igual repete o primeiro para sempre e abandona o segundo, então a presença de details.reason é o que vale ramificar, e não o código de erro, que os dois dividem.
O que ela custa: o endereço que está sendo pago
Do lado de quem recebe nada é recusado; um destinatário não ativado é um preço. Uma transferência para um endereço sem saldo de USDT tem que abrir a conta de token do destinatário além de mover os tokens, o que leva cerca de 131,000 unidades de energia contra cerca de 65,000 para um endereço que já tem USDT (por que os dois diferem). Pela taxa do protocolo isso são 13.1 TRX de queima em vez de 6.5 TRX, e numa rodada de pagamentos a clientes novos boa parte do lote pode estar nesse estado de uma vez — quanto custa alugar essa energia se move com o mercado, a queima não.
Aqui as duas perguntas se separam, e os nomes convidam à confusão, então seja exato. activated pergunta se a rede tem uma conta para o endereço. holds_usdt pergunta se o saldo de USDT dele está acima de zero. O preço segue a segunda: kind é double sempre que o endereço não tem USDT, ativado ou não. O aviso inactive_recipient segue a primeira. Então um endereço ativado anos atrás que simplesmente nunca foi pago em USDT não leva aviso nenhum e ainda assim é precificado como double; e um endereço que nunca foi ativado pode mesmo assim ter USDT — um saldo TRC-20 vive no armazenamento do próprio contrato do token, então uma transferência recebida cria um saldo e não uma conta — o que o precifica como single e ao mesmo tempo avisa inactive_recipient. As duas parecem uma pergunta só até um endereço respondê-las de formas diferentes.
Conferir um endereço, e conferir quinhentos
Para um endereço só, GET /v1/address-check responde as duas perguntas e mais duas numa chamada: activated, holds_usdt, blacklisted, is_contract, e o expected_kind que decorre deles.
Para um lote, POST /v1/estimate aceita até 500 transferências e não recusa nada — tudo o que ele nota volta como warnings no item, inclusive achados que travariam um pedido. Destinatários são sempre examinados. O remetente só é examinado se você nomear um: from é opcional num item de estimativa e não muda preço, e a única coisa que ele compra é a resposta. inactive_sender ali é o mesmo achado que um pedido reporta como um 422, chegando enquanto nada está em jogo.
POST /v1/estimate
{"transfers":[{"from":"TN3W…","to":"TMu1…"}]}
# avisos que um item pode trazer: blacklisted, inactive_recipient,
# contract_recipient, inactive_sender, blacklisted_sender
Nenhuma das duas chamadas reserva ou cobra nada, então uma lista pode ser peneirada tantas vezes quanto os limites permitirem. O que nenhuma das duas ensaia é o pedido em si, que gasta dinheiro de verdade em todo modo.
A solução
Mande algum TRX para o endereço, deixe essa transação confirmar, e repita o pedido com a mesma chave e os mesmos bytes. Não há passo de cadastro, nem requerimento, nem uma segunda chamada para nós. A única regra de ordem que vale anotar é que a carteira tem que existir antes do pedido, não antes da transferência: energia é entregue a uma conta, então a conta tem que estar lá para receber.
A mesma exigência vale para uma carteira que você quer manter abastecida. Uma regra de Auto-refill é recusada num endereço não ativado com essa mesma palavra de motivo, e num endereço de contrato com contract_wallet — o consumo de energia de um contrato funciona de outro jeito e a regra não tem o que dimensionar. Ative primeiro, depois configure a regra.