ACCOUNT_TYPE::class, 'amount' => 'decimal:18', 'gas_price' => 'decimal:18', 'gas_used' => 'integer', 'gas_fee' => 'decimal:18', 'status' => 'integer', 'block_number' => 'integer' ]; protected static function booted() { static::creating(function ($transaction) { // 自动计算矿工费 if ($transaction->gas_price && $transaction->gas_used) { $transaction->gas_fee = bcdiv( bcmul($transaction->gas_price, (string)$transaction->gas_used), '1000000000', 18 ); } }); static::updating(function ($transaction) { // 当 gas_price 或 gas_used 更新时重新计算矿工费 if ($transaction->isDirty('gas_price') || $transaction->isDirty('gas_used')) { $transaction->gas_fee = bcdiv( bcmul($transaction->gas_price, (string)$transaction->gas_used), '1000000000', 18 ); } }); static::updated(function ($transaction) { if ($transaction->isDirty('status')) { if ($transaction->status === 1) { // 交易成功 $transaction->updateWalletBalances(); } } }); } public function fromWallet(): BelongsTo { return $this->belongsTo(BlockchainWallet::class, 'from_address', 'address'); } public function toWallet(): BelongsTo { return $this->belongsTo(BlockchainWallet::class, 'to_address', 'address'); } public function getStatusLabelAttribute(): string { return match($this->status) { 0 => '待确认', 1 => '成功', 2 => '失败', default => '未知' }; } public function updateWalletBalances(): void { DB::transaction(function () { // 更新发送方钱包余额 $fromWallet = $this->fromWallet; if ($fromWallet) { $newBalance = bcsub($fromWallet->balance, $this->amount, 18); $fromWallet->updateBalance($newBalance); } // 更新接收方钱包余额 $toWallet = $this->toWallet; if ($toWallet) { $newBalance = bcadd($toWallet->balance, $this->amount, 18); $toWallet->updateBalance($newBalance); } }); } public function getConfirmations(): int { if (!$this->block_number) { return 0; } $latestBlockNumber = Cache::remember('latest_block_number', 60, function () { $bscScanService = app(BscScanService::class); return $bscScanService->getLatestBlockNumber(); }); return max(0, $latestBlockNumber - $this->block_number); } public function isSafe(): bool { $requiredConfirmations = config('blockchain.transaction.confirmations', 12); return $this->getConfirmations() >= $requiredConfirmations; } public function getTotalGasFee(): float { if (!$this->gas_price || !$this->gas_used) { return 0; } return bcmul($this->gas_price, (string)$this->gas_used, 18); } /** * 获取交易的总成本(转账金额 + 矿工费) * 仅当代币类型为 BNB 时才包含矿工费 */ public function getTotalCost(): string { if ($this->token_type === ACCOUNT_TYPE::BNB) { return bcadd($this->amount, $this->gas_fee, 18); } return $this->amount; } /** * 获取格式化的矿工费(带单位) */ public function getFormattedGasFeeAttribute(): string { return $this->gas_fee . ' BNB'; } /** * 获取预估的矿工费 */ public static function estimateGasFee(ACCOUNT_TYPE $tokenType, float $gasPrice): float { $gasLimit = $tokenType === ACCOUNT_TYPE::BNB ? 21000 : 65000; return bcdiv(bcmul((string)$gasPrice, (string)$gasLimit), '1000000000', 18); } /** * 检查矿工费是否超过最大限制 */ public function isGasFeeTooHigh(): bool { $maxGasPrice = config('blockchain.transaction.max_gas_price', 10); // GWEI return bccomp($this->gas_price, (string)$maxGasPrice, 18) === 1; } }