sdsf
This commit is contained in:
@@ -271,6 +271,20 @@ final class Router
|
||||
Http::json(['data' => $this->saveWalletSnapshot($projectKey, Http::input())], 201);
|
||||
}
|
||||
|
||||
if ($resource === 'wallet-withdrawals' && $method === 'GET') {
|
||||
Http::json(['data' => $this->walletWithdrawals($projectKey)]);
|
||||
}
|
||||
|
||||
if ($resource === 'wallet-withdrawals' && $method === 'POST') {
|
||||
$this->repository()->ensureProject($projectKey);
|
||||
Http::json(['data' => $this->saveWalletWithdrawal($projectKey, Http::input())], 201);
|
||||
}
|
||||
|
||||
if (preg_match('~^wallet-withdrawals/(\d+)$~', $resource, $matches) && $method === 'DELETE') {
|
||||
$this->deleteWalletWithdrawal($projectKey, (int) $matches[1]);
|
||||
Http::json(['data' => ['deleted' => true]]);
|
||||
}
|
||||
|
||||
if ($resource === 'miner-offers' && $method === 'GET') {
|
||||
Http::json(['data' => $this->minerOffers($projectKey)]);
|
||||
}
|
||||
@@ -343,6 +357,7 @@ final class Router
|
||||
'cost_plans' => [],
|
||||
'currencies' => [],
|
||||
'payouts' => [],
|
||||
'wallet_withdrawals' => [],
|
||||
'miner_offers' => [],
|
||||
'purchased_miners' => [],
|
||||
'measurement_rates' => [],
|
||||
@@ -1161,6 +1176,7 @@ final class Router
|
||||
$includeCostPlans = !array_key_exists('cost_plans', $options) || (bool) $options['cost_plans'];
|
||||
$includeCurrencies = !array_key_exists('currencies', $options) || (bool) $options['currencies'];
|
||||
$includePayouts = !array_key_exists('payouts', $options) || (bool) $options['payouts'];
|
||||
$includeWalletWithdrawals = !array_key_exists('wallet_withdrawals', $options) || (bool) $options['wallet_withdrawals'];
|
||||
$includeMinerOffers = !array_key_exists('miner_offers', $options) || (bool) $options['miner_offers'];
|
||||
$includePurchasedMiners = !array_key_exists('purchased_miners', $options) || (bool) $options['purchased_miners'];
|
||||
|
||||
@@ -1177,6 +1193,7 @@ final class Router
|
||||
'module_theme_mode' => 'inherit',
|
||||
'module_theme_accent' => 'teal',
|
||||
'preferred_currencies' => $this->preferredCurrencies(),
|
||||
'wallet_withdrawals' => [],
|
||||
];
|
||||
if (!$this->isValidTimezone((string) ($base['display_timezone'] ?? ''))) {
|
||||
$base['display_timezone'] = nexus_display_timezone_name();
|
||||
@@ -1192,6 +1209,7 @@ final class Router
|
||||
$base['currencies'] = $includeCurrencies ? $this->currencies() : [];
|
||||
$base['preferred_currencies'] = $this->preferredCurrencies($base['preferred_currencies'] ?? null);
|
||||
$base['payouts'] = $includePayouts ? $this->payouts($projectKey) : [];
|
||||
$base['wallet_withdrawals'] = $includeWalletWithdrawals ? $this->walletWithdrawals($projectKey) : [];
|
||||
$base['miner_offers'] = $includeMinerOffers ? $this->minerOffers($projectKey) : [];
|
||||
$base['purchased_miners'] = $includePurchasedMiners ? $this->purchasedMiners($projectKey) : [];
|
||||
$base['measurement_rates'] = [];
|
||||
@@ -1378,8 +1396,9 @@ final class Router
|
||||
],
|
||||
'wallet' => [
|
||||
'cost_plans' => false,
|
||||
'currencies' => false,
|
||||
'payouts' => false,
|
||||
'currencies' => true,
|
||||
'payouts' => true,
|
||||
'wallet_withdrawals' => true,
|
||||
'miner_offers' => false,
|
||||
'purchased_miners' => false,
|
||||
],
|
||||
@@ -1806,6 +1825,32 @@ final class Router
|
||||
return $this->repository()->saveWalletSnapshot($projectKey, $payload);
|
||||
}
|
||||
|
||||
private function walletWithdrawals(string $projectKey): array
|
||||
{
|
||||
if (!$this->repository()->tableExists('wallet_withdrawals')) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return $this->repository()->listWalletWithdrawals($projectKey);
|
||||
}
|
||||
|
||||
private function saveWalletWithdrawal(string $projectKey, array $input): array
|
||||
{
|
||||
$payload = [
|
||||
'withdrawal_at' => $this->requiredDateTime($input['withdrawal_at'] ?? null, 'withdrawal_at', $this->projectTimezone($projectKey)),
|
||||
'coins_amount' => $this->requiredDecimal($input['coins_amount'] ?? null, 'coins_amount'),
|
||||
'withdrawal_currency' => $this->requiredCurrency($input['withdrawal_currency'] ?? 'DOGE', 'withdrawal_currency'),
|
||||
'note' => $this->optionalString($input['note'] ?? null, 1000),
|
||||
];
|
||||
|
||||
return $this->repository()->saveWalletWithdrawal($projectKey, $payload);
|
||||
}
|
||||
|
||||
private function deleteWalletWithdrawal(string $projectKey, int $withdrawalId): void
|
||||
{
|
||||
$this->repository()->deleteWalletWithdrawal($projectKey, $withdrawalId);
|
||||
}
|
||||
|
||||
private function saveMinerOffer(string $projectKey, array $input): array
|
||||
{
|
||||
$paymentType = $this->enumValue($input['payment_type'] ?? 'fiat', ['fiat', 'crypto'], 'payment_type');
|
||||
|
||||
@@ -31,6 +31,7 @@ final class AnalyticsService
|
||||
$baselineAt = (string) ($settings['baseline_measured_at'] ?? '');
|
||||
$costPlans = is_array($settings['cost_plans'] ?? null) ? $settings['cost_plans'] : [];
|
||||
$payouts = is_array($settings['payouts'] ?? null) ? $settings['payouts'] : [];
|
||||
$walletWithdrawals = is_array($settings['wallet_withdrawals'] ?? null) ? $settings['wallet_withdrawals'] : [];
|
||||
$purchasedMiners = is_array($settings['purchased_miners'] ?? null) ? $settings['purchased_miners'] : [];
|
||||
$preferredPriceCurrencies = array_values(array_unique(array_filter([
|
||||
strtoupper(trim((string) ($settings['report_currency'] ?? ''))),
|
||||
@@ -368,7 +369,7 @@ final class AnalyticsService
|
||||
'reinvest'
|
||||
)
|
||||
: null;
|
||||
$walletBalances = $this->walletBalances($payouts, $purchasedMiners, $latestMeasuredTs);
|
||||
$walletBalances = $this->walletBalances($payouts, $walletWithdrawals, $purchasedMiners, $latestMeasuredTs);
|
||||
$latestWalletSnapshot = $this->latestWalletSnapshot(is_array($options['wallet_snapshots'] ?? null) ? $options['wallet_snapshots'] : []);
|
||||
if (is_array($latestWalletSnapshot)) {
|
||||
$snapshotBalances = $this->walletSnapshotBalances($latestWalletSnapshot);
|
||||
@@ -1297,7 +1298,7 @@ final class AnalyticsService
|
||||
return $endIndex - $startIndex + 1;
|
||||
}
|
||||
|
||||
private function walletBalances(array $payouts, array $purchasedMiners, int $measurementTs): array
|
||||
private function walletBalances(array $payouts, array $walletWithdrawals, array $purchasedMiners, int $measurementTs): array
|
||||
{
|
||||
$balances = [];
|
||||
|
||||
@@ -1334,6 +1335,21 @@ final class AnalyticsService
|
||||
$balances[$currency] = ($balances[$currency] ?? 0.0) - $amount;
|
||||
}
|
||||
|
||||
foreach ($walletWithdrawals as $withdrawal) {
|
||||
$withdrawalTs = $this->utcTimestamp((string) ($withdrawal['withdrawal_at'] ?? ''));
|
||||
if ($measurementTs > 0 && $withdrawalTs > $measurementTs) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$currency = strtoupper(trim((string) ($withdrawal['withdrawal_currency'] ?? '')));
|
||||
$amount = is_numeric($withdrawal['coins_amount'] ?? null) ? (float) $withdrawal['coins_amount'] : null;
|
||||
if ($currency === '' || $amount === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$balances[$currency] = ($balances[$currency] ?? 0.0) - $amount;
|
||||
}
|
||||
|
||||
ksort($balances);
|
||||
return array_map(fn (float $value): float => round($value, 8), $balances);
|
||||
}
|
||||
|
||||
@@ -459,6 +459,76 @@ final class MiningRepository
|
||||
]);
|
||||
}
|
||||
|
||||
public function listWalletWithdrawals(string $projectKey): array
|
||||
{
|
||||
$stmt = $this->pdo->prepare(
|
||||
'SELECT * FROM ' . $this->table('wallet_withdrawals') . ' WHERE project_key = :project_key AND owner_sub = :owner_sub ORDER BY withdrawal_at ASC, id ASC'
|
||||
);
|
||||
$stmt->execute(['project_key' => $projectKey, 'owner_sub' => $this->ownerSub]);
|
||||
return $this->normalizeRows($stmt->fetchAll() ?: []);
|
||||
}
|
||||
|
||||
public function saveWalletWithdrawal(string $projectKey, array $payload): array
|
||||
{
|
||||
if ($this->driver === 'pgsql') {
|
||||
$stmt = $this->pdo->prepare(
|
||||
'INSERT INTO ' . $this->table('wallet_withdrawals') . ' (
|
||||
project_key, owner_sub, withdrawal_at, coins_amount, withdrawal_currency, note
|
||||
) VALUES (
|
||||
:project_key, :owner_sub, :withdrawal_at, :coins_amount, :withdrawal_currency, :note
|
||||
)
|
||||
RETURNING *'
|
||||
);
|
||||
$stmt->execute([
|
||||
'project_key' => $projectKey,
|
||||
'owner_sub' => $this->ownerSub,
|
||||
'withdrawal_at' => $payload['withdrawal_at'],
|
||||
'coins_amount' => $payload['coins_amount'],
|
||||
'withdrawal_currency' => $payload['withdrawal_currency'],
|
||||
'note' => $payload['note'],
|
||||
]);
|
||||
return $this->normalizeRow($stmt->fetch() ?: []);
|
||||
}
|
||||
|
||||
$stmt = $this->pdo->prepare(
|
||||
'INSERT INTO ' . $this->table('wallet_withdrawals') . ' (
|
||||
project_key, owner_sub, withdrawal_at, coins_amount, withdrawal_currency, note
|
||||
) VALUES (
|
||||
:project_key, :owner_sub, :withdrawal_at, :coins_amount, :withdrawal_currency, :note
|
||||
)'
|
||||
);
|
||||
$stmt->execute([
|
||||
'project_key' => $projectKey,
|
||||
'owner_sub' => $this->ownerSub,
|
||||
'withdrawal_at' => $payload['withdrawal_at'],
|
||||
'coins_amount' => $payload['coins_amount'],
|
||||
'withdrawal_currency' => $payload['withdrawal_currency'],
|
||||
'note' => $payload['note'],
|
||||
]);
|
||||
|
||||
$id = (int) $this->pdo->lastInsertId();
|
||||
$fetch = $this->pdo->prepare('SELECT * FROM ' . $this->table('wallet_withdrawals') . ' WHERE id = :id LIMIT 1');
|
||||
$fetch->execute(['id' => $id]);
|
||||
return $this->normalizeRow($fetch->fetch() ?: []);
|
||||
}
|
||||
|
||||
public function deleteWalletWithdrawal(string $projectKey, int $withdrawalId): void
|
||||
{
|
||||
if ($withdrawalId <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
$stmt = $this->pdo->prepare(
|
||||
'DELETE FROM ' . $this->table('wallet_withdrawals') . '
|
||||
WHERE id = :id AND project_key = :project_key AND owner_sub = :owner_sub'
|
||||
);
|
||||
$stmt->execute([
|
||||
'id' => $withdrawalId,
|
||||
'project_key' => $projectKey,
|
||||
'owner_sub' => $this->ownerSub,
|
||||
]);
|
||||
}
|
||||
|
||||
public function listWalletSnapshots(string $projectKey, int $limit = 100): array
|
||||
{
|
||||
$stmt = $this->pdo->prepare(
|
||||
|
||||
@@ -205,6 +205,10 @@ final class SchemaManager
|
||||
$this->ensureWalletSnapshotsTable();
|
||||
$applied[] = 'wallet_snapshots_table';
|
||||
}
|
||||
if (!$this->tableExists($this->prefix . 'wallet_withdrawals')) {
|
||||
$this->ensureWalletWithdrawalsTable();
|
||||
$applied[] = 'wallet_withdrawals_table';
|
||||
}
|
||||
if (!$this->tableExists($this->prefix . 'fx_fetches') || !$this->tableExists($this->prefix . 'fx_rates')) {
|
||||
$this->ensureFxRatesTable();
|
||||
$applied[] = 'fx_rates_table';
|
||||
@@ -324,6 +328,10 @@ final class SchemaManager
|
||||
$this->ensureWalletSnapshotsTable();
|
||||
$applied[] = 'wallet_snapshots_table';
|
||||
}
|
||||
if (!$this->tableExists($this->prefix . 'wallet_withdrawals')) {
|
||||
$this->ensureWalletWithdrawalsTable();
|
||||
$applied[] = 'wallet_withdrawals_table';
|
||||
}
|
||||
|
||||
if (!$this->tableExists($this->prefix . 'miner_offers')) {
|
||||
$this->upgradeMinerOffersTable();
|
||||
@@ -679,6 +687,9 @@ final class SchemaManager
|
||||
if (!$this->tableExists($this->prefix . 'wallet_snapshots')) {
|
||||
$upgrades[] = 'wallet_snapshots_table';
|
||||
}
|
||||
if (!$this->tableExists($this->prefix . 'wallet_withdrawals')) {
|
||||
$upgrades[] = 'wallet_withdrawals_table';
|
||||
}
|
||||
if (!$this->tableExists($this->prefix . 'miner_offers')) {
|
||||
$upgrades[] = 'miner_offers_table';
|
||||
}
|
||||
@@ -978,6 +989,49 @@ final class SchemaManager
|
||||
$this->executeUpgradeStatements($statements, 'Schema-Upgrade fuer Wallet-Snapshots fehlgeschlagen.');
|
||||
}
|
||||
|
||||
public function ensureWalletWithdrawalsTable(): void
|
||||
{
|
||||
if ($this->tableExists($this->prefix . 'wallet_withdrawals')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$table = $this->prefix . 'wallet_withdrawals';
|
||||
$projectTable = $this->prefix . 'projects';
|
||||
$statements = $this->driver === 'pgsql'
|
||||
? [
|
||||
'CREATE TABLE IF NOT EXISTS ' . $table . ' (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
project_key VARCHAR(64) NOT NULL,
|
||||
owner_sub VARCHAR(128) NOT NULL,
|
||||
withdrawal_at TIMESTAMP NOT NULL,
|
||||
coins_amount NUMERIC(20,6) NOT NULL,
|
||||
withdrawal_currency VARCHAR(10) NOT NULL DEFAULT \'DOGE\',
|
||||
note TEXT,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
CONSTRAINT fk_mining_wallet_withdrawals_project FOREIGN KEY (project_key) REFERENCES ' . $projectTable . '(project_key) ON DELETE CASCADE
|
||||
)',
|
||||
'CREATE INDEX IF NOT EXISTS idx_miningcheck_wallet_withdrawals_project_owner_at ON ' . $table . ' (project_key, owner_sub, withdrawal_at)',
|
||||
]
|
||||
: [
|
||||
'CREATE TABLE IF NOT EXISTS `' . $table . '` (
|
||||
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
project_key VARCHAR(64) NOT NULL,
|
||||
owner_sub VARCHAR(128) NOT NULL,
|
||||
withdrawal_at TIMESTAMP NOT NULL,
|
||||
coins_amount DECIMAL(20,6) NOT NULL,
|
||||
withdrawal_currency VARCHAR(10) NOT NULL DEFAULT \'DOGE\',
|
||||
note TEXT,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
CONSTRAINT fk_mining_wallet_withdrawals_project FOREIGN KEY (project_key) REFERENCES `' . $projectTable . '`(project_key) ON DELETE CASCADE,
|
||||
KEY idx_miningcheck_wallet_withdrawals_project_owner_at (project_key, owner_sub, withdrawal_at)
|
||||
)',
|
||||
];
|
||||
|
||||
$this->executeUpgradeStatements($statements, 'Schema-Upgrade fuer Wallet-Auszahlungen fehlgeschlagen.');
|
||||
}
|
||||
|
||||
public function ensureMinerTables(): void
|
||||
{
|
||||
if (!$this->tableExists($this->prefix . 'miner_offers')) {
|
||||
@@ -1451,6 +1505,7 @@ final class SchemaManager
|
||||
$this->prefix . 'measurement_rates',
|
||||
$this->prefix . 'payouts',
|
||||
$this->prefix . 'wallet_snapshots',
|
||||
$this->prefix . 'wallet_withdrawals',
|
||||
$this->prefix . 'miner_offers',
|
||||
$this->prefix . 'purchased_miners',
|
||||
];
|
||||
@@ -1471,6 +1526,7 @@ final class SchemaManager
|
||||
$this->prefix . 'measurement_rates',
|
||||
$this->prefix . 'payouts',
|
||||
$this->prefix . 'wallet_snapshots',
|
||||
$this->prefix . 'wallet_withdrawals',
|
||||
$this->prefix . 'miner_offers',
|
||||
$this->prefix . 'targets',
|
||||
$this->prefix . 'dashboard_definitions',
|
||||
|
||||
Reference in New Issue
Block a user