EosBase.php 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. <?php
  2. /**
  3. * EOS相关操作
  4. * User: ben
  5. * Date: 2018/9/19
  6. * Time: 下午2:59
  7. */
  8. class EosBase extends Singleton {
  9. /**
  10. * 解锁钱包
  11. * @param string $name 钱包名 [0-9a-f]{12}
  12. * @param string $password 钱包名对应的密码
  13. */
  14. function unlockWallet($name = null, $password = null) {
  15. $name = $name ?: $GLOBALS['walletName'];
  16. $password = $password ?: $GLOBALS['walletPwd'];
  17. // 解锁钱包
  18. $cmd = "cleos wallet unlock -n {$name} --password {$password}";
  19. exec($cmd);
  20. }
  21. /**
  22. * 创建账号
  23. * @param string $name 账号名 [0-9a-f]{12}
  24. * @param string $ownerKey owner的公钥
  25. * @param string $activeKey active的公钥
  26. * @param string $creator 创建者账号名 [0-9a-f]{12}
  27. *
  28. * @return string json
  29. */
  30. function createAccount($name, $ownerKey, $activeKey = '', $creator = null) {
  31. $creator = $creator ?: $GLOBALS['codeBaccarat'];
  32. // $cmd = "cleos -u {$GLOBALS['eosUrl']} create account {$creator} {$name} {$ownerKey} {$activeKey} -j";
  33. $cmd = "cleos -u {$GLOBALS['eosUrl']} system newaccount --stake-net '0.0500 EOS' --stake-cpu '0.1500 EOS' --buy-ram-kbytes 4 {$creator} {$name} {$ownerKey} {$activeKey} -j";
  34. $json = Eos::execCmd($cmd);
  35. return $json;
  36. }
  37. /**
  38. * 获取链的概要信息
  39. * @return mixed
  40. */
  41. function getInfo() {
  42. $cmd = "cleos -u {$GLOBALS['eosUrl']} get info";
  43. $json = self::execCmd($cmd);
  44. return json_decode($json, true);
  45. }
  46. /**
  47. * eos或gt币转账给用户
  48. * @param $from
  49. * @param $to
  50. * @param $amount
  51. * @param $memo
  52. * @param $transaction_type
  53. * @param $player_transaction_id
  54. * @return array
  55. */
  56. public function transfer($from, $to, $amount, $memo, $transaction_type, $player_transaction_id = '') {
  57. $type = strpos(strtolower($amount), 'eos') === false ? 'gt' : 'eos';
  58. if ($type == 'gt') {
  59. // $from = $GLOBALS['codeGtAdmin'];
  60. $cmd = "cleos -u {$GLOBALS['eosUrl']} push action eosgetgtoken transfer '[ \"{$from}\", \"{$to}\", \"{$amount}\", \"{$memo}\" ]' -p {$from} -j";
  61. } elseif ($type == 'eos') {
  62. // $from = $GLOBALS['codeBaccarat'];
  63. $cmd = "cleos -u {$GLOBALS['eosUrl']} transfer {$from} {$to} '{$amount}' '{$memo}' -j";
  64. } else {
  65. return null;
  66. }
  67. $json = self::execCmd($cmd);
  68. $log = [
  69. 'player_transaction_id' => $player_transaction_id,
  70. 'transaction_type' => $transaction_type,
  71. 'from' => $from,
  72. 'to' => $to,
  73. 'cmd' => $cmd,
  74. 'json' => $json,
  75. ];
  76. // 记录交易,失败重试
  77. return self::logTrans($log);
  78. }
  79. /**
  80. * 当前交易的块id
  81. * @var int
  82. */
  83. static $last_json = '';
  84. static $last_trx_id = 0;
  85. /**
  86. * 记录交易,并定时检查是否失效了
  87. * @param $data [`transaction_id`, `player_transaction_id`, `transaction_type`, `from`, `to`, `cmd`, `transaction_state`, `json`, `retry_times`]
  88. * @return array
  89. */
  90. static function logTrans($data) {
  91. self::$last_json = $data['json'];
  92. $objTrans = new TableHelper('transaction_log', 'dw_eos');
  93. $ret = [];
  94. $flag = false;
  95. if (!$data['transaction_id']) {
  96. if (!$data['json']) {
  97. self::_fillId($data);
  98. $data['transaction_state'] = -1;
  99. } else {
  100. $ret = json_decode($data['json'], true);
  101. $data['transaction_id'] = $ret['transaction_id'];
  102. if ($data['transaction_id']) {
  103. $flag = true;
  104. $data['block_num'] = $ret['processed']['block_num'];
  105. } else {
  106. // 没有id,就需要填充
  107. self::_fillId($data);
  108. $data['transaction_state'] = -1;
  109. }
  110. }
  111. }
  112. self::$last_trx_id = $data['transaction_id'];
  113. $data['console'] = $data['console'] ?: $ret['processed']['action_traces'][0]['console'];
  114. $data['create_time'] = date('Y-m-d H:i:s');
  115. // $objTrans->addObject($data);
  116. if ($flag) {
  117. // return $data['transaction_id'];
  118. return $data;
  119. } else {
  120. return null;
  121. }
  122. }
  123. private static function _fillId(&$data) {
  124. $objTrans = new TableHelper('transaction_log', 'dw_eos');
  125. $count = $objTrans->getCount();
  126. $rand = rand(1000, 9999);
  127. $data['transaction_id'] = "unknown:{$count}:{$rand}";
  128. }
  129. /**
  130. * 获取交易详情
  131. * @param string $transaction_id
  132. * @param int $block_num_hint
  133. * @return string
  134. */
  135. static function getTransaction($transaction_id, $block_num_hint) {
  136. $api = $GLOBALS['eosUrl'] . 'v1/history/get_transaction';
  137. $data = ["id" => $transaction_id,];
  138. $block_num_hint = (int)$block_num_hint;
  139. if ($block_num_hint) {
  140. $data['block_num_hint'] = $block_num_hint;
  141. }
  142. $json = null;
  143. for ($i = 0; $i < 4; $i++) {
  144. $post_json = json_encode($data);
  145. $json = (new dwHttp)->post2($api, $post_json, 3, 3);
  146. $trx = json_decode($json, true);
  147. if ($trx['id']) {
  148. return $json;
  149. } else {
  150. $data['block_num_hint']++;
  151. }
  152. }
  153. return $json;
  154. }
  155. /**
  156. * 获取账号信息
  157. * @param $userName
  158. *
  159. * @return string
  160. */
  161. static function getAccount($userName) {
  162. $cmd = "cleos -u {$GLOBALS['eosUrl']} get account {$userName} -j";
  163. return self::execCmd($cmd);
  164. }
  165. /**
  166. * 获取余额
  167. * @param $userName
  168. *
  169. * @return float
  170. */
  171. public static function getBalance($userName, $code = 'eosio.token') {
  172. $cmd = "cleos -u {$GLOBALS['eosUrl']} get currency balance {$code} {$userName}";
  173. $result = self::execCmd($cmd);
  174. $balance = (float) $result;
  175. return $balance * 10000;
  176. }
  177. static function execCmd($cmd) {
  178. $startTime = microtime(true);
  179. if (strpos($cmd, ' 2>&1') === false) {
  180. $cmd = $cmd .' 2>&1';
  181. }
  182. // 同时输出错误信息
  183. $json = shell_exec($cmd);
  184. $msg = "{$cmd}, ret:" . substr($json, 0, 100);
  185. CallLog::logModuleCall("Shell:", $msg, null, $json, $startTime);
  186. CallLog::flushLogs();
  187. return $json;
  188. }
  189. static function log($msg) {
  190. $date = date('Y-m-d H:i:s', time());
  191. print_r("[{$date}], {$msg}\n");
  192. }
  193. /**
  194. * 重试多次获取交易id
  195. * @param $transaction_id
  196. * @param int $block_num_hint
  197. * @param int $maxTimes
  198. * @param int $times
  199. * @throws Exception
  200. * @return mixed
  201. */
  202. static function getTransaction2($transaction_id, $block_num_hint, $maxTimes = 3, $times = 0) {
  203. // 检验交易id是否是当前用户,当前gameid
  204. $json = Eos::getTransaction($transaction_id, $block_num_hint);
  205. $ret = json_decode($json, true);
  206. if ($ret['error']) {
  207. // 3040011 The transaction can not be found
  208. if ($ret['error']['code'] == 3040011) {
  209. if ($times < $maxTimes) {
  210. Tool::sleep($times);
  211. return self::getTransaction2($transaction_id, $block_num_hint, $maxTimes, $times + 1);
  212. } else {
  213. throw new Exception("transaction id:{$transaction_id} is not found.", CODE_PARAM_ERROR);
  214. }
  215. }
  216. }
  217. return $ret;
  218. }
  219. /**
  220. * 获取真正的块id
  221. * @param $trxId
  222. * @param int $block_num
  223. *
  224. * @return mixed
  225. */
  226. static function getRealBlockNum($trxId, $block_num = 0) {
  227. if ($block_num || ENV == ENV_DEV) {
  228. $ret = self::getTransaction2($trxId, $block_num);
  229. } else {
  230. $ret = Eos::getTrxBySpark($trxId);
  231. }
  232. return $ret['block_num'];
  233. }
  234. static function getTrxBySpark($transaction_id) {
  235. $api_key = '37400d93f3c7eb64428585f1cd355fe8';
  236. $url = "https://api.eospark.com/api?module=transaction&action=get_transaction_detail_info&apikey={$api_key}&trx_id={$transaction_id}";
  237. $objHttp = new dwHttp();
  238. $data = null;
  239. for ($i = 1; $i <= 3; $i++) {
  240. $json = $objHttp->get2($url);
  241. $data = json_decode($json, true);
  242. if ($data['errno'] == 0) {
  243. return $data['data'];
  244. } else {
  245. sleep($i / 2);
  246. }
  247. }
  248. return $data;
  249. }
  250. }