TRX.php 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. <?php
  2. namespace Tron;
  3. use Phactor\Key;
  4. use IEXBase\TronAPI\Exception\TronException;
  5. use IEXBase\TronAPI\Tron;
  6. use IEXBase\TronAPI\Provider\HttpProvider;
  7. use Tron\Interfaces\WalletInterface;
  8. use Tron\Exceptions\TronErrorException;
  9. use Tron\Exceptions\TransactionException;
  10. use Tron\Support\Key as SupportKey;
  11. use InvalidArgumentException;
  12. class TRX implements WalletInterface
  13. {
  14. public function __construct(Api $_api, array $config = [])
  15. {
  16. $this->_api = $_api;
  17. $host = $_api->getClient()->getConfig('base_uri')->getScheme() . '://' . $_api->getClient()->getConfig('base_uri')->getHost();
  18. $fullNode = new HttpProvider($host);
  19. $solidityNode = new HttpProvider($host);
  20. $eventServer = new HttpProvider($host);
  21. try {
  22. $this->tron = new Tron($fullNode, $solidityNode, $eventServer);
  23. } catch (TronException $e) {
  24. throw new TronErrorException($e->getMessage(), $e->getCode());
  25. }
  26. }
  27. public function generateAddress(): Address
  28. {
  29. $attempts = 0;
  30. $validAddress = false;
  31. do {
  32. if ($attempts++ === 5) {
  33. throw new TronErrorException('Could not generate valid key');
  34. }
  35. $key = new Key([
  36. 'private_key_hex' => '',
  37. 'private_key_dec' => '',
  38. 'public_key' => '',
  39. 'public_key_compressed' => '',
  40. 'public_key_x' => '',
  41. 'public_key_y' => ''
  42. ]);
  43. $keyPair = $key->GenerateKeypair();
  44. $privateKeyHex = $keyPair['private_key_hex'];
  45. $pubKeyHex = $keyPair['public_key'];
  46. //We cant use hex2bin unless the string length is even.
  47. if (strlen($pubKeyHex) % 2 !== 0) {
  48. continue;
  49. }
  50. try {
  51. $addressHex = Address::ADDRESS_PREFIX . SupportKey::publicKeyToAddress($pubKeyHex);
  52. $addressBase58 = SupportKey::getBase58CheckAddress($addressHex);
  53. } catch (InvalidArgumentException $e) {
  54. throw new TronErrorException($e->getMessage());
  55. }
  56. $address = new Address($addressBase58, $privateKeyHex, $addressHex);
  57. $validAddress = $this->validateAddress($address);
  58. } while (!$validAddress);
  59. return $address;
  60. }
  61. public function validateAddress(Address $address): bool
  62. {
  63. if (!$address->isValid()) {
  64. return false;
  65. }
  66. $body = $this->_api->post('/wallet/validateaddress', [
  67. 'address' => $address->address,
  68. ]);
  69. return $body->result;
  70. }
  71. public function privateKeyToAddress(string $privateKeyHex): Address
  72. {
  73. try {
  74. $addressHex = Address::ADDRESS_PREFIX . SupportKey::privateKeyToAddress($privateKeyHex);
  75. $addressBase58 = SupportKey::getBase58CheckAddress($addressHex);
  76. } catch (InvalidArgumentException $e) {
  77. throw new TronErrorException($e->getMessage());
  78. }
  79. $address = new Address($addressBase58, $privateKeyHex, $addressHex);
  80. $validAddress = $this->validateAddress($address);
  81. if (!$validAddress) {
  82. throw new TronErrorException('Invalid private key');
  83. }
  84. return $address;
  85. }
  86. public function balance(Address $address)
  87. {
  88. $this->tron->setAddress($address->address);
  89. return $this->tron->getBalance(null, true);
  90. }
  91. public function transfer(Address $from, Address $to, float $amount): Transaction
  92. {
  93. $this->tron->setAddress($from->address);
  94. $this->tron->setPrivateKey($from->privateKey);
  95. try {
  96. $transaction = $this->tron->getTransactionBuilder()->sendTrx($to->address, $amount, $from->address);
  97. $signedTransaction = $this->tron->signTransaction($transaction);
  98. $response = $this->tron->sendRawTransaction($signedTransaction);
  99. } catch (TronException $e) {
  100. throw new TransactionException($e->getMessage(), $e->getCode());
  101. }
  102. if (isset($response['result']) && $response['result'] == true) {
  103. return new Transaction(
  104. $transaction['txID'],
  105. $transaction['raw_data'],
  106. 'PACKING'
  107. );
  108. } else {
  109. throw new TransactionException(hex2bin($response['message']));
  110. }
  111. }
  112. public function blockNumber(): Block
  113. {
  114. try {
  115. $block = $this->tron->getCurrentBlock();
  116. } catch (TronException $e) {
  117. throw new TransactionException($e->getMessage(), $e->getCode());
  118. }
  119. $transactions = isset($block['transactions']) ? $block['transactions'] : [];
  120. return new Block($block['blockID'], $block['block_header'], $transactions);
  121. }
  122. public function blockByNumber(int $blockID): Block
  123. {
  124. try {
  125. $block = $this->tron->getBlockByNumber($blockID);
  126. } catch (TronException $e) {
  127. throw new TransactionException($e->getMessage(), $e->getCode());
  128. }
  129. $transactions = isset($block['transactions']) ? $block['transactions'] : [];
  130. return new Block($block['blockID'], $block['block_header'], $transactions);
  131. }
  132. public function transactionReceipt(string $txHash): Transaction
  133. {
  134. try {
  135. $detail = $this->tron->getTransaction($txHash);
  136. } catch (TronException $e) {
  137. throw new TransactionException($e->getMessage(), $e->getCode());
  138. }
  139. return new Transaction(
  140. $detail['txID'],
  141. $detail['raw_data'],
  142. $detail['ret'][0]['contractRet'] ?? ''
  143. );
  144. }
  145. }