query('per_page', 20))); $items = WalletTransfer::where('user_id', $user->id) ->orderByDesc('id') ->limit($perPage) ->get(['id','type','amount','currency','created_at']); $transfers = $items->map(fn($t) => [ 'id' => $t->id, 'type' => $t->type, 'amount' => (string) $t->amount, 'currency' => $t->currency, 'created_at' => $t->created_at?->toIso8601String(), ]); $map = $user->vault_balances ?? []; return response()->json([ 'balance' => (string) ($user->balance ?? '0.0000'), 'vault_balance' => (string) ($user->vault_balance ?? '0.0000'), 'vault_balances' => array_merge( ['BTX' => (string) ($user->vault_balance ?? '0.0000')], $map ), 'currency' => 'BTX', 'transfers' => $transfers, 'now' => now()->toIso8601String(), ], 200); } /** * POST /api/wallet/vault/deposit */ public function deposit(Request $request) { $user = Auth::user(); abort_unless($user, 403); $data = $request->validate([ 'amount' => ['required','string','regex:/^\d+(?:\.\d{1,4})?$/'], 'pin' => ['required','string','regex:/^\d{4,8}$/'], 'currency' => ['sometimes','string','in:' . implode(',', self::SUPPORTED_CURRENCIES)], 'idempotency_key' => ['sometimes','nullable','string','max:64'], ]); $currency = strtoupper($data['currency'] ?? 'BTX'); if ($resp = $this->wallet->verifyVaultPin($user, (string) $data['pin'])) { return $resp; } $out = $this->wallet->depositToVault($user, $data['amount'], $data['idempotency_key'] ?? null, $currency); return response()->json([ 'data' => ['type' => 'deposit', 'amount' => $data['amount'], 'currency' => $currency], 'balances' => [ 'balance' => $out['balance'], 'vault_balance' => $out['vault_balance'], 'vault_balances' => $out['vault_balances'], ], ], 201); } /** * POST /api/wallet/vault/withdraw */ public function withdraw(Request $request) { $user = Auth::user(); abort_unless($user, 403); $data = $request->validate([ 'amount' => ['required','string','regex:/^\d+(?:\.\d{1,4})?$/'], 'pin' => ['required','string','regex:/^\d{4,8}$/'], 'currency' => ['sometimes','string','in:' . implode(',', self::SUPPORTED_CURRENCIES)], 'idempotency_key' => ['sometimes','nullable','string','max:64'], ]); $currency = strtoupper($data['currency'] ?? 'BTX'); if ($resp = $this->wallet->verifyVaultPin($user, (string) $data['pin'])) { return $resp; } $out = $this->wallet->withdrawFromVault($user, $data['amount'], $data['idempotency_key'] ?? null, $currency); return response()->json([ 'data' => ['type' => 'withdraw', 'amount' => $data['amount'], 'currency' => $currency], 'balances' => [ 'balance' => $out['balance'], 'vault_balance' => $out['vault_balance'], 'vault_balances' => $out['vault_balances'], ], ], 201); } }