mirror of
https://github.com/Such-Software/hash-wallet.git
synced 2026-10-17 05:41:29 +02:00
fix: wownero P0s, fail-closed RNG, iOS scheme, dep pins
- resetToDefault omitted Wownero: the reset button null-crashed and left WOW wallets with an empty node list - accountLabel was missing a return and rendered blank for WOW wallets - sec_random now throws instead of returning empty bytes when the native entropy channel fails or under-delivers - iOS builds no longer register the leftover cakewallet:// URL scheme - WOW fee estimate now fetched from the connected daemon's get_fee_estimate RPC and cached; the inherited XMR constant table remains only as a pre-fetch fallback - pin cake_backup, flutter_local_authentication, and bech32 git deps to their locked SHAs for reproducible builds
This commit is contained in:
@@ -14,8 +14,14 @@ Future<Uint8List> secRandom(int count) async {
|
||||
final rng = Random.secure();
|
||||
return Uint8List.fromList(List<int>.generate(count, (_) => rng.nextInt(byteSize)));
|
||||
}
|
||||
return await utils.invokeMethod<Uint8List>('sec_random', {'count': count}) ?? Uint8List.fromList([]);
|
||||
} on PlatformException catch (_) {
|
||||
return Uint8List.fromList([]);
|
||||
final bytes = await utils.invokeMethod<Uint8List>('sec_random', {'count': count});
|
||||
if (bytes == null || bytes.length != count) {
|
||||
throw StateError('sec_random returned ${bytes?.length ?? 0} bytes, expected $count');
|
||||
}
|
||||
return bytes;
|
||||
} on PlatformException catch (e) {
|
||||
// Never fail open: an entropy source that cannot deliver must throw,
|
||||
// not hand back an empty buffer for key material.
|
||||
throw StateError('sec_random platform call failed: ${e.message}');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:ffi';
|
||||
import 'dart:io';
|
||||
import 'dart:isolate';
|
||||
@@ -223,12 +224,38 @@ abstract class WowneroWalletBase
|
||||
|
||||
wownero_wallet.setTrustedDaemon(node.trusted);
|
||||
syncStatus = ConnectedSyncStatus();
|
||||
unawaited(_updateBaseFeeEstimate(node));
|
||||
} catch (e) {
|
||||
syncStatus = FailedSyncStatus();
|
||||
printV(e);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _updateBaseFeeEstimate(Node node) async {
|
||||
try {
|
||||
final rpcUri = node.isSSL
|
||||
? Uri.https(node.uri.authority, '/json_rpc')
|
||||
: Uri.http(node.uri.authority, '/json_rpc');
|
||||
final client = ProxyWrapper().getHttpIOClient();
|
||||
final response = await client
|
||||
.post(rpcUri,
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: json.encode({'jsonrpc': '2.0', 'id': '0', 'method': 'get_fee_estimate'}))
|
||||
.timeout(const Duration(seconds: 15));
|
||||
|
||||
if (response.statusCode != 200) return;
|
||||
|
||||
final result =
|
||||
(json.decode(response.body) as Map<String, dynamic>)['result'] as Map<String, dynamic>?;
|
||||
final feePerByte = result?['fee'] as int?;
|
||||
if (feePerByte != null && feePerByte > 0) {
|
||||
_cachedBaseFeePerByte = feePerByte;
|
||||
}
|
||||
} catch (e) {
|
||||
printV('get_fee_estimate failed, keeping fallback fee table: $e');
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> startSync() async {
|
||||
try {
|
||||
@@ -352,11 +379,26 @@ abstract class WowneroWalletBase
|
||||
return PendingWowneroTransaction(pendingTransactionDescription);
|
||||
}
|
||||
|
||||
// Base fee per byte in atomic units, fetched from the connected daemon's
|
||||
// get_fee_estimate RPC. Null until the first successful fetch.
|
||||
int? _cachedBaseFeePerByte;
|
||||
|
||||
// Typical 2-in/2-out ring-22 transaction weight. Only used for the
|
||||
// pre-confirmation estimate; the real fee comes from wallet2 when the
|
||||
// transaction is built.
|
||||
static const _estimatedTxWeightBytes = 2300;
|
||||
|
||||
@override
|
||||
int calculateEstimatedFee(TransactionPriority priority, int? amount) {
|
||||
// FIXME: hardcoded value;
|
||||
|
||||
if (priority is MoneroTransactionPriority) {
|
||||
final baseFeePerByte = _cachedBaseFeePerByte;
|
||||
if (baseFeePerByte != null) {
|
||||
return baseFeePerByte * _estimatedTxWeightBytes * _feeMultiplier(priority);
|
||||
}
|
||||
|
||||
// Fallback while no daemon estimate is available yet. Inherited from
|
||||
// upstream and calibrated for XMR, not WOW — kept only so the send
|
||||
// screen shows something before get_fee_estimate returns.
|
||||
switch (priority) {
|
||||
case MoneroTransactionPriority.slow:
|
||||
return 24590000;
|
||||
@@ -374,6 +416,23 @@ abstract class WowneroWalletBase
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _feeMultiplier(MoneroTransactionPriority priority) {
|
||||
switch (priority) {
|
||||
case MoneroTransactionPriority.slow:
|
||||
return 1;
|
||||
case MoneroTransactionPriority.automatic:
|
||||
return 5;
|
||||
case MoneroTransactionPriority.medium:
|
||||
return 10;
|
||||
case MoneroTransactionPriority.fast:
|
||||
return 25;
|
||||
case MoneroTransactionPriority.fastest:
|
||||
return 1000;
|
||||
default:
|
||||
return 5;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> save() async {
|
||||
await walletAddresses.updateUsedSubaddress();
|
||||
|
||||
@@ -38,10 +38,6 @@
|
||||
<string>hashbags</string>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Editor</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Editor</string>
|
||||
|
||||
@@ -82,6 +82,7 @@ Future<List<Node>> loadDefaultNanoPowNodes() async {
|
||||
}
|
||||
|
||||
Future<void> resetToDefault(Box<Node> nodeSource) async {
|
||||
final wowneroNodes = await loadDefaultNodes(WalletType.wownero);
|
||||
final moneroNodes = await loadDefaultNodes(WalletType.monero);
|
||||
final bitcoinElectrumServerList = await loadDefaultNodes(WalletType.bitcoin);
|
||||
final litecoinElectrumServerList = await loadDefaultNodes(WalletType.litecoin);
|
||||
@@ -94,7 +95,8 @@ Future<void> resetToDefault(Box<Node> nodeSource) async {
|
||||
final arbitrumNodes = await loadDefaultNodes(WalletType.arbitrum);
|
||||
final bscNodes = await loadDefaultNodes(WalletType.bsc);
|
||||
|
||||
final nodes = moneroNodes +
|
||||
final nodes = wowneroNodes +
|
||||
moneroNodes +
|
||||
bitcoinElectrumServerList +
|
||||
litecoinElectrumServerList +
|
||||
ethereumNodes +
|
||||
|
||||
@@ -389,7 +389,7 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo
|
||||
case WalletType.monero:
|
||||
return monero!.getCurrentAccount(wallet).label;
|
||||
case WalletType.wownero:
|
||||
wownero!.getCurrentAccount(wallet).label;
|
||||
return wownero!.getCurrentAccount(wallet).label;
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
|
||||
+3
-1
@@ -38,6 +38,7 @@ dependencies:
|
||||
flutter_local_authentication:
|
||||
git:
|
||||
url: https://github.com/cake-tech/flutter_local_authentication
|
||||
ref: 75c8681ebef62398a87c8ae0cccb7cfddffa9734
|
||||
package_info_plus: ^8.0.1
|
||||
devicelocale: 0.8.1
|
||||
auto_size_text: ^3.0.0
|
||||
@@ -82,7 +83,7 @@ dependencies:
|
||||
cake_backup:
|
||||
git:
|
||||
url: https://github.com/cake-tech/cake_backup.git
|
||||
ref: main
|
||||
ref: 3aba867dcab6737f6707782f5db15d71f303db38
|
||||
version: 1.0.0
|
||||
flutter_plugin_android_lifecycle: 2.0.23
|
||||
path_provider_android: ^2.2.1
|
||||
@@ -190,6 +191,7 @@ dependency_overrides:
|
||||
bech32:
|
||||
git:
|
||||
url: https://github.com/cake-tech/bech32.git
|
||||
ref: 05755063b593aa6cca0a4820a318e0ce17de6192
|
||||
web3dart:
|
||||
git:
|
||||
url: https://github.com/cake-tech/web3dart.git
|
||||
|
||||
@@ -18,9 +18,6 @@ cp -rf ./ios/Runner/InfoBase.plist ./ios/Runner/Info.plist
|
||||
/usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString ${APP_IOS_VERSION}" ./ios/Runner/Info.plist
|
||||
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion ${APP_IOS_BUILD_NUMBER}" ./ios/Runner/Info.plist
|
||||
|
||||
/usr/libexec/PlistBuddy -c "Add :CFBundleURLTypes:1:CFBundleURLName string ${APP_IOS_TYPE}" ./ios/Runner/Info.plist
|
||||
/usr/libexec/PlistBuddy -c "Add :CFBundleURLTypes:1:CFBundleURLSchemes array" ./ios/Runner/Info.plist
|
||||
/usr/libexec/PlistBuddy -c "Add :CFBundleURLTypes:1:CFBundleURLSchemes: string ${APP_IOS_TYPE}" ./ios/Runner/Info.plist
|
||||
universal_sed "s/PRODUCT_BUNDLE_IDENTIFIER = .*;/PRODUCT_BUNDLE_IDENTIFIER = $APP_IOS_BUNDLE_ID;/g" ./ios/Runner.xcodeproj/project.pbxproj
|
||||
|
||||
CONFIG_ARGS=""
|
||||
|
||||
Reference in New Issue
Block a user