123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235 |
- <?php
- namespace App\Servers;
- use App\Models\Broadcast;
- use App\Models\ContractDistribution;
- use App\Servers\Icon\BanRPC;
- use App\Servers\Icon\Utils;
- use Web3p\EthereumTx\Transaction;
- /**
- * 广播接口
- */
- class BroadcastServer
- {
- public static $type_str=[
- ];
- static private $server = null;
- /**
- * 创建对象
- * @return BroadcastServer
- */
- static function creatServer()
- {
- if (empty(self::$server)) self::$server = new BroadcastServer();
- return self::$server;
- }
- /**
- * 创建广播信息
- * @param $coin_id
- * @param $money
- * @param $from
- * @param $from_key
- * @param $to
- * @param $member_id
- * @param int $order_id
- * @param int $status_type
- * @param int $status
- * @return mixed
- */
- public static function addBroadcast($coin_id, $money, $from, $from_key, $to, $member_id, $order_id = 0, $status_type = 0, $status = 1)
- {
- //保留数量
- $transaction = [
- 'depend' => 0,
- 'from' => $from,
- 'to' => $to,
- 'nonce' => '',
- 'coin_id' => $coin_id,
- 'value' => '0x0',
- 'data' => !empty($tx['data']) ? $tx['data'] : Utils::fixHex(bin2hex('NYT')),
- 'chain_id' => 0,
- 'gas_price' => '',
- 'gas_limit' => '',
- 'to_address' => $to,
- 'sign' => '',
- 'success' => '',
- 'hash' => $status == 5 ? '系统内部转账,直接成功,无需链上广播' : '',
- 'from_key' => $from_key,
- 'money' =>round($money,6),
- 'status' => $status,
- 'type' => $status_type,
- 'm_id' => $member_id,
- 'order_id' => $order_id,
- ];
- $transaction = Broadcast::create($transaction);
- return $transaction->{'id'};
- }
- /**
- * 广播查询
- */
- public function getBroadcast()
- {
- $list = Broadcast::where('status', '2')->select(['id', 'm_id', 'from', 'to', 'value', 'coin_id', 'type', 'sign', 'money', 'from_key', 'coin_id', 'hash', 'order_id'])->limit(100)->get();
- $ret_type=false;
- if (empty($list)) return $ret_type;
- $bnbServer=BanRPC::creatServer();
- foreach ($list as $value) {
- $receipt = $bnbServer->getTransactionReceipt($value['hash']);//交易查询
- if (empty($receipt)) {
- //交易正在广播中,下次继续查询
- continue;
- } else {
- //交易已完成 返回数据格式数据 ,将数据json保存
- $distribution=ContractDistribution::where('id',$value->{'order_id'})->where('type',$value->{'type'})->first();
- if ($receipt['status'] != '0x1') {
- $update_info['error'] = '广播提交失败';
- $update_info['status'] = 3;
- $distribution->update(['status' => 2]);
- } else {
- $update_info['status'] = 4;
- $update_info['end_time'] = time();
- $distribution->update(['status' => 3]);
- }
- $value->update($update_info);
- }
- }
- return $list->count();
- }
- /**
- * 交易广播
- */
- function sendBroadcast(){
- $list = Broadcast::where('status', '1')->where([['end_time','=',0,'or'],['end_time','<=',time()-60,'or']])->select(['id', 'm_id', 'from', 'to', 'nonce', 'value', 'data', 'gas_price', 'gas_limit', 'sign', 'money', 'from_key', 'coin_id', 'depend','type','contract_address','order_id'])->limit(100)->get();
- $bnbServer=BanRPC::creatServer();
- foreach ($list as $value){
- $bnbNum=$bnbServer->getBalance($value->{'from'});
- if(env('TEST_SERVE')){
- $value->{'money'}='0.00001';
- }
- if((empty($bnbNum) || $bnbNum<($value->{'money'}+0.0004)) && !env('TEST_SERVE')){
- $transaction['end_time'] = time();
- }else{
- //ETH广播
- $send_num = Broadcast::where('from', $value->{'from'})->where('status', '2')->count('id');
- if ($send_num > 0) {
- sleep(1);
- continue;
- }
- $transaction = $this->sendBnb($value);
- if (empty($transaction) || empty($transaction['hash'])) {
- $transaction = ['status' => 3, 'error' => '广播失败'];
- } else {
- $transaction['status'] = 2;
- }
- if ($transaction) {
- Broadcast::where('id', $value->{'id'})->update($transaction);
- }
- }
- }
- return $list->count();
- }
- function sendBnb($value){
- $bnbServer=BanRPC::creatServer();
- // try {
- $transaction['from'] = $value['from'];
- $transaction['to'] = $value['to'];
- $transaction['chain_id'] = $bnbServer->chainId;
- $transaction['value'] = Utils::dec2hex(Utils::fund2int($value['money'] )); // 转账金额
- $transaction['data'] = '0x0';
- // $transaction['data'] = Utils::decodeSolMethod('transfer(address,uint256)', [$value['to'], Utils::fund2int($value['money'], 18)]);
- $nonce = $bnbServer->getTransactionCount($value['from']);
- $transaction['nonce'] = $nonce;
- $gas_price = $bnbServer->getGasPrice();
- // $transaction['gas_price'] = Utils::dec2hex(Utils::toWei("26gwei") + Utils::hex2dec($gas_price));//燃料十六进制。由eth_estimateGas获取
- $transaction['gas_price'] =$gas_price;//燃料十六进制。由eth_estimateGas获取
- $gas_limit =$this->getEthGasLimit($transaction);
- $transaction['gas_limit'] = $gas_limit;
- if($value->{'type'}==3)$value->{'m_id'}=0;
- $sign = $this->ethSign($transaction, PassServer::creatServer()->getSecretKey($value->{'from_key'}, $value->{'m_id'})); //交易签名
- $transaction['sign'] = $sign;
- $error='';
- $hash = $bnbServer->sendRawTransaction($transaction['sign'], $error);//广播交易
- $transaction['hash'] = $hash;
- return $transaction;
- // } catch (\Exception $e) {
- // return false;
- // }
- }
- /**
- * @param $transaction
- * @return string
- */
- public function getEthGasLimit($transaction)
- {
- $bnbServer=BanRPC::creatServer();
- $tx = [
- 'from' => $transaction['from'],
- 'to' => $transaction['to'],
- 'nonce' => $transaction['nonce'],
- 'value' => $transaction['value'],
- 'data' => $transaction['data'],
- 'chainId' => $bnbServer->chainId,
- 'gasPrice' => $transaction['gas_price'],
- ];
- $gasLimit = $bnbServer->estimateGas($tx);
- if (!$gasLimit) {
- $gasLimit = 10 * 10000; // 预估失败, 最高10万
- }
- return $gasLimit;
- }
- protected function build($from, $to, $value, $data)
- {
- $tx = [];
- $tx['from'] = $from;
- $tx['to'] = $to;
- $tx['value'] = $value;
- $tx['data'] = $data;
- return $tx;
- }
- function ethSign($transaction, $key)
- {
- $bnbServer=BanRPC::creatServer();
- $tx = [
- 'from' => $transaction['from'],
- 'to' => $transaction['to'],
- 'nonce' => $transaction['nonce'],
- 'value' => $transaction['value'],
- 'data' => $transaction['data'],
- 'chainId' => $bnbServer->chainId,
- 'gasPrice' => $transaction['gas_price'],
- 'gasLimit' => $transaction['gas_limit'],
- ];
- // 数据签名
- $tr = new Transaction($tx);
- $tr->sign($key);
- return Utils::fixHex($tr->serialize());
- }
- }
|