Tài khoản TRON chưa kích hoạt: nó chặn gì và gỡ ra sao
Một địa chỉ chỉ là một cặp khóa cho tới khi mạng lưới có một tài khoản cho nó. Toàn bộ chuyện «tài khoản TRON chưa kích hoạt» chỉ có thế, và đó là câu trả lời làm người ta bất ngờ: địa chỉ đúng dạng, ví hiện nó ra, mã QR quét được, mà chuỗi thì chưa từng nghe nói tới nó. Với một bộ phận chi trả, trạng thái này xuất hiện ở hai chỗ khác nhau — chiếc ví đứng gửi và địa chỉ được trả tiền — và chỉ một trong hai là một lời từ chối.
Kích hoạt thực ra là gì
Một địa chỉ TRON được suy ra từ một cặp khóa, ngoại tuyến. Lúc được tạo ra, nó không được đăng ký ở đâu cả, và mạng lưới chỉ biết tới nó khi một giao dịch tạo ra một bản ghi tài khoản cho nó. Phép kiểm tra của chính chúng tôi hiểu điều đó theo nghĩa đen: chúng tôi hỏi một nút về tài khoản đứng sau địa chỉ, và một câu trả lời rỗng chính là ý nghĩa của activated: false. Không phải «chúng tôi không tìm thấy» và cũng không phải «trông có vẻ mới» — ở đó không có tài khoản nào cả.
Cách thông thường để một tài khoản ra đời là một lần chuyển TRX đi vào: gửi TRX tới địa chỉ đó và mạng lưới tạo tài khoản ngay trong lúc thực hiện lần chuyển ấy. Tạo một tài khoản thì không miễn phí. Cái giá của nó là một tham số của chuỗi chứ không phải một con số đáng in lên một trang, nên hãy đọc nó từ mạng lưới thay vì từ bất cứ chỗ nào có thể đã cũ cả năm. Điều quan trọng ở đây là chỉ cần một giao dịch thông thường, và sau đó địa chỉ ấy là một tài khoản như mọi tài khoản khác.
Nó chặn gì: chiếc ví sắp gửi
Năng lượng được ủy quyền tới một tài khoản, và khi không có tài khoản nào thì cũng chẳng có gì để ủy quyền tới. Toàn bộ lời từ chối chỉ có thế. Một đơn hàng ở mode A hoặc mode C nêu một chiếc ví như thế làm from sẽ nhận về 422 invalid_address với details.reason đặt ở inactive_wallet, kèm details.index — lần chuyển nào trong lô — và details.address. Đó là một trong bốn hỏng hóc mà một bộ phận chi trả gặp đi gặp lại, và là một trong hai trường hợp mà đơn hàng từ chối thẳng thay vì tính giá.
Có ba tính chất của lời từ chối ấy đáng biết trước khi viết đoạn xử lý.
Nó không tiêu tốn Idempotency-Key. Không lời từ chối nào trong họ này tiêu tốn khóa cả: yêu cầu đúng dạng, chỉ là chúng tôi không nhận được nó với những địa chỉ ấy. Khi chiếc ví đã tồn tại, cùng khóa đó với phần thân giống nhau từng byte là một lần phát lại hợp lệ chứ không phải một xung đột, nên phía bạn không phải sinh lại gì.
Nó không được trả lời từ bộ đệm. Trạng thái địa chỉ có được đệm ở đây, nhưng việc kích hoạt thì được đọc lại vượt qua bộ đệm trước khi một đơn hàng bị từ chối vì nó — một chiếc ví vừa kích hoạt vài giây trước sẽ được nhận ngay chứ không phải đợi tới lúc một mục nào đó hết hạn. Cứ thử lại ngay; chẳng có gì phải chờ cho qua.
Nó không tồn tại ở mode B. Ở đó giao dịch tới nơi đã được chủ sở hữu của địa chỉ gửi ký sẵn, nên tài khoản có mặt theo đúng cấu tạo và phép kiểm tra sẽ chỉ là đặt một câu hỏi đã tự trả lời.
Chưa kích hoạt không phải là sai dạng
Hai câu trả lời mang cùng một mã lỗi mà nghĩa thì ngược nhau. 400 invalid_address, hoàn toàn không có details.reason, nói về hình dạng của chuỗi ký tự: nó không phải một địa chỉ TRON, và chẳng có chuyện gì xảy ra trên chuỗi làm nó thành địa chỉ TRON được. 422 invalid_address có kèm details.reason thì nói về trạng thái của một địa chỉ hoàn toàn ổn, và chỉ một giao dịch là sửa xong. Một pipeline xử lý cả hai như nhau sẽ thử lại cái thứ nhất mãi mãi và bỏ rơi cái thứ hai, nên đáng rẽ nhánh theo sự có mặt của details.reason chứ không theo mã lỗi, thứ mà cả hai cùng dùng chung.
Nó tốn gì: địa chỉ được trả tiền
Ở phía nhận thì không có gì bị từ chối; một người nhận chưa kích hoạt là một cái giá. Một lần chuyển tới địa chỉ không có số dư USDT phải mở cả tài khoản token cho người nhận bên cạnh việc chuyển token đi, và việc đó tốn khoảng 131,000 đơn vị năng lượng so với khoảng 65,000 cho một địa chỉ đã giữ USDT (vì sao hai con số khác nhau). Theo mức của giao thức thì đó là đốt 13.1 TRX thay vì 6.5 TRX, và trong một đợt chi trả cho khách hàng mới, phần lớn cả lô có thể cùng ở trạng thái ấy một lúc — việc thuê chỗ năng lượng đó tốn bao nhiêu thì đi theo thị trường, còn phần đốt thì không.
Đến đây hai câu hỏi tách ra, mà tên gọi thì mời gọi người ta trộn chúng lại, nên hãy nói cho thật chính xác. activated hỏi mạng lưới có một tài khoản cho địa chỉ này hay không. holds_usdt hỏi số dư USDT của nó có lớn hơn không hay không. Giá đi theo câu thứ hai: kind là double bất cứ khi nào địa chỉ không giữ USDT, đã kích hoạt hay chưa. Cảnh báo inactive_recipient thì đi theo câu thứ nhất. Vậy nên một địa chỉ được kích hoạt từ nhiều năm trước nhưng đơn giản là chưa bao giờ được trả bằng USDT sẽ không mang cảnh báo nào mà vẫn được tính giá double; còn một địa chỉ chưa từng được kích hoạt vẫn có thể đang giữ USDT — số dư TRC-20 nằm trong bộ nhớ của chính hợp đồng token, nên một lần chuyển đi vào tạo ra một số dư chứ không tạo ra một tài khoản — và địa chỉ đó được tính giá single đồng thời nhận cảnh báo inactive_recipient. Hai câu hỏi trông như một cho tới khi có một địa chỉ trả lời chúng khác nhau.
Kiểm tra một địa chỉ, và kiểm tra năm trăm
Với một địa chỉ đơn lẻ, GET /v1/address-check trả lời cả hai câu hỏi ấy và thêm hai câu nữa trong một lệnh gọi: activated, holds_usdt, blacklisted, is_contract, và expected_kind suy ra từ chúng.
Với cả một lô, POST /v1/estimate nhận tối đa 500 lần chuyển và không từ chối gì — mọi thứ nó nhận ra đều quay về dưới dạng warnings trên từng mục, kể cả những phát hiện đủ để chặn một đơn hàng. Người nhận thì luôn được xem xét. Người gửi chỉ được xem xét nếu bạn nêu tên: from là tùy chọn trên một mục ước tính và không làm đổi giá, và thứ duy nhất nó mua được là câu trả lời. inactive_sender ở đây chính là phát hiện mà một đơn hàng báo về dưới dạng 422, chỉ khác là nó tới lúc chưa có gì đặt cược.
POST /v1/estimate
{"transfers":[{"from":"TN3W…","to":"TMu1…"}]}
# các warnings một mục có thể mang: blacklisted, inactive_recipient,
# contract_recipient, inactive_sender, blacklisted_sender
Cả hai lệnh gọi đều không giữ gì và không tính tiền gì, nên một danh sách có thể được rà đi rà lại với tần suất mà các hạn mức cho phép. Cái mà cả hai đều không diễn tập là chính đơn hàng, thứ tiêu tiền thật ở mọi chế độ.
Cách sửa
Hãy gửi cho địa chỉ đó một ít TRX, chờ giao dịch ấy được xác nhận, rồi phát lại đơn hàng với cùng khóa và cùng những byte cũ. Không có bước đăng ký nào, không có đơn từ nào và không có lệnh gọi thứ hai tới chỗ chúng tôi. Quy tắc về thứ tự duy nhất đáng ghi lại là chiếc ví phải tồn tại trước đơn hàng, chứ không phải trước lần chuyển: năng lượng được giao tới một tài khoản, nên tài khoản phải có mặt ở đó để nhận.
Vẫn đòi hỏi ấy với một chiếc ví bạn muốn giữ cho luôn đầy. Một quy tắc Auto-refill bị từ chối trên một địa chỉ chưa kích hoạt với đúng chữ lý do đó, và trên một địa chỉ hợp đồng thì với contract_wallet — mức tiêu năng lượng của một hợp đồng vận hành theo cách khác và quy tắc chẳng có gì để đo cỡ. Hãy kích hoạt trước, rồi mới đặt quy tắc.