'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')); } }