title: how to generate Trx wallet without using API
body: <p>base on <a href="https://developers.tron.network/docs/account" rel="nofollow noreferrer">TRX documents</a> and some search in GitHub I tried to generate wallet offline and I can't use API for some reasons.</p>
  <h1>based on Trx documents I should do these steps :</h1>
  <blockquote>
  <ol>
  <li>Generate a key pair and extract the public key (a 64-byte byte array representing its x,y coordinates).</li>
  <li>Hash the public key using sha3-256 function and extract the last 20 bytes of the result.</li>
  <li>Add 0x41 to the beginning of the byte array. The length of the initial address should be 21 bytes.</li>
  <li>Hash the address twice using sha256 function and take the first 4 bytes as verification code.</li>
  <li>Add the verification code to the end of the initial address and get an address in base58check format through base58 encoding.</li>
  <li>An encoded Mainnet address begins with T and is 34 bytes in length.</li>
  </ol>
  <p><strong>Please note: the sha3 protocol adopted is KECCAK-256.</strong></p>
  </blockquote>
  <p>I find <code>mattvb91/tron-trx-php</code> in GitHub and this repository there is a wallet generator method <code>/src/Wallet.php</code> but the generated key validation return an Error Exception and validation get failed.</p>
  <p>I try to recode <code>mattvb91/tron-trx-php</code> Wallet generator method and create my wallet generator</p>
  <pre><code>class walletGenerator
      {
  
          private $addressPrefix = &quot;41&quot;;
          private $addressPrefixByte = 0x41;
          private $addressSize = 34;
  
          public function __construct()
          {
  
          }
  
          public function generateWallet()
          {
              $key = new Key();
  
              $odd = false;
              while (!$odd)
              {
                  $keyPair = $key-&gt;GenerateKeypair();
                  if(strlen($keyPair['public_key']) % 2 == 0) $odd = true;
              }
  
              $privateKeyHex = $keyPair['private_key_hex'];
              $pubKeyHex = $keyPair['public_key'];
  
              $pubKeyBin = hex2bin($pubKeyHex);
              $addressHex = $this-&gt;getAddressHex($pubKeyBin);
              $addressBin = hex2bin($addressHex);
              $addressBase58 = $this-&gt;getBase58CheckAddress($addressBin);
              $validAddress = $this-&gt;validateAddress($addressBase58);
  
          }
  
          private function getAddressHex($pubKeyBin)
          {
              if (strlen($pubKeyBin) == 65) {
                  $pubKeyBin = substr($pubKeyBin, 1);
              }
  
              $hash = Keccak::hash($pubKeyBin , 256);
              $hash = substr($hash, 24);
  
              return $this-&gt;addressPrefix . $hash;
          }
  
          private function getBase58CheckAddress($addressBin){
              $hash0 = Hash::SHA256($addressBin);
              $hash1 = Hash::SHA256($hash0);
              $checksum = substr($hash1, 0, 4);
              $checksum = $addressBin . $checksum;
              $result = Base58::encode(Crypto::bin2bc($checksum));
  
              return $result;
          }
  
          private function validateAddress($walletAddress){
              if(strlen($walletAddress) !== $this-&gt;addressSize) return false;
  
              $address = Base58Check::decode($walletAddress , false , 0 , false);
              $utf8 = hex2bin($address);
  
              if(strlen($utf8) !== 25) return false;
              if(strpos($utf8 , $this-&gt;addressPrefixByte) !== 0) return false; // strpos(): Non-string needles will be interpreted as strings in the future. Use an explicit chr() call to preserve the current behavior
  
              $checkSum = substr($utf8, 21);
              $address = substr($utf8, 0, 21);
  
  
              $hash0 = Hash::SHA256($address);
              $hash1 = Hash::SHA256($hash0);
              $checkSum1 = substr($hash1, 0, 4);
  
              if ($checkSum === $checkSum1) {
                  return true;
              }
          }
  
  </code></pre>
  <h1>Here is my problems :</h1>
  <ol>
  <li><code>validateAddress</code> method has an Error Exception</li>
  <li>when I add Private Key in Trx Wallets manually the detected wallet address is different from the generated Address.</li>
  </ol>
  <pre><code>if(strpos($utf8 , $this-&gt;addressPrefixByte) !== 0) return false; // strpos(): Non-string needles will be interpreted as strings in the future. Use an explicit chr() call to preserve the current behavior
  
  </code></pre>
  <h1>additional information</h1>
  <p>I used <code>ionux/phactor</code> to generating keyPair and <code>iexbase/tron-api</code> Support classes for Hash and ...</p>