|
|
@@ -0,0 +1,559 @@
|
|
|
+<?php
|
|
|
+
|
|
|
+
|
|
|
+namespace App\Servers;
|
|
|
+
|
|
|
+use App\Models\Broadcast;
|
|
|
+use App\Models\CoinTypes;
|
|
|
+use App\Models\Config;
|
|
|
+use App\Models\MemberCoins;
|
|
|
+use App\Models\Withdraw;
|
|
|
+use App\Servers\Eth\Utils;
|
|
|
+use Illuminate\Support\Facades\Log;
|
|
|
+use Web3p\EthereumTx\Transaction;
|
|
|
+
|
|
|
+
|
|
|
+/**
|
|
|
+ * 广播接口
|
|
|
+ */
|
|
|
+class BroadcastServer
|
|
|
+{
|
|
|
+
|
|
|
+ public static $type_str=[
|
|
|
+ 1=>'BTC充值',
|
|
|
+ 2=>'ETH充值',
|
|
|
+ 3=>'USDT充值',
|
|
|
+ 4=>'BTC提现',
|
|
|
+ 5=>'ETH提现',
|
|
|
+ 6=>'USDT提现',
|
|
|
+ 7=>'ETH手续费',
|
|
|
+ ];
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @param $eth_address ## 用户钱包地址
|
|
|
+ * @return bool|mixed|string|null
|
|
|
+ *
|
|
|
+ * 查询用户NYTR余额
|
|
|
+ */
|
|
|
+ public static function getUsdtNum($eth_address)
|
|
|
+ {
|
|
|
+ $eth = EthereumRPCServer::getInstance();
|
|
|
+ $tx = [];
|
|
|
+ $tx['from'] = $eth_address; //用户地址
|
|
|
+// $tx['to'] = config('muc.hy_address', ''); //系统钱包地址
|
|
|
+ $tx['to'] =Config::where('key','hy_address')->value('value'); //系统钱包地址
|
|
|
+ $tx['data'] = Utils::decodeSolMethod('balanceOf(address)', [$eth_address]);
|
|
|
+ $balance = $eth->call($tx);
|
|
|
+ $balance = Utils::hex2dec($balance);
|
|
|
+ $balance = Utils::int2fund($balance,6); // 18位小数
|
|
|
+ $balance = Utils::fund2int($balance, 2);
|
|
|
+ $balance = round($balance / 100, 2);
|
|
|
+ return $balance;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取ETH余额
|
|
|
+ * @param $eth_address ##用户钱包地址
|
|
|
+ * @return bool|mixed|string
|
|
|
+ */
|
|
|
+ public static function getEthNum($eth_address)
|
|
|
+ {
|
|
|
+ $eth = EthereumRPCServer::getInstance();
|
|
|
+ $eth_num = $eth->getBalance($eth_address);
|
|
|
+ $eth_num = Utils::hex2dec($eth_num);
|
|
|
+ $eth_num = Utils::int2fund($eth_num, 18);
|
|
|
+ return $eth_num;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取BTC数量
|
|
|
+ * @param $btc_address
|
|
|
+ * @return string
|
|
|
+ */
|
|
|
+ public static function getBtcNum($btc_address)
|
|
|
+ {
|
|
|
+ $btc = BtcereumRPCServer::getInstance();
|
|
|
+ $btc_num = $btc->bitcoinBalanceOfAddress($btc_address);
|
|
|
+ return $btc_num;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ public static function addBroadcast($coin_id, $money, $from, $from_key, $to, $member_id, $order_id = 0, $status_type = 0, $from_id = 0, $status = 1)
|
|
|
+ {
|
|
|
+ //保留数量
|
|
|
+ $retain_num = CoinTypes::where('id', $coin_id)->value('retain_num');
|
|
|
+ $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' => '',
|
|
|
+ 'hash' => $status == 5 ? '系统内部转账,直接成功,无需链上广播' : '',
|
|
|
+ 'from_key' => $from_key,
|
|
|
+ 'money' =>$coin_id!=4? round($money - $retain_num,6):$money,
|
|
|
+ 'status' => $status,
|
|
|
+ 'type' => $status_type,
|
|
|
+ 'm_id' => $member_id,
|
|
|
+ 'order_id' => $order_id,
|
|
|
+// 'from_id' => $from_id,
|
|
|
+ 'retain_num' => $retain_num,
|
|
|
+ 'send_money' => $money,
|
|
|
+ ];
|
|
|
+ if ($coin_id == 1) {
|
|
|
+// $btc = BtcereumRPCServer::getInstance();
|
|
|
+// $feeAddressUXTO = $btc->listunspent(0, 999999, [$from]);
|
|
|
+// if (empty($feeAddressUXTO)) {
|
|
|
+// $transaction['error'] = "手续费地址uxto为空";
|
|
|
+// $transaction['status'] = 4;
|
|
|
+// } else {
|
|
|
+// $inputs = [];
|
|
|
+// foreach ($feeAddressUXTO as $item) {
|
|
|
+// $inputs[] = [
|
|
|
+// 'txid' => $item['txid'],
|
|
|
+// 'vout' => $item['vout'],
|
|
|
+// ];
|
|
|
+// }
|
|
|
+// $output = [$to => $transaction['money']];
|
|
|
+// $rawtx = $btc->createrawtransaction($inputs, $output);
|
|
|
+// if ($rawtx === false) {
|
|
|
+// $transaction['error'] = "创建裸交易失败";
|
|
|
+// $transaction['status'] = 4;
|
|
|
+// } else {
|
|
|
+// $transaction['data'] = $rawtx;
|
|
|
+// }
|
|
|
+// }
|
|
|
+ } else {
|
|
|
+ $eth = EthereumRPCServer::getInstance();
|
|
|
+ $transaction['chain_id'] = $eth->chainId;
|
|
|
+ $depend = 0;
|
|
|
+ if ($coin_id == 4) {
|
|
|
+ $hy_address=Config::where('key','hy_address')->value('value');
|
|
|
+ $tx = static::build(
|
|
|
+ $from,
|
|
|
+ $hy_address,//系统钱包地址
|
|
|
+ '0x0',
|
|
|
+ Utils::decodeSolMethod(
|
|
|
+ 'transfer(address,uint256)',
|
|
|
+ [$to, Utils::fund2int($money, 6)]
|
|
|
+// [$to, Utils::fund2int($money, 18)]
|
|
|
+ )
|
|
|
+ );
|
|
|
+ $transaction['from'] = $tx['from'];
|
|
|
+ $transaction['to'] = $tx['to'];
|
|
|
+ $transaction['data'] = $tx['data'];
|
|
|
+ $my_eth = static::getEthNum($tx['from']);
|
|
|
+ if ($my_eth * 1 < 0.002) {
|
|
|
+ $depend = static::withholdServiceCharge($tx, $member_id);
|
|
|
+ }
|
|
|
+ }else{
|
|
|
+ $transaction['value'] =Utils::dec2hex(Utils::fund2int($transaction['money'] * 1)); // 转账金额
|
|
|
+ $transaction['data'] = '0x0';
|
|
|
+ }
|
|
|
+ $transaction['depend'] = $depend;
|
|
|
+// $nonce = $eth->getTransactionCount($transaction['from']);
|
|
|
+// $transaction['nonce'] = $nonce;//交易顺序十六进制。由eth_getTransactionCount获取
|
|
|
+// $gas_price = $eth->getGasPrice();
|
|
|
+// $transaction['gas_price'] = Utils::dec2hex(Utils::toWei("1gwei") + Utils::hex2dec($gas_price));//燃料十六进制。由eth_estimateGas获取
|
|
|
+// $gas_limit = static::getGasLimit($transaction);
|
|
|
+// $transaction['gas_limit'] = $gas_limit;
|
|
|
+ //写入数据库代码 $transaction
|
|
|
+ }
|
|
|
+ $transaction = Broadcast::create($transaction);
|
|
|
+// //写入 返回成功
|
|
|
+ return $transaction->{'id'};
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 导入广播
|
|
|
+ * @param $from
|
|
|
+ * @param $to
|
|
|
+ * @param $nonce
|
|
|
+ * @param $value
|
|
|
+ * @param $data
|
|
|
+ * @param $chain_id
|
|
|
+ * @param $gas_price
|
|
|
+ * @param $gas_limit
|
|
|
+ * @param $sign
|
|
|
+ * @param $hash
|
|
|
+ * @param $money
|
|
|
+ * @param $order_id
|
|
|
+ * @param $coin_id
|
|
|
+ * @param $status
|
|
|
+ * @return mixed
|
|
|
+ */
|
|
|
+ public static function addSysBroadcast($from, $to, $nonce, $value, $data, $chain_id, $gas_price, $gas_limit, $sign, $hash, $money, $order_id, $coin_id, $status)
|
|
|
+ {
|
|
|
+ $withdraws = Withdraw::where('id', $order_id)->first();
|
|
|
+ if (empty($withdraws)) {
|
|
|
+ Log::info('导入提现信息不存在,提现ID:' . $order_id);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ if($withdraws->{'status'}!=1)return false;
|
|
|
+ $transaction_id = Broadcast::where('order_id', $order_id)->where('type', '2')->value('id');
|
|
|
+ //保留数量
|
|
|
+ $transaction = [
|
|
|
+ 'depend' => 0,
|
|
|
+ 'from' => $from,
|
|
|
+ 'to' => $to,
|
|
|
+ 'nonce' => $nonce,
|
|
|
+ 'coin_id' => $coin_id,
|
|
|
+ 'value' => $value,
|
|
|
+ 'data' => $data,
|
|
|
+ 'chain_id' => $chain_id,
|
|
|
+ 'gas_price' => $gas_price,
|
|
|
+ 'gas_limit' => $gas_limit,
|
|
|
+ 'sign' => $sign,
|
|
|
+ 'hash' => $hash,
|
|
|
+ 'from_key' => '',
|
|
|
+ 'money' => $money,
|
|
|
+ 'status' => 3,
|
|
|
+ 'type' => $status,
|
|
|
+ 'm_id' => $withdraws->{'m_id'},
|
|
|
+ 'order_id' => $order_id,
|
|
|
+ 'created_at' => date('Y-m-d H:i:s'),
|
|
|
+ 'updated_at' => date('Y-m-d H:i:s'),
|
|
|
+
|
|
|
+ ];
|
|
|
+ if (empty($transaction_id)) {
|
|
|
+ $transaction_id = Broadcast::insertGetId($transaction);
|
|
|
+ } else {
|
|
|
+ Broadcast::where('id', $transaction_id)->update($transaction);
|
|
|
+ }
|
|
|
+ Withdraw::where('id', $order_id)->update(['updated_at' => date('Y-m-d H:i:s'),'hash'=>$hash, 'status' => '2']);
|
|
|
+// //写入 返回成功
|
|
|
+ return $transaction_id;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 广播签名
|
|
|
+ * @return bool
|
|
|
+ */
|
|
|
+ public static function signBroadcast()
|
|
|
+ {
|
|
|
+ $btc = BtcereumRPCServer::getInstance();
|
|
|
+ $list = Broadcast::where('status', '1')->select(['id', 'depend', 'chain_id', 'm_id', 'from', 'to', 'nonce', 'value', 'data', 'gas_price', 'gas_limit', 'sign', 'money', 'from_key', 'coin_id'])->groupBy('m_id')->limit(10)->get()->toArray();
|
|
|
+// $service_money='4000000000000000';
|
|
|
+
|
|
|
+ // 手续费交易 转账0.0015个
|
|
|
+// $serviceFee = Utils::dec2hex($service_money); // 手续费
|
|
|
+
|
|
|
+ if (empty($list)) return false;
|
|
|
+ $sys_wei=Config::where('key','service_charge')->value('value');
|
|
|
+ $sys_wei=empty($sys_wei)?'15':$sys_wei;
|
|
|
+ $eth = EthereumRPCServer::getInstance();
|
|
|
+ foreach ($list as $value) {
|
|
|
+ $update_info = [];
|
|
|
+ $from_key = PassServer::getSecretKey($value['from_key'], $value['m_id']);
|
|
|
+ $send_num = Broadcast::whereIn('status', ['2'])->where('from', $value['from'])->count();
|
|
|
+ if ($send_num > 0) continue;
|
|
|
+ if ($value['depend']) {
|
|
|
+ $num = Broadcast::where('id', $value['depend'])->where('status', 5)->where('updated_at','<',date('Y-m-d H:i:s',time()-15))->count();
|
|
|
+ if ($num <= 0) continue;
|
|
|
+ }
|
|
|
+ if ($value['coin_id'] == 1) {
|
|
|
+ $feeAddressUXTO = $btc->listunspent(0, 999999, [$value['from']]);
|
|
|
+ if (empty($feeAddressUXTO)) {
|
|
|
+ $update_info['error'] = "手续费地址uxto为空";
|
|
|
+ $update_info['status'] = 4;
|
|
|
+ } else {
|
|
|
+ $inputs = [];
|
|
|
+ foreach ($feeAddressUXTO as $item) {
|
|
|
+ $inputs[] = [
|
|
|
+ 'txid' => $item['txid'],
|
|
|
+ 'vout' => $item['vout'],
|
|
|
+ ];
|
|
|
+ }
|
|
|
+ $output = [$value['to'] => $value['money']*1];
|
|
|
+ $rawtx = $btc->createrawtransaction($inputs, $output);
|
|
|
+ if ($rawtx === false) {
|
|
|
+ $update_info['error'] = "创建裸交易失败";
|
|
|
+ $update_info['status'] = 4;
|
|
|
+ } else {
|
|
|
+ $value['data'] = $rawtx;
|
|
|
+ $privKeys[] = $from_key;
|
|
|
+ $sign = $btc->signrawtransactionwithkey($value['data'], $privKeys,null);
|
|
|
+ if ($sign === false) {
|
|
|
+ $update_info['error'] = '签名失败';
|
|
|
+ $update_info['status'] = 5;
|
|
|
+ } else {
|
|
|
+ $update_info['sign'] = $sign['hex'];
|
|
|
+ $update_info['status'] = 2;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+
|
|
|
+ if($value['coin_id']==4){
|
|
|
+ $my_eth = static::getEthNum($value['from']);
|
|
|
+ //dd( $my_eth);
|
|
|
+ if ($my_eth * 1 < 0.005) {
|
|
|
+ $depend = static::withholdServiceCharge($value, $value['m_id']);
|
|
|
+ Broadcast::where('id', $value['id'])->update(['depend' => $depend]);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ }else{
|
|
|
+// $value['value'] =Utils::dec2hex(Utils::fund2int($value['money'] * 1)); // 转账金额
|
|
|
+ }
|
|
|
+ if(empty($value['nonce']) || true){
|
|
|
+ $nonce = $eth->getTransactionCount($value['from']);
|
|
|
+ //交易顺序十六进制。由eth_getTransactionCount获取
|
|
|
+
|
|
|
+ $nonce_count = Broadcast::where('nonce', $nonce)->where('from',$value['from'])->where('id','<>', $value['id'])->count();
|
|
|
+ if ($nonce_count >= 1) {
|
|
|
+ continue;
|
|
|
+// $nonce=Utils::dec2hex(Utils::hex2dec($nonce) + 1);
|
|
|
+ }
|
|
|
+ $value['nonce'] = $nonce;
|
|
|
+ }
|
|
|
+
|
|
|
+ $gas_price = $eth->getGasPrice();
|
|
|
+
|
|
|
+ $value['gas_price'] = Utils::dec2hex(Utils::toWei($sys_wei."gwei") + Utils::hex2dec($gas_price));//燃料十六进制。由eth_estimateGas获取
|
|
|
+// $value['gas_price'] = $gas_price;//燃料十六进制。由eth_estimateGas获取
|
|
|
+ $gas_limit = static::getGasLimit($value);
|
|
|
+ $value['gas_limit'] = $gas_limit;
|
|
|
+ $sign = static::sign($value, $from_key); //交易签名
|
|
|
+
|
|
|
+ if ($sign === false) {
|
|
|
+ $update_info['error'] = '签名失败';
|
|
|
+ $update_info['status'] = 4;
|
|
|
+ } else {
|
|
|
+ $update_info['sign'] = $sign;
|
|
|
+ $update_info['status'] = 2;
|
|
|
+ $update_info['nonce'] = $value['nonce'];
|
|
|
+ $update_info['gas_limit'] = $value['gas_limit'];
|
|
|
+ $update_info['gas_price'] = $value['gas_price'];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ Broadcast::where('id', $value['id'])->update($update_info);
|
|
|
+ sleep(5);
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 广播交易
|
|
|
+ * @return bool
|
|
|
+ */
|
|
|
+ public static function sendBroadcast()
|
|
|
+ {
|
|
|
+ $btc = BtcereumRPCServer::getInstance();
|
|
|
+ $eth = EthereumRPCServer::getInstance();
|
|
|
+ $list = Broadcast::where('status', '2')->select(['id', 'm_id', 'from', 'to', 'nonce', 'value', 'data', 'gas_price', 'gas_limit', 'sign', 'money', 'from_key', 'coin_id'])->limit(10)->get()->toArray();
|
|
|
+ if (empty($list)) return false;
|
|
|
+ foreach ($list as $value) {
|
|
|
+ $update_info = [];
|
|
|
+ if ($value['coin_id'] == 1) {
|
|
|
+ $txid = $btc->sendrawtransaction($value['sign']);
|
|
|
+ if ($txid == false) {
|
|
|
+ $update_info['error'] = '广播失败';
|
|
|
+ $update_info['status'] = 4;
|
|
|
+ } else {
|
|
|
+ $update_info['hash'] = $txid;
|
|
|
+ $update_info['status'] = 3;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ $hash = $eth->sendRawTransaction($value['sign'], $error);//广播交易
|
|
|
+ if ($hash == false) {
|
|
|
+ $update_info['error'] = json_encode($error);
|
|
|
+ $update_info['status'] = 4;
|
|
|
+ } else {
|
|
|
+ $update_info['hash'] = $hash;
|
|
|
+ $update_info['status'] = 3;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ Broadcast::where('id', $value['id'])->update($update_info);
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 广播查询
|
|
|
+ */
|
|
|
+ public static function getBroadcast(){
|
|
|
+ $btc = BtcereumRPCServer::getInstance();
|
|
|
+ $eth = EthereumRPCServer::getInstance();
|
|
|
+ $list = Broadcast::where('status', '3')->select(['id', 'm_id', 'from', 'to', 'send_money', 'value', 'coin_id', 'type', 'sign', 'money', 'from_key', 'coin_id','hash','send_money','order_id'])->limit(10)->get()->toArray();
|
|
|
+ if (empty($list)) return false;
|
|
|
+ foreach ($list as $value) {
|
|
|
+ $update_info = [];
|
|
|
+ if ($value['coin_id'] == 1) {
|
|
|
+ $deal_info=$btc->getrawtransaction ($value['hash'],true);
|
|
|
+ if(empty($deal_info['confirmations']) || $deal_info['confirmations'] <=3){
|
|
|
+ continue;
|
|
|
+ }else{
|
|
|
+ $update_info['success'] = json_encode($deal_info);
|
|
|
+ $update_info['status'] = 5;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ $receipt = $eth->getTransactionReceipt($value['hash']);//交易查询
|
|
|
+ if (empty($receipt)) {
|
|
|
+ //交易正在广播中,下次继续查询
|
|
|
+ continue;
|
|
|
+ } else {
|
|
|
+ //交易已完成 返回数据格式数据 ,将数据json保存
|
|
|
+ if ($receipt['status'] != '0x1') {
|
|
|
+ $update_info['error'] = json_encode($receipt);
|
|
|
+ $update_info['status'] = 4;
|
|
|
+ }else{
|
|
|
+ $update_info['success'] = json_encode($receipt);
|
|
|
+ $update_info['status'] = 5;
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(!empty($update_info)){
|
|
|
+ Broadcast::where('id', $value['id'])->update($update_info);
|
|
|
+ if($update_info['status']==5){
|
|
|
+ //广播成功,增加会员余额
|
|
|
+ if($value['type']<=3){
|
|
|
+ $member_coin= MemberCoins::where('m_id',$value['m_id'])->where('coin_id',$value['coin_id'])->select(['id','coin_name','coin_id','num','m_id'])->first();
|
|
|
+ MemberCoins::where('id',$member_coin->{'id'})->update(['num'=>$member_coin->{'num'}+$value['send_money']]);
|
|
|
+ MoneyDetailServer::write($member_coin['coin_id'], MoneyDetailServer::$status['coin_recharge'], $value['send_money'], MoneyDetailServer::$add_reduce['add'], $member_coin->{'m_id'}, $member_coin->{'mobile'}, '充币' .$value['send_money'] .''. $member_coin->{'coin_name'}, '', $value['id'], $member_coin->{'num'}, 'Recharge ' . $member_coin->{'money'} . $member_coin->{'coin_name'});
|
|
|
+ }elseif($value['type']<=6){
|
|
|
+ $withdraws = Withdraw::where('id', $value['order_id'])->where('m_id', $value['m_id'])->first();
|
|
|
+ if (!empty($withdraws)) {
|
|
|
+ Withdraw::where('id', $value['order_id'])->update([ 'status' => '3']);
|
|
|
+ $member_coin = MemberCoins::where('m_id', $value['m_id'])->where('coin_id', $value['coin_id'])->select(['id', 'coin_name', 'coin_id', 'num', 'm_id','lock_num'])->first();
|
|
|
+ $lock_num = $member_coin->{'lock_num'} - $withdraws->{'money'};
|
|
|
+ if ($lock_num < 0) $lock_num = 0;
|
|
|
+ MemberCoins::where('id', $member_coin->{'id'})->update(['lock_num' => $lock_num]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 系统手续费转账
|
|
|
+ * @param $tx
|
|
|
+ * @param $member_id
|
|
|
+ * @return mixed
|
|
|
+ */
|
|
|
+ public static function withholdServiceCharge($tx, $member_id)
|
|
|
+ {
|
|
|
+ $eth = EthereumRPCServer::getInstance();
|
|
|
+ $gasPrice = $eth->getGasPrice(); // 手续费
|
|
|
+ $cb_address = Config::where('key', 'cb_address')->value('value');
|
|
|
+ $address_key = Config::where('key', 'address_key')->value('value');
|
|
|
+ $sys_wei=Config::where('key','service_charge')->value('value');
|
|
|
+ $service_money=Config::where('key','service_money')->value('value');
|
|
|
+ $sys_wei=empty($sys_wei)?'15':$sys_wei;
|
|
|
+ $service_money=empty($service_money)?'3000000000000000':$service_money;
|
|
|
+ $tx = [
|
|
|
+ 'from' => $cb_address,
|
|
|
+ 'to' => $tx['from'],
|
|
|
+ 'value' => '0x0',
|
|
|
+ 'data' => $tx['data'],
|
|
|
+ ];
|
|
|
+ $gasLimit = $eth->estimateGas($tx);
|
|
|
+ // 手续费交易 转账0.0015个
|
|
|
+ $serviceFee = Utils::dec2hex($service_money); // 手续费
|
|
|
+ // 广播手续费
|
|
|
+ $transaction = [
|
|
|
+ 'depend' => 0,
|
|
|
+ 'from' => $cb_address,
|
|
|
+ 'to' => $tx['to'],
|
|
|
+ 'nonce' => '',
|
|
|
+ 'value' => $serviceFee,//转账0.004个
|
|
|
+ 'data' => '0x0',
|
|
|
+ 'money' => round($service_money/1000000000000000000,6),
|
|
|
+ 'gas_limit' => $gasLimit,
|
|
|
+ 'chain_id' => $eth->chainId,
|
|
|
+ 'gas_price' => '',
|
|
|
+ 'to_address' => $tx['to'],
|
|
|
+ 'coin_id' => 2,
|
|
|
+ 'sign' => '',
|
|
|
+ 'hash' => '',
|
|
|
+ 'from_key' => $address_key,//系统支付秘钥
|
|
|
+ 'status' => 1,//系统支付秘钥
|
|
|
+ 'type' => 7,//系统支付秘钥
|
|
|
+ 'm_id' => 0,
|
|
|
+ 'send_money' => round($service_money/1000000000000000000,6),
|
|
|
+ ];
|
|
|
+ $nonce = $eth->getTransactionCount($transaction['from']);
|
|
|
+ $transaction['nonce'] = $nonce;//交易顺序十六进制。由eth_getTransactionCount获取
|
|
|
+ $transaction['gas_price'] = Utils::dec2hex(Utils::toWei($sys_wei."gwei") + Utils::hex2dec($gasPrice));//燃料十六进制。由eth_estimateGas获取
|
|
|
+ $transaction['gas_limit'] = $gasLimit;
|
|
|
+ //写入数据库代码 $transaction
|
|
|
+ $nytr = Broadcast::create($transaction);
|
|
|
+ return $nytr->{'id'};
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 转账内容拼接
|
|
|
+ * @param $from
|
|
|
+ * @param $to
|
|
|
+ * @param $value
|
|
|
+ * @param $data
|
|
|
+ * @return array
|
|
|
+ * @throws
|
|
|
+ */
|
|
|
+ protected static function build($from, $to, $value, $data)
|
|
|
+ {
|
|
|
+ $tx = [];
|
|
|
+ $tx['from'] = $from;
|
|
|
+ $tx['to'] = $to;
|
|
|
+ $tx['value'] = $value;
|
|
|
+ $tx['data'] = $data;
|
|
|
+
|
|
|
+ return $tx;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @param $transaction
|
|
|
+ * @return string
|
|
|
+ */
|
|
|
+ public static function getGasLimit($transaction)
|
|
|
+ {
|
|
|
+ $tx = [
|
|
|
+ 'from' => $transaction['from'],
|
|
|
+ 'to' => $transaction['to'],
|
|
|
+ 'nonce' => $transaction['nonce'],
|
|
|
+ 'value' => $transaction['value'],
|
|
|
+ 'data' => $transaction['data'],
|
|
|
+ 'chainId' => 1,
|
|
|
+ 'gasPrice' => $transaction['gas_price'],
|
|
|
+ ];
|
|
|
+ $eth = EthereumRPCServer::getInstance();
|
|
|
+ $gasLimit = $eth->estimateGas($tx);
|
|
|
+ if (!$gasLimit) {
|
|
|
+ $gasLimit = 10 * 10000; // 预估失败, 最高10万
|
|
|
+ }
|
|
|
+ return $gasLimit;
|
|
|
+ }
|
|
|
+
|
|
|
+ protected static function sign($transaction, $key)
|
|
|
+ {
|
|
|
+ $tx = [
|
|
|
+ 'from' => $transaction['from'],
|
|
|
+ 'to' => $transaction['to'],
|
|
|
+ 'nonce' => $transaction['nonce'],
|
|
|
+ 'value' => $transaction['value'],
|
|
|
+ 'data' => $transaction['data'],
|
|
|
+ 'chainId' => $transaction['chain_id'],
|
|
|
+ 'gasPrice' => $transaction['gas_price'],
|
|
|
+ 'gasLimit' => $transaction['gas_limit'],
|
|
|
+ ];
|
|
|
+ // 数据签名
|
|
|
+
|
|
|
+ $tr = new Transaction($tx);
|
|
|
+ $tr->sign($key);
|
|
|
+ return Utils::fixHex($tr->serialize()->toString('hex'));
|
|
|
+ }
|
|
|
+}
|