Split peyawallet into lite and mining variants
build / Build Linux (lite) (push) Successful in 2m19s
build / Build Linux (mining) (push) Successful in 2m48s
build / Build Windows (lite) (push) Successful in 21m58s
build / Build Windows (mining) (push) Has been cancelled

This commit is contained in:
Codex Bot
2026-04-20 22:42:52 +02:00
parent 32b38820d6
commit b4d32e5ea8
14 changed files with 1263 additions and 70 deletions
+63 -15
View File
@@ -1,5 +1,5 @@
name: build
run-name: build wallet (peya=${{ inputs.peya_release_tag || 'latest' }}, monero_c=${{ inputs.monero_c_release_tag || 'latest' }})
run-name: build wallet variants (peya=${{ inputs.peya_release_tag || 'latest' }}, monero_c=${{ inputs.monero_c_release_tag || 'latest' }}, xmrig=${{ inputs.xmrig_release_tag || 'latest' }})
on:
workflow_dispatch:
@@ -12,6 +12,10 @@ on:
description: monero_c release tag to bundle runtime from
required: false
default: latest
xmrig_release_tag:
description: xmrig release tag to bundle mining runtime from
required: false
default: latest
push:
branches:
- develop
@@ -29,11 +33,20 @@ on:
jobs:
build-linux:
name: Build Linux wallet
name: Build Linux (${{ matrix.flavor }})
runs-on: ubuntu-22.04
strategy:
fail-fast: false
matrix:
include:
- flavor: lite
enable_mining: "false"
- flavor: mining
enable_mining: "true"
env:
PEYA_RELEASE_TAG: ${{ inputs.peya_release_tag }}
MONERO_C_RELEASE_TAG: ${{ inputs.monero_c_release_tag }}
XMRIG_RELEASE_TAG: ${{ inputs.xmrig_release_tag }}
steps:
- name: Checkout
uses: https://github.com/actions/checkout@v4
@@ -82,33 +95,56 @@ jobs:
MONERO_C_GITEA_PAT: ${{ secrets.MONERO_C_GITEA_PAT }}
GITEA_PAT: ${{ secrets.PEYA_GITEA_PAT }}
run: |
set -euo pipefail
EXTRA_ARGS=()
if [ "${{ matrix.flavor }}" = "mining" ]; then
EXTRA_ARGS+=(--xmrig-tag "${XMRIG_RELEASE_TAG:-latest}")
fi
python3 scripts/ci/stage_release_runtime.py \
--platform linux \
--peya-tag "${PEYA_RELEASE_TAG:-latest}" \
--monero-c-tag "${MONERO_C_RELEASE_TAG:-latest}" \
--repo-root .
--repo-root . \
"${EXTRA_ARGS[@]}"
- name: Fetch Dart/Flutter deps
run: |
flutter pub get
run: flutter pub get
- name: Build Linux release
run: |
flutter build linux --release
flutter build linux --release \
--dart-define=PEYA_ENABLE_MINING=${{ matrix.enable_mining }} \
--dart-define=PEYA_RELEASE_FLAVOR=${{ matrix.flavor }}
- name: Bundle xmrig
if: ${{ matrix.flavor == 'mining' }}
run: |
set -euo pipefail
install -Dm755 external/miner/xmrig \
build/linux/x64/release/bundle/external/miner/xmrig
- name: Upload Linux bundle
uses: https://github.com/actions/upload-artifact@v3
with:
name: peyawallet-linux-release
name: peyawallet-${{ matrix.flavor }}-linux-release
path: build/linux/x64/release/bundle/**
if-no-files-found: error
build-windows:
name: Build Windows wallet
name: Build Windows (${{ matrix.flavor }})
runs-on: windows-latest
strategy:
fail-fast: false
matrix:
include:
- flavor: lite
enable_mining: "false"
- flavor: mining
enable_mining: "true"
env:
PEYA_RELEASE_TAG: ${{ inputs.peya_release_tag }}
MONERO_C_RELEASE_TAG: ${{ inputs.monero_c_release_tag }}
XMRIG_RELEASE_TAG: ${{ inputs.xmrig_release_tag }}
steps:
- name: Checkout
uses: https://github.com/actions/checkout@v4
@@ -140,30 +176,42 @@ jobs:
MONERO_C_GITEA_PAT: ${{ secrets.PEYA_GITEA_PAT }}
run: |
set -euo pipefail
EXTRA_ARGS=()
if [ "${{ matrix.flavor }}" = "mining" ]; then
EXTRA_ARGS+=(--xmrig-tag "${XMRIG_RELEASE_TAG:-latest}")
fi
python -u scripts/ci/stage_release_runtime.py \
--platform windows \
--peya-tag "${PEYA_RELEASE_TAG:-latest}" \
--monero-c-tag "${MONERO_C_RELEASE_TAG:-latest}" \
--repo-root .
--repo-root . \
"${EXTRA_ARGS[@]}"
- name: Show toolchain
shell: bash
run: |
flutter doctor -v
run: flutter doctor -v
- name: Fetch Dart/Flutter deps
shell: bash
run: |
flutter pub get
run: flutter pub get
- name: Build Windows release
shell: bash
run: |
flutter build windows --release
flutter build windows --release \
--dart-define=PEYA_ENABLE_MINING=${{ matrix.enable_mining }} \
--dart-define=PEYA_RELEASE_FLAVOR=${{ matrix.flavor }}
- name: Bundle xmrig
if: ${{ matrix.flavor == 'mining' }}
shell: cmd
run: |
if not exist build\windows\x64\runner\Release\external\miner mkdir build\windows\x64\runner\Release\external\miner
copy external\miner\xmrig.exe build\windows\x64\runner\Release\external\miner\xmrig.exe
- name: Upload Windows bundle
uses: https://github.com/actions/upload-artifact@v3
with:
name: peyawallet-windows-release
name: peyawallet-${{ matrix.flavor }}-windows-release
path: build/windows/x64/runner/Release/**
if-no-files-found: error
+63 -15
View File
@@ -1,5 +1,5 @@
name: release
run-name: release wallet ${{ inputs.tag_name }}
run-name: release wallet variants ${{ inputs.tag_name }}
on:
workflow_dispatch:
@@ -19,6 +19,10 @@ on:
description: monero_c release tag to bundle runtime from
required: false
default: latest
xmrig_release_tag:
description: xmrig release tag to bundle mining runtime from
required: false
default: latest
release_name:
description: Optional release title
required: false
@@ -121,12 +125,21 @@ jobs:
echo "release_id=$(jq -r '.id' /tmp/release.json)" >> "$GITHUB_OUTPUT"
build-linux:
name: Build Linux release
name: Build Linux release (${{ matrix.flavor }})
needs: create-release
runs-on: ubuntu-22.04
strategy:
fail-fast: false
matrix:
include:
- flavor: lite
enable_mining: "false"
- flavor: mining
enable_mining: "true"
env:
PEYA_RELEASE_TAG: ${{ inputs.peya_release_tag }}
MONERO_C_RELEASE_TAG: ${{ inputs.monero_c_release_tag }}
XMRIG_RELEASE_TAG: ${{ inputs.xmrig_release_tag }}
steps:
- name: Checkout
uses: https://github.com/actions/checkout@v4
@@ -178,26 +191,40 @@ jobs:
MONERO_C_GITEA_PAT: ${{ secrets.MONERO_C_GITEA_PAT }}
GITEA_PAT: ${{ secrets.GITEA_PAT }}
run: |
set -euo pipefail
EXTRA_ARGS=()
if [ "${{ matrix.flavor }}" = "mining" ]; then
EXTRA_ARGS+=(--xmrig-tag "${XMRIG_RELEASE_TAG:-latest}")
fi
python3 scripts/ci/stage_release_runtime.py \
--platform linux \
--peya-tag "${PEYA_RELEASE_TAG:-latest}" \
--monero-c-tag "${MONERO_C_RELEASE_TAG:-latest}" \
--repo-root .
--repo-root . \
"${EXTRA_ARGS[@]}"
- name: Fetch Dart/Flutter deps
run: |
flutter pub get
run: flutter pub get
- name: Build Linux release
run: |
flutter build linux --release
flutter build linux --release \
--dart-define=PEYA_ENABLE_MINING=${{ matrix.enable_mining }} \
--dart-define=PEYA_RELEASE_FLAVOR=${{ matrix.flavor }}
- name: Bundle xmrig
if: ${{ matrix.flavor == 'mining' }}
run: |
set -euo pipefail
install -Dm755 external/miner/xmrig \
build/linux/x64/release/bundle/external/miner/xmrig
- name: Package Linux release
env:
TAG_NAME: ${{ inputs.tag_name }}
run: |
set -euo pipefail
archive="/tmp/peyawallet-${TAG_NAME}-linux-x86_64.tar.gz"
archive="/tmp/peyawallet-${{ matrix.flavor }}-${TAG_NAME}-linux-x86_64.tar.gz"
tar -C build/linux/x64/release/bundle -czf "${archive}" .
echo "ARCHIVE_PATH=${archive}" >> "$GITHUB_ENV"
echo "ARCHIVE_NAME=$(basename "${archive}")" >> "$GITHUB_ENV"
@@ -244,12 +271,21 @@ jobs:
>/dev/null
build-windows:
name: Build Windows release
name: Build Windows release (${{ matrix.flavor }})
needs: create-release
runs-on: windows-latest
strategy:
fail-fast: false
matrix:
include:
- flavor: lite
enable_mining: "false"
- flavor: mining
enable_mining: "true"
env:
PEYA_RELEASE_TAG: ${{ inputs.peya_release_tag }}
MONERO_C_RELEASE_TAG: ${{ inputs.monero_c_release_tag }}
XMRIG_RELEASE_TAG: ${{ inputs.xmrig_release_tag }}
steps:
- name: Checkout
uses: https://github.com/actions/checkout@v4
@@ -282,26 +318,38 @@ jobs:
GITEA_PAT: ${{ secrets.GITEA_PAT }}
run: |
set -euo pipefail
EXTRA_ARGS=()
if [ "${{ matrix.flavor }}" = "mining" ]; then
EXTRA_ARGS+=(--xmrig-tag "${XMRIG_RELEASE_TAG:-latest}")
fi
python -u scripts/ci/stage_release_runtime.py \
--platform windows \
--peya-tag "${PEYA_RELEASE_TAG:-latest}" \
--monero-c-tag "${MONERO_C_RELEASE_TAG:-latest}" \
--repo-root .
--repo-root . \
"${EXTRA_ARGS[@]}"
- name: Show toolchain
shell: bash
run: |
flutter doctor -v
run: flutter doctor -v
- name: Fetch Dart/Flutter deps
shell: bash
run: |
flutter pub get
run: flutter pub get
- name: Build Windows release
shell: bash
run: |
flutter build windows --release
flutter build windows --release \
--dart-define=PEYA_ENABLE_MINING=${{ matrix.enable_mining }} \
--dart-define=PEYA_RELEASE_FLAVOR=${{ matrix.flavor }}
- name: Bundle xmrig
if: ${{ matrix.flavor == 'mining' }}
shell: cmd
run: |
if not exist build\windows\x64\runner\Release\external\miner mkdir build\windows\x64\runner\Release\external\miner
copy external\miner\xmrig.exe build\windows\x64\runner\Release\external\miner\xmrig.exe
- name: Package Windows release
shell: bash
@@ -309,7 +357,7 @@ jobs:
TAG_NAME: ${{ inputs.tag_name }}
run: |
set -euo pipefail
archive="C:/Windows/Temp/peyawallet-${TAG_NAME}-windows-x86_64.zip"
archive="C:/Windows/Temp/peyawallet-${{ matrix.flavor }}-${TAG_NAME}-windows-x86_64.zip"
powershell.exe -NoProfile -Command "if (Test-Path '${archive}') { Remove-Item '${archive}' -Force }; Compress-Archive -Path 'build/windows/x64/runner/Release/*' -DestinationPath '${archive}'"
echo "ARCHIVE_PATH=${archive}" >> "$GITHUB_ENV"
echo "ARCHIVE_NAME=$(basename "${archive}")" >> "$GITHUB_ENV"
+2
View File
@@ -31,6 +31,8 @@ migrate_working_dir/
.pub/
/build/
/external/
/third_party/daemon/
/third_party/monero_c/
# Local working files
codex_resume.txt
+13
View File
@@ -0,0 +1,13 @@
abstract final class AppFeatures {
static const bool enableMining = bool.fromEnvironment(
'PEYA_ENABLE_MINING',
defaultValue: true,
);
static const String releaseFlavor = String.fromEnvironment(
'PEYA_RELEASE_FLAVOR',
defaultValue: 'mining',
);
static bool get isMiningFlavor => enableMining;
}
+72
View File
@@ -6,6 +6,8 @@ enum NodeMode { local, remote }
enum LanguagePreference { system, english, polish }
enum MiningMode { solo, pool }
class RemoteNode {
const RemoteNode({
required this.host,
@@ -223,6 +225,61 @@ class SyncStatus {
}
}
class MiningConfig {
const MiningConfig({
required this.mode,
required this.cpuThreads,
required this.poolHost,
required this.poolPort,
required this.apiPort,
});
final MiningMode mode;
final int cpuThreads;
final String poolHost;
final int poolPort;
final int apiPort;
MiningConfig copyWith({
MiningMode? mode,
int? cpuThreads,
String? poolHost,
int? poolPort,
int? apiPort,
}) {
return MiningConfig(
mode: mode ?? this.mode,
cpuThreads: cpuThreads ?? this.cpuThreads,
poolHost: poolHost ?? this.poolHost,
poolPort: poolPort ?? this.poolPort,
apiPort: apiPort ?? this.apiPort,
);
}
Map<String, dynamic> toJson() {
return {
'mode': mode.name,
'cpuThreads': cpuThreads,
'poolHost': poolHost,
'poolPort': poolPort,
'apiPort': apiPort,
};
}
factory MiningConfig.fromJson(Map<String, dynamic> json) {
return MiningConfig(
mode: MiningMode.values.firstWhere(
(value) => value.name == (json['mode'] as String? ?? 'solo'),
orElse: () => MiningMode.solo,
),
cpuThreads: (json['cpuThreads'] as num?)?.toInt() ?? 1,
poolHost: json['poolHost'] as String? ?? 'peya.cryptohash.top',
poolPort: (json['poolPort'] as num?)?.toInt() ?? 3333,
apiPort: (json['apiPort'] as num?)?.toInt() ?? 18091,
);
}
}
class AppConfig {
const AppConfig({
required this.lastWallet,
@@ -235,6 +292,7 @@ class AppConfig {
required this.languagePreference,
required this.hiddenSubaddresses,
required this.localNodeArgs,
required this.miningConfig,
required this.p2poolStratum,
required this.p2poolP2p,
required this.p2poolStartMining,
@@ -251,6 +309,7 @@ class AppConfig {
final LanguagePreference languagePreference;
final Map<String, List<String>> hiddenSubaddresses;
final List<String> localNodeArgs;
final MiningConfig miningConfig;
final String p2poolStratum;
final String p2poolP2p;
final bool p2poolStartMining;
@@ -267,6 +326,7 @@ class AppConfig {
LanguagePreference? languagePreference,
Map<String, List<String>>? hiddenSubaddresses,
List<String>? localNodeArgs,
MiningConfig? miningConfig,
String? p2poolStratum,
String? p2poolP2p,
bool? p2poolStartMining,
@@ -283,6 +343,7 @@ class AppConfig {
languagePreference: languagePreference ?? this.languagePreference,
hiddenSubaddresses: hiddenSubaddresses ?? this.hiddenSubaddresses,
localNodeArgs: localNodeArgs ?? this.localNodeArgs,
miningConfig: miningConfig ?? this.miningConfig,
p2poolStratum: p2poolStratum ?? this.p2poolStratum,
p2poolP2p: p2poolP2p ?? this.p2poolP2p,
p2poolStartMining: p2poolStartMining ?? this.p2poolStartMining,
@@ -306,6 +367,13 @@ class AppConfig {
languagePreference: LanguagePreference.system,
hiddenSubaddresses: const {},
localNodeArgs: const [],
miningConfig: const MiningConfig(
mode: MiningMode.solo,
cpuThreads: 1,
poolHost: 'peya.cryptohash.top',
poolPort: 3333,
apiPort: 18091,
),
p2poolStratum: '0.0.0.0:3333',
p2poolP2p: '0.0.0.0:38889',
p2poolStartMining: false,
@@ -325,6 +393,7 @@ class AppConfig {
'languagePreference': languagePreference.name,
'hiddenSubaddresses': hiddenSubaddresses,
'localNodeArgs': localNodeArgs,
'miningConfig': miningConfig.toJson(),
'p2poolStratum': p2poolStratum,
'p2poolP2p': p2poolP2p,
'p2poolStartMining': p2poolStartMining,
@@ -349,6 +418,8 @@ class AppConfig {
final p2poolStartMining = json['p2poolStartMining'] as bool? ?? false;
final p2poolMiningThreads =
(json['p2poolMiningThreads'] as num?)?.toInt() ?? 1;
final miningConfigJson =
json['miningConfig'] as Map<String, dynamic>? ?? const {};
return AppConfig(
lastWallet: json['lastWallet'] == null
? null
@@ -374,6 +445,7 @@ class AppConfig {
),
hiddenSubaddresses: hidden,
localNodeArgs: localNodeArgs,
miningConfig: MiningConfig.fromJson(miningConfigJson),
p2poolStratum: p2poolStratum,
p2poolP2p: p2poolP2p,
p2poolStartMining: p2poolStartMining,
+25
View File
@@ -345,6 +345,31 @@
"miningThreadsLabel": "CPU threads",
"miningSettingsSaved": "Mining settings saved.",
"miningCurrentConfigTitle": "Current configuration",
"miningScreenSubtitle": "Configure the CPU miner release now. Process control and live XMRig stats land in the next step.",
"miningSourceTitle": "Source",
"miningModeLabel": "Mining mode",
"miningModeSolo": "Solo to local daemon",
"miningModePool": "Pool",
"miningTargetLabel": "Target",
"miningSoloTargetValue": "127.0.0.1:17750 (local Peya daemon)",
"miningSoloHint": "Solo mode will target the local daemon bundled with the wallet.",
"miningSoloNeedsLocalNode": "Solo mode expects the wallet to use the local node.",
"miningPoolHint": "Default pool is preconfigured for Peya and can be adjusted here.",
"miningApiPortLabel": "XMRig API port",
"miningResetDraftAction": "Reset draft",
"miningConfigInvalid": "Enter a valid pool host and ports.",
"miningControlsTitle": "Controls",
"miningBackendPending": "Miner process control will be enabled in the next step. This screen already stores the target config and release layout.",
"miningStatsTitle": "Stats",
"miningHashrate10sLabel": "Hashrate (10s)",
"miningHashrate1mLabel": "Hashrate (1m)",
"miningJobsLabel": "Jobs",
"miningAcceptedSharesLabel": "Accepted shares",
"miningRejectedSharesLabel": "Rejected shares",
"miningBundledTitle": "Bundled miner",
"miningBundledEnabled": "This build includes the bundled XMRig binary.",
"miningBundledDisabled": "This release flavor does not include the bundled miner.",
"miningBundledBody": "Mining releases bundle XMRig from the dedicated Peya xmrig repo. Lite releases hide the tab entirely.",
"miningStartMiningEnabled": "Enabled ({threads} threads)",
"@miningStartMiningEnabled": {
"placeholders": {
+150
View File
@@ -1694,6 +1694,156 @@ abstract class AppLocalizations {
/// **'Current configuration'**
String get miningCurrentConfigTitle;
/// No description provided for @miningScreenSubtitle.
///
/// In en, this message translates to:
/// **'Configure the CPU miner release now. Process control and live XMRig stats land in the next step.'**
String get miningScreenSubtitle;
/// No description provided for @miningSourceTitle.
///
/// In en, this message translates to:
/// **'Source'**
String get miningSourceTitle;
/// No description provided for @miningModeLabel.
///
/// In en, this message translates to:
/// **'Mining mode'**
String get miningModeLabel;
/// No description provided for @miningModeSolo.
///
/// In en, this message translates to:
/// **'Solo to local daemon'**
String get miningModeSolo;
/// No description provided for @miningModePool.
///
/// In en, this message translates to:
/// **'Pool'**
String get miningModePool;
/// No description provided for @miningTargetLabel.
///
/// In en, this message translates to:
/// **'Target'**
String get miningTargetLabel;
/// No description provided for @miningSoloTargetValue.
///
/// In en, this message translates to:
/// **'127.0.0.1:17750 (local Peya daemon)'**
String get miningSoloTargetValue;
/// No description provided for @miningSoloHint.
///
/// In en, this message translates to:
/// **'Solo mode will target the local daemon bundled with the wallet.'**
String get miningSoloHint;
/// No description provided for @miningSoloNeedsLocalNode.
///
/// In en, this message translates to:
/// **'Solo mode expects the wallet to use the local node.'**
String get miningSoloNeedsLocalNode;
/// No description provided for @miningPoolHint.
///
/// In en, this message translates to:
/// **'Default pool is preconfigured for Peya and can be adjusted here.'**
String get miningPoolHint;
/// No description provided for @miningApiPortLabel.
///
/// In en, this message translates to:
/// **'XMRig API port'**
String get miningApiPortLabel;
/// No description provided for @miningResetDraftAction.
///
/// In en, this message translates to:
/// **'Reset draft'**
String get miningResetDraftAction;
/// No description provided for @miningConfigInvalid.
///
/// In en, this message translates to:
/// **'Enter a valid pool host and ports.'**
String get miningConfigInvalid;
/// No description provided for @miningControlsTitle.
///
/// In en, this message translates to:
/// **'Controls'**
String get miningControlsTitle;
/// No description provided for @miningBackendPending.
///
/// In en, this message translates to:
/// **'Miner process control will be enabled in the next step. This screen already stores the target config and release layout.'**
String get miningBackendPending;
/// No description provided for @miningStatsTitle.
///
/// In en, this message translates to:
/// **'Stats'**
String get miningStatsTitle;
/// No description provided for @miningHashrate10sLabel.
///
/// In en, this message translates to:
/// **'Hashrate (10s)'**
String get miningHashrate10sLabel;
/// No description provided for @miningHashrate1mLabel.
///
/// In en, this message translates to:
/// **'Hashrate (1m)'**
String get miningHashrate1mLabel;
/// No description provided for @miningJobsLabel.
///
/// In en, this message translates to:
/// **'Jobs'**
String get miningJobsLabel;
/// No description provided for @miningAcceptedSharesLabel.
///
/// In en, this message translates to:
/// **'Accepted shares'**
String get miningAcceptedSharesLabel;
/// No description provided for @miningRejectedSharesLabel.
///
/// In en, this message translates to:
/// **'Rejected shares'**
String get miningRejectedSharesLabel;
/// No description provided for @miningBundledTitle.
///
/// In en, this message translates to:
/// **'Bundled miner'**
String get miningBundledTitle;
/// No description provided for @miningBundledEnabled.
///
/// In en, this message translates to:
/// **'This build includes the bundled XMRig binary.'**
String get miningBundledEnabled;
/// No description provided for @miningBundledDisabled.
///
/// In en, this message translates to:
/// **'This release flavor does not include the bundled miner.'**
String get miningBundledDisabled;
/// No description provided for @miningBundledBody.
///
/// In en, this message translates to:
/// **'Mining releases bundle XMRig from the dedicated Peya xmrig repo. Lite releases hide the tab entirely.'**
String get miningBundledBody;
/// No description provided for @miningStartMiningEnabled.
///
/// In en, this message translates to:
+83
View File
@@ -850,6 +850,89 @@ class AppLocalizationsEn extends AppLocalizations {
@override
String get miningCurrentConfigTitle => 'Current configuration';
@override
String get miningScreenSubtitle =>
'Configure the CPU miner release now. Process control and live XMRig stats land in the next step.';
@override
String get miningSourceTitle => 'Source';
@override
String get miningModeLabel => 'Mining mode';
@override
String get miningModeSolo => 'Solo to local daemon';
@override
String get miningModePool => 'Pool';
@override
String get miningTargetLabel => 'Target';
@override
String get miningSoloTargetValue => '127.0.0.1:17750 (local Peya daemon)';
@override
String get miningSoloHint =>
'Solo mode will target the local daemon bundled with the wallet.';
@override
String get miningSoloNeedsLocalNode =>
'Solo mode expects the wallet to use the local node.';
@override
String get miningPoolHint =>
'Default pool is preconfigured for Peya and can be adjusted here.';
@override
String get miningApiPortLabel => 'XMRig API port';
@override
String get miningResetDraftAction => 'Reset draft';
@override
String get miningConfigInvalid => 'Enter a valid pool host and ports.';
@override
String get miningControlsTitle => 'Controls';
@override
String get miningBackendPending =>
'Miner process control will be enabled in the next step. This screen already stores the target config and release layout.';
@override
String get miningStatsTitle => 'Stats';
@override
String get miningHashrate10sLabel => 'Hashrate (10s)';
@override
String get miningHashrate1mLabel => 'Hashrate (1m)';
@override
String get miningJobsLabel => 'Jobs';
@override
String get miningAcceptedSharesLabel => 'Accepted shares';
@override
String get miningRejectedSharesLabel => 'Rejected shares';
@override
String get miningBundledTitle => 'Bundled miner';
@override
String get miningBundledEnabled =>
'This build includes the bundled XMRig binary.';
@override
String get miningBundledDisabled =>
'This release flavor does not include the bundled miner.';
@override
String get miningBundledBody =>
'Mining releases bundle XMRig from the dedicated Peya xmrig repo. Lite releases hide the tab entirely.';
@override
String miningStartMiningEnabled(Object threads) {
return 'Enabled ($threads threads)';
+83
View File
@@ -854,6 +854,89 @@ class AppLocalizationsPl extends AppLocalizations {
@override
String get miningCurrentConfigTitle => 'Aktualna konfiguracja';
@override
String get miningScreenSubtitle =>
'Tu konfigurujesz wariant CPU miner. Sterowanie procesem i żywe statystyki XMRig dojdą w następnym kroku.';
@override
String get miningSourceTitle => 'Źródło';
@override
String get miningModeLabel => 'Tryb kopania';
@override
String get miningModeSolo => 'Solo do lokalnego daemona';
@override
String get miningModePool => 'Pool';
@override
String get miningTargetLabel => 'Cel';
@override
String get miningSoloTargetValue => '127.0.0.1:17750 (lokalny daemon Peya)';
@override
String get miningSoloHint =>
'Tryb solo będzie kierował kopanie do lokalnego daemona bundlowanego z walletem.';
@override
String get miningSoloNeedsLocalNode =>
'Tryb solo zakłada, że portfel korzysta z lokalnego noda.';
@override
String get miningPoolHint =>
'Domyślny pool dla Peya jest już wpisany i można go tu zmienić.';
@override
String get miningApiPortLabel => 'Port API XMRig';
@override
String get miningResetDraftAction => 'Przywróć szkic';
@override
String get miningConfigInvalid => 'Podaj poprawny host poola i porty.';
@override
String get miningControlsTitle => 'Sterowanie';
@override
String get miningBackendPending =>
'Sterowanie procesem minera zostanie dopięte w następnym kroku. Ten ekran zapisuje już docelową konfigurację i układ releasu.';
@override
String get miningStatsTitle => 'Statystyki';
@override
String get miningHashrate10sLabel => 'Hashrate (10s)';
@override
String get miningHashrate1mLabel => 'Hashrate (1m)';
@override
String get miningJobsLabel => 'Joby';
@override
String get miningAcceptedSharesLabel => 'Zaakceptowane udziały';
@override
String get miningRejectedSharesLabel => 'Odrzucone udziały';
@override
String get miningBundledTitle => 'Bundlowany miner';
@override
String get miningBundledEnabled =>
'Ten build zawiera bundlowaną binarkę XMRig.';
@override
String get miningBundledDisabled =>
'Ten wariant releasu nie zawiera bundlowanego minera.';
@override
String get miningBundledBody =>
'Warianty mining bundle\'ują XMRig z dedykowanego repo Peya xmrig. Wariant lite całkowicie ukrywa ten tab.';
@override
String miningStartMiningEnabled(Object threads) {
return 'Włączony ($threads wątków)';
+25
View File
@@ -345,6 +345,31 @@
"miningThreadsLabel": "Wątki CPU",
"miningSettingsSaved": "Ustawienia mining zapisane.",
"miningCurrentConfigTitle": "Aktualna konfiguracja",
"miningScreenSubtitle": "Tu konfigurujesz wariant CPU miner. Sterowanie procesem i żywe statystyki XMRig dojdą w następnym kroku.",
"miningSourceTitle": "Źródło",
"miningModeLabel": "Tryb kopania",
"miningModeSolo": "Solo do lokalnego daemona",
"miningModePool": "Pool",
"miningTargetLabel": "Cel",
"miningSoloTargetValue": "127.0.0.1:17750 (lokalny daemon Peya)",
"miningSoloHint": "Tryb solo będzie kierował kopanie do lokalnego daemona bundlowanego z walletem.",
"miningSoloNeedsLocalNode": "Tryb solo zakłada, że portfel korzysta z lokalnego noda.",
"miningPoolHint": "Domyślny pool dla Peya jest już wpisany i można go tu zmienić.",
"miningApiPortLabel": "Port API XMRig",
"miningResetDraftAction": "Przywróć szkic",
"miningConfigInvalid": "Podaj poprawny host poola i porty.",
"miningControlsTitle": "Sterowanie",
"miningBackendPending": "Sterowanie procesem minera zostanie dopięte w następnym kroku. Ten ekran zapisuje już docelową konfigurację i układ releasu.",
"miningStatsTitle": "Statystyki",
"miningHashrate10sLabel": "Hashrate (10s)",
"miningHashrate1mLabel": "Hashrate (1m)",
"miningJobsLabel": "Joby",
"miningAcceptedSharesLabel": "Zaakceptowane udziały",
"miningRejectedSharesLabel": "Odrzucone udziały",
"miningBundledTitle": "Bundlowany miner",
"miningBundledEnabled": "Ten build zawiera bundlowaną binarkę XMRig.",
"miningBundledDisabled": "Ten wariant releasu nie zawiera bundlowanego minera.",
"miningBundledBody": "Warianty mining bundle'ują XMRig z dedykowanego repo Peya xmrig. Wariant lite całkowicie ukrywa ten tab.",
"miningStartMiningEnabled": "Włączony ({threads} wątków)",
"@miningStartMiningEnabled": {
"placeholders": {
+42
View File
@@ -46,6 +46,48 @@ class AppConfigController extends StateNotifier<AppConfig> {
await updateConfig(state.copyWith(localNodeArgs: args));
}
Future<void> setMiningConfig(MiningConfig config) async {
await updateConfig(state.copyWith(miningConfig: config));
}
Future<void> setMiningMode(MiningMode mode) async {
await updateConfig(
state.copyWith(miningConfig: state.miningConfig.copyWith(mode: mode)),
);
}
Future<void> setMiningCpuThreads(int value) async {
await updateConfig(
state.copyWith(
miningConfig: state.miningConfig.copyWith(cpuThreads: value),
),
);
}
Future<void> setMiningPoolHost(String value) async {
await updateConfig(
state.copyWith(
miningConfig: state.miningConfig.copyWith(poolHost: value),
),
);
}
Future<void> setMiningPoolPort(int value) async {
await updateConfig(
state.copyWith(
miningConfig: state.miningConfig.copyWith(poolPort: value),
),
);
}
Future<void> setMiningApiPort(int value) async {
await updateConfig(
state.copyWith(
miningConfig: state.miningConfig.copyWith(apiPort: value),
),
);
}
Future<void> setP2poolStratum(String value) async {
await updateConfig(state.copyWith(p2poolStratum: value));
}
+69 -33
View File
@@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
import 'package:material_symbols_icons/material_symbols_icons.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../../app_features.dart';
import '../l10n/app_localizations_ext.dart';
import '../widgets/status_bar.dart';
import 'account_screen.dart';
@@ -25,16 +26,54 @@ class _HomeShellState extends ConsumerState<HomeShell> {
@override
Widget build(BuildContext context) {
final l10n = context.l10n;
final screens = <Widget>[
const AccountScreen(),
const SendScreen(),
const ReceiveScreen(),
const StakingScreen(),
const MiningScreen(),
const TransactionsScreen(),
const SettingsScreen(),
final items = <_NavItem>[
_NavItem(
icon: const Icon(Symbols.account_box),
label: l10n.accountTitle,
screen: const AccountScreen(),
),
_NavItem(
icon: const Icon(Symbols.call_made),
label: l10n.sendTitle,
screen: const SendScreen(),
),
_NavItem(
icon: const Icon(Symbols.call_received),
label: l10n.receiveTitle,
screen: const ReceiveScreen(),
),
_NavItem(
icon: const Icon(Symbols.chart_data),
label: l10n.stakingTitle,
screen: const StakingScreen(),
),
if (AppFeatures.enableMining)
_NavItem(
icon: const Icon(Symbols.memory),
label: l10n.miningTitle,
screen: const MiningScreen(),
),
_NavItem(
icon: const Icon(Symbols.list_alt),
label: l10n.transactionsTitle,
screen: const TransactionsScreen(),
),
_NavItem(
icon: const Icon(Symbols.settings),
label: l10n.settingsTitle,
screen: const SettingsScreen(),
),
];
final selectedIndex = _selectedIndex.clamp(0, items.length - 1);
if (selectedIndex != _selectedIndex) {
WidgetsBinding.instance.addPostFrameCallback((_) {
if (mounted) {
setState(() => _selectedIndex = selectedIndex);
}
});
}
return Scaffold(
body: Row(
children: [
@@ -42,7 +81,7 @@ class _HomeShellState extends ConsumerState<HomeShell> {
minWidth: 88,
minExtendedWidth: 232,
extended: true,
selectedIndex: _selectedIndex,
selectedIndex: selectedIndex,
onDestinationSelected: (index) =>
setState(() => _selectedIndex = index),
labelType: NavigationRailLabelType.none,
@@ -50,42 +89,39 @@ class _HomeShellState extends ConsumerState<HomeShell> {
padding: EdgeInsets.fromLTRB(18, 18, 18, 10),
child: _BrandHeader(),
),
destinations: [
NavigationRailDestination(
icon: const Icon(Symbols.account_box),
label: Text(l10n.accountTitle)),
NavigationRailDestination(
icon: const Icon(Symbols.call_made),
label: Text(l10n.sendTitle)),
NavigationRailDestination(
icon: const Icon(Symbols.call_received),
label: Text(l10n.receiveTitle)),
NavigationRailDestination(
icon: const Icon(Symbols.chart_data),
label: Text(l10n.stakingTitle)),
NavigationRailDestination(
icon: const Icon(Symbols.memory),
label: Text(l10n.miningTitle)),
NavigationRailDestination(
icon: const Icon(Symbols.list_alt),
label: Text(l10n.transactionsTitle)),
NavigationRailDestination(
icon: const Icon(Symbols.settings),
label: Text(l10n.settingsTitle)),
],
destinations: items
.map(
(item) => NavigationRailDestination(
icon: item.icon,
label: Text(item.label),
),
)
.toList(),
trailing: const Padding(
padding: EdgeInsets.all(12),
child: StatusBar(),
),
),
const VerticalDivider(width: 1),
Expanded(child: screens[_selectedIndex]),
Expanded(child: items[selectedIndex].screen),
],
),
);
}
}
class _NavItem {
const _NavItem({
required this.icon,
required this.label,
required this.screen,
});
final Widget icon;
final String label;
final Widget screen;
}
class _BrandHeader extends StatelessWidget {
const _BrandHeader();
+524 -3
View File
@@ -1,14 +1,535 @@
import 'dart:io';
import 'dart:math' as math;
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:material_symbols_icons/material_symbols_icons.dart';
import '../../app_features.dart';
import '../../domain/models.dart';
import '../../state/providers.dart';
import '../l10n/app_localizations_ext.dart';
import 'placeholder_screen.dart';
class MiningScreen extends StatelessWidget {
class MiningScreen extends ConsumerStatefulWidget {
const MiningScreen({super.key});
@override
ConsumerState<MiningScreen> createState() => _MiningScreenState();
}
class _MiningScreenState extends ConsumerState<MiningScreen> {
late MiningMode _mode;
late int _cpuThreads;
late final TextEditingController _poolHostController;
late final TextEditingController _poolPortController;
late final TextEditingController _apiPortController;
bool _dirty = false;
@override
void initState() {
super.initState();
final config = ref.read(appConfigControllerProvider).miningConfig;
_mode = config.mode;
_cpuThreads = config.cpuThreads;
_poolHostController = TextEditingController(text: config.poolHost);
_poolPortController = TextEditingController(text: config.poolPort.toString());
_apiPortController = TextEditingController(text: config.apiPort.toString());
}
@override
void dispose() {
_poolHostController.dispose();
_poolPortController.dispose();
_apiPortController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
final l10n = context.l10n;
return PlaceholderScreen(title: l10n.miningTitle);
final theme = Theme.of(context);
final config = ref.watch(appConfigControllerProvider);
final walletState = ref.watch(walletControllerProvider);
final maxThreads = math.max(1, math.min(Platform.numberOfProcessors, 64));
final poolHost = _poolHostController.text.trim();
final poolPort = int.tryParse(_poolPortController.text.trim());
final apiPort = int.tryParse(_apiPortController.text.trim());
final canSave = poolHost.isNotEmpty &&
poolPort != null &&
poolPort > 0 &&
apiPort != null &&
apiPort > 0;
return SingleChildScrollView(
padding: const EdgeInsets.all(24),
child: Center(
child: ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 1120),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
l10n.miningTitle,
style: theme.textTheme.headlineMedium?.copyWith(
fontWeight: FontWeight.w700,
),
),
const SizedBox(height: 8),
Text(
l10n.miningScreenSubtitle,
style: theme.textTheme.bodyLarge?.copyWith(
color: theme.colorScheme.onSurfaceVariant,
),
),
const SizedBox(height: 24),
LayoutBuilder(
builder: (context, constraints) {
final wide = constraints.maxWidth >= 920;
return Flex(
direction: wide ? Axis.horizontal : Axis.vertical,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
flex: wide ? 3 : 0,
child: Column(
children: [
_SectionCard(
title: l10n.miningSourceTitle,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
DropdownButtonFormField<MiningMode>(
value: _mode,
decoration: InputDecoration(
labelText: l10n.miningModeLabel,
),
items: [
DropdownMenuItem(
value: MiningMode.solo,
child: Text(l10n.miningModeSolo),
),
DropdownMenuItem(
value: MiningMode.pool,
child: Text(l10n.miningModePool),
),
],
onChanged: (value) {
if (value == null) {
return;
}
setState(() {
_mode = value;
_dirty = true;
});
},
),
const SizedBox(height: 16),
if (_mode == MiningMode.solo) ...[
_InfoTile(
label: l10n.miningTargetLabel,
value: l10n.miningSoloTargetValue,
icon: Symbols.lan,
),
const SizedBox(height: 12),
Text(
config.nodeConfig.mode == NodeMode.local
? l10n.miningSoloHint
: l10n.miningSoloNeedsLocalNode,
style: theme.textTheme.bodyMedium?.copyWith(
color: config.nodeConfig.mode == NodeMode.local
? theme.colorScheme.onSurfaceVariant
: theme.colorScheme.error,
),
),
] else ...[
TextFormField(
controller: _poolHostController,
decoration: InputDecoration(
labelText: l10n.hostLabel,
),
onChanged: (_) => setState(() => _dirty = true),
),
const SizedBox(height: 16),
TextFormField(
controller: _poolPortController,
keyboardType: TextInputType.number,
decoration: InputDecoration(
labelText: l10n.portLabel,
),
onChanged: (_) => setState(() => _dirty = true),
),
const SizedBox(height: 12),
Text(
l10n.miningPoolHint,
style: theme.textTheme.bodyMedium?.copyWith(
color: theme.colorScheme.onSurfaceVariant,
),
),
],
const SizedBox(height: 20),
DropdownButtonFormField<int>(
value: _cpuThreads.clamp(1, maxThreads),
decoration: InputDecoration(
labelText: l10n.miningThreadsLabel,
),
items: [
for (var value = 1; value <= maxThreads; value++)
DropdownMenuItem(
value: value,
child: Text(value.toString()),
),
],
onChanged: (value) {
if (value == null) {
return;
}
setState(() {
_cpuThreads = value;
_dirty = true;
});
},
),
const SizedBox(height: 16),
TextFormField(
controller: _apiPortController,
keyboardType: TextInputType.number,
decoration: InputDecoration(
labelText: l10n.miningApiPortLabel,
),
onChanged: (_) => setState(() => _dirty = true),
),
const SizedBox(height: 16),
Row(
children: [
FilledButton.icon(
onPressed: canSave ? _saveConfig : null,
icon: const Icon(Symbols.save),
label: Text(l10n.saveAction),
),
const SizedBox(width: 12),
OutlinedButton.icon(
onPressed: _dirty ? _resetDraft : null,
icon: const Icon(Symbols.undo),
label: Text(l10n.miningResetDraftAction),
),
],
),
],
),
),
const SizedBox(height: 16),
_SectionCard(
title: l10n.miningControlsTitle,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Wrap(
spacing: 12,
runSpacing: 12,
children: [
FilledButton.icon(
onPressed: null,
icon: const Icon(Symbols.play_arrow),
label: Text(l10n.miningStartAction),
),
OutlinedButton.icon(
onPressed: null,
icon: const Icon(Symbols.stop),
label: Text(l10n.miningStopAction),
),
OutlinedButton.icon(
onPressed: null,
icon: const Icon(Symbols.refresh),
label: Text(l10n.localNodeRestartAction),
),
],
),
const SizedBox(height: 12),
Text(
l10n.miningBackendPending,
style: theme.textTheme.bodyMedium?.copyWith(
color: theme.colorScheme.onSurfaceVariant,
),
),
],
),
),
],
),
),
SizedBox(width: wide ? 16 : 0, height: wide ? 0 : 16),
Expanded(
flex: wide ? 2 : 0,
child: Column(
children: [
_SectionCard(
title: l10n.miningStatsTitle,
child: Wrap(
spacing: 12,
runSpacing: 12,
children: [
_StatTile(
label: l10n.transactionStatusLabel,
value: l10n.comingSoon,
),
_StatTile(
label: l10n.miningHashrate10sLabel,
value: l10n.miningDataUnknownValue,
),
_StatTile(
label: l10n.miningHashrate1mLabel,
value: l10n.miningDataUnknownValue,
),
_StatTile(
label: l10n.miningLabelHashrate15m,
value: l10n.miningDataUnknownValue,
),
_StatTile(
label: l10n.miningJobsLabel,
value: l10n.miningDataUnknownValue,
),
_StatTile(
label: l10n.miningAcceptedSharesLabel,
value: l10n.miningDataUnknownValue,
),
_StatTile(
label: l10n.miningRejectedSharesLabel,
value: l10n.miningDataUnknownValue,
),
_StatTile(
label: l10n.miningLabelUptime,
value: l10n.miningDataUnknownValue,
),
],
),
),
const SizedBox(height: 16),
_SectionCard(
title: l10n.miningCurrentConfigTitle,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_InfoTile(
label: l10n.miningWalletAddressLabel,
value: walletState.walletInfo?.address.isNotEmpty == true
? walletState.walletInfo!.address
: l10n.miningNoWalletAddress,
icon: Symbols.account_balance_wallet,
),
const SizedBox(height: 12),
_InfoTile(
label: l10n.miningModeLabel,
value: config.miningConfig.mode == MiningMode.solo
? l10n.miningModeSolo
: '${config.miningConfig.poolHost}:${config.miningConfig.poolPort}',
icon: config.miningConfig.mode == MiningMode.solo
? Symbols.lan
: Symbols.hub,
),
const SizedBox(height: 12),
_InfoTile(
label: l10n.miningThreadsLabel,
value: config.miningConfig.cpuThreads.toString(),
icon: Symbols.memory,
),
const SizedBox(height: 12),
_InfoTile(
label: l10n.miningApiPortLabel,
value: config.miningConfig.apiPort.toString(),
icon: Symbols.settings_ethernet,
),
],
),
),
const SizedBox(height: 16),
_SectionCard(
title: l10n.miningBundledTitle,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
AppFeatures.isMiningFlavor
? l10n.miningBundledEnabled
: l10n.miningBundledDisabled,
style: theme.textTheme.bodyMedium?.copyWith(
color: theme.colorScheme.onSurfaceVariant,
),
),
const SizedBox(height: 12),
Text(
l10n.miningBundledBody,
style: theme.textTheme.bodySmall?.copyWith(
color: theme.colorScheme.onSurfaceVariant,
),
),
],
),
),
],
),
),
],
);
},
),
],
),
),
),
);
}
void _resetDraft() {
final config = ref.read(appConfigControllerProvider).miningConfig;
setState(() {
_mode = config.mode;
_cpuThreads = config.cpuThreads;
_poolHostController.text = config.poolHost;
_poolPortController.text = config.poolPort.toString();
_apiPortController.text = config.apiPort.toString();
_dirty = false;
});
}
Future<void> _saveConfig() async {
final l10n = context.l10n;
final port = int.tryParse(_poolPortController.text.trim());
final apiPort = int.tryParse(_apiPortController.text.trim());
if (_poolHostController.text.trim().isEmpty ||
port == null ||
port <= 0 ||
apiPort == null ||
apiPort <= 0) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(l10n.miningConfigInvalid)),
);
return;
}
final next = MiningConfig(
mode: _mode,
cpuThreads: _cpuThreads,
poolHost: _poolHostController.text.trim(),
poolPort: port,
apiPort: apiPort,
);
await ref.read(appConfigControllerProvider.notifier).setMiningConfig(next);
if (!mounted) {
return;
}
setState(() => _dirty = false);
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(l10n.miningSettingsSaved)),
);
}
}
class _SectionCard extends StatelessWidget {
const _SectionCard({required this.title, required this.child});
final String title;
final Widget child;
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
return Card(
child: Padding(
padding: const EdgeInsets.all(20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
title,
style: theme.textTheme.titleLarge?.copyWith(
fontWeight: FontWeight.w700,
),
),
const SizedBox(height: 16),
child,
],
),
),
);
}
}
class _StatTile extends StatelessWidget {
const _StatTile({required this.label, required this.value});
final String label;
final String value;
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
return Container(
width: 180,
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: theme.colorScheme.surfaceContainerHighest.withValues(alpha: 0.65),
borderRadius: BorderRadius.circular(18),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
label,
style: theme.textTheme.bodySmall?.copyWith(
color: theme.colorScheme.onSurfaceVariant,
),
),
const SizedBox(height: 8),
Text(
value,
style: theme.textTheme.titleLarge?.copyWith(
fontWeight: FontWeight.w700,
),
),
],
),
);
}
}
class _InfoTile extends StatelessWidget {
const _InfoTile({
required this.label,
required this.value,
required this.icon,
});
final String label;
final String value;
final IconData icon;
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
return Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Icon(icon, size: 20, color: theme.colorScheme.primary),
const SizedBox(width: 12),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
label,
style: theme.textTheme.bodySmall?.copyWith(
color: theme.colorScheme.onSurfaceVariant,
),
),
const SizedBox(height: 2),
SelectableText(
value,
style: theme.textTheme.bodyLarge,
),
],
),
),
],
);
}
}
+49 -4
View File
@@ -117,7 +117,14 @@ def extract_member_from_zip(url: str, member_name: str, destination: Path, token
write_bytes(destination, archive.read(member), executable=True)
def stage_linux(base_url: str, monero_c_tag: str, peya_tag: str, token: str | None, root: Path) -> None:
def stage_linux(
base_url: str,
monero_c_tag: str,
peya_tag: str,
xmrig_tag: str | None,
token: str | None,
root: Path,
) -> None:
log("Staging Linux runtime")
monero_release = release_metadata(base_url, "tiamak/monero_c", monero_c_tag, token)
peya_release = release_metadata(base_url, "tiamak/Peya", peya_tag, token)
@@ -135,10 +142,25 @@ def stage_linux(base_url: str, monero_c_tag: str, peya_tag: str, token: str | No
peya_url = asset_download_url(base_url, peya_release, peya_asset, token)
extract_member_from_tar(peya_url, "peyad", daemon_dir / "peyad", token)
if xmrig_tag:
miner_dir = root / "external" / "miner"
ensure_clean_dir(miner_dir)
xmrig_release = release_metadata(base_url, "tiamak/xmrig", xmrig_tag, token)
xmrig_asset = f"xmrig-peya-{xmrig_release['tag_name']}-linux-x86_64.tar.gz"
xmrig_url = asset_download_url(base_url, xmrig_release, xmrig_asset, token)
extract_member_from_tar(xmrig_url, "xmrig", miner_dir / "xmrig", token)
print(f"Staged Linux runtime from monero_c {monero_release['tag_name']} and Peya {peya_release['tag_name']}")
def stage_windows(base_url: str, monero_c_tag: str, peya_tag: str, token: str | None, root: Path) -> None:
def stage_windows(
base_url: str,
monero_c_tag: str,
peya_tag: str,
xmrig_tag: str | None,
token: str | None,
root: Path,
) -> None:
log("Staging Windows runtime")
monero_release = release_metadata(base_url, "tiamak/monero_c", monero_c_tag, token)
peya_release = release_metadata(base_url, "tiamak/Peya", peya_tag, token)
@@ -161,6 +183,14 @@ def stage_windows(base_url: str, monero_c_tag: str, peya_tag: str, token: str |
peya_url = asset_download_url(base_url, peya_release, peya_asset, token)
extract_member_from_zip(peya_url, "peyad.exe", daemon_dir / "peyad.exe", token)
if xmrig_tag:
miner_dir = root / "external" / "miner"
ensure_clean_dir(miner_dir)
xmrig_release = release_metadata(base_url, "tiamak/xmrig", xmrig_tag, token)
xmrig_asset = f"xmrig-peya-{xmrig_release['tag_name']}-windows-x86_64.zip"
xmrig_url = asset_download_url(base_url, xmrig_release, xmrig_asset, token)
extract_member_from_zip(xmrig_url, "xmrig.exe", miner_dir / "xmrig.exe", token)
print(f"Staged Windows runtime from monero_c {monero_release['tag_name']} and Peya {peya_release['tag_name']}")
@@ -169,6 +199,7 @@ def main() -> int:
parser.add_argument("--platform", choices=("linux", "windows"), required=True)
parser.add_argument("--monero-c-tag", default="latest")
parser.add_argument("--peya-tag", default="latest")
parser.add_argument("--xmrig-tag")
parser.add_argument("--gitea-base-url", default=os.environ.get("GITEA_BASE_URL", DEFAULT_GITEA_BASE))
parser.add_argument("--repo-root", default=".")
args = parser.parse_args()
@@ -178,9 +209,23 @@ def main() -> int:
try:
if args.platform == "linux":
stage_linux(args.gitea_base_url, args.monero_c_tag, args.peya_tag, token, root)
stage_linux(
args.gitea_base_url,
args.monero_c_tag,
args.peya_tag,
args.xmrig_tag,
token,
root,
)
else:
stage_windows(args.gitea_base_url, args.monero_c_tag, args.peya_tag, token, root)
stage_windows(
args.gitea_base_url,
args.monero_c_tag,
args.peya_tag,
args.xmrig_tag,
token,
root,
)
except Exception as exc:
log(f"stage_release_runtime.py failed: {exc}")
raise