PHP WebShell

Текущая директория: /var/www/bitcardoApp/models/crypto

Просмотр файла: create_sol_user_address.php

<?php
/**
 * File: create_sol_user_address.php
 * Purpose: Create or rotate a user's SOL address via BitGo Express.
 *
 * Depends on (must be included FIRST):
 *   create_address_helper.php
 *     - starts session (if needed)
 *     - flash_success(string), flash_error(string)
 *     - ensure_user_wallets_has_wallet_add_column(mysqli $conn)
 *     - bitgo_request(string $method, string $path, array $payload=null): array
 *     - pick_bitgo_wallet_id_for_coin(string $coin): ?string
 *
 * Triggers:
 *   - POST/GET create_sol_address=1  -> create if none exists (else reuse current Active)
 *   - POST/GET rotate_sol_address=1  -> always create NEW and archive existing Active
 */

try {
    if (!isset($conn) || !($conn instanceof mysqli)) {
        throw new RuntimeException('DB connection not available.');
    }
    foreach (['BITGO_API_BASE_URL','BITGO_ACCESS_TOKEN'] as $c) {
        if (!defined($c) || constant($c) === '') {
            throw new RuntimeException("Missing config constant: $c");
        }
    }

    // Determine action
    $create = (isset($_POST['create_sol_address']) && $_POST['create_sol_address'] == '1')
           || (isset($_GET['create_sol_address'])  && $_GET['create_sol_address']  == '1');
    $rotate = (isset($_POST['rotate_sol_address']) && $_POST['rotate_sol_address'] == '1')
           || (isset($_GET['rotate_sol_address'])  && $_GET['rotate_sol_address']  == '1');

    if (!$create && !$rotate) {
        return; // included but not triggered
    }

    if (session_status() !== PHP_SESSION_ACTIVE) {
        session_start();
    }
    if (empty($_SESSION['user_id'])) {
        throw new RuntimeException('You must be logged in.');
    }

    $userId = (int) $_SESSION['user_id'];
    $coin   = 'SOL';

    // Ensure schema has wallet_add column (after user_id)
    ensure_user_wallets_has_wallet_add_column($conn);

    // Look up current Active SOL address (if any)
    $active = null;
    $stmt = $conn->prepare("
        SELECT cwallet_id, wallet_add
        FROM user_wallets
        WHERE user_id = ? AND coin = ? AND wallet_status = 'Active'
        LIMIT 1
    ");
    if (!$stmt) throw new RuntimeException('DB prepare failed: ' . $conn->error);
    $stmt->bind_param('is', $userId, $coin);
    $stmt->execute();
    $res = $stmt->get_result();
    if ($res && $res->num_rows) {
        $active = $res->fetch_assoc();
    }
    $stmt->close();

    // If only "create" (not rotate) and we already have an active address, reuse it
    if ($create && $active && !empty($active['wallet_add'])) {
        flash_success("SOL address already exists: " . $active['wallet_add']);
        header('Location: index.php');
        exit;
    }

    // Fetch user email for labeling the BitGo address
    $userEmail = null;
    $stmt = $conn->prepare("SELECT email FROM users WHERE user_id = ? LIMIT 1");
    if ($stmt) {
        $stmt->bind_param('i', $userId);
        $stmt->execute();
        $res = $stmt->get_result();
        if ($res && $row = $res->fetch_assoc()) {
            $userEmail = $row['email'] ?? null;
        }
        $stmt->close();
    }

    // Build label for BitGo
    $bitgoLabel = $userEmail ? ("User: " . $userEmail) : ("UserID: " . $userId);

    // Pick the BitGo SOL wallet id (only for API; NOT stored in DB)
    $bitgoWalletId = pick_bitgo_wallet_id_for_coin('sol');
    if (!$bitgoWalletId) {
        throw new RuntimeException('No SOL wallet found in BitGo.');
    }

    // Create one new SOL receive address with label
    $addrObj = bitgo_request(
        'POST',
        'sol/wallet/' . rawurlencode($bitgoWalletId) . '/address',
        ['label' => $bitgoLabel]
    );
    $address = $addrObj['address'] ?? null;
    if (!$address) {
        throw new RuntimeException('BitGo did not return a SOL address.');
    }

    // Default SOL wallet fields
    $bankName = 'bitcardo';
    $icon     = 'sol.png';       // make sure this icon exists in your assets/icons
    $balance  = '0.000000000';   // 9 decimals for SOL
    $type     = 'crypto';
    $label    = 'SOL Wallet';

    $conn->begin_transaction();
    try {
        if (($rotate || $active) && !empty($active['cwallet_id'])) {
            $stmt = $conn->prepare("UPDATE user_wallets SET wallet_status = 'Archived' WHERE cwallet_id = ?");
            if (!$stmt) throw new RuntimeException('DB prepare failed: ' . $conn->error);
            $stmt->bind_param('i', $active['cwallet_id']);
            if (!$stmt->execute()) throw new RuntimeException('DB archive failed: ' . $stmt->error);
            $stmt->close();
        }

        // Insert new Active SOL entry
        $sql = "INSERT INTO user_wallets
                  (user_id, wallet_add, bank_name, coin, icon, balance, type, label, wallet_status)
                VALUES
                  (?,?,?,?,?,?,?,?,?)";
        $stmt = $conn->prepare($sql);
        if (!$stmt) throw new RuntimeException('DB prepare failed: ' . $conn->error);
        $status = 'Active';
        $stmt->bind_param(
            'issssssss',
            $userId,
            $address,
            $bankName,
            $coin,
            $icon,
            $balance,
            $type,
            $label,
            $status
        );
        if (!$stmt->execute()) throw new RuntimeException('DB insert failed: ' . $stmt->error);
        $stmt->close();

        $conn->commit();
    } catch (Throwable $tx) {
        $conn->rollback();
        throw $tx;
    }

    $verb = ($rotate || $active) ? 'rotated' : 'created';
    flash_success("SOL address $verb: " . $address);

    // Redirect back to dashboard so the new wallet shows immediately
    header('Location: index.php');
    exit;

} catch (Throwable $e) {
    flash_error($e->getMessage());
    header('Location: index.php');
    exit;
}

Выполнить команду


Для локальной разработки. Не используйте в интернете!