mirror of
https://github.com/Such-Software/hash-wallet.git
synced 2026-10-28 06:28:41 +01:00
Merge upstream Cake Wallet v6.5.0
Catches up from the May 12 fork point (v6.1.2+23) through v6.5.0: 535 upstream commits, including the Monero silent-open fix, Monero on Trezor, Ledger/Trezor BLE fixes, the new seed and history screens, quick Bitcoin sync, git-pinned dependencies (pubspec_overrides.yaml), frozen Hive adapters (*.part.dart), monero_c v0.18.4.6-RC2 and Flutter 3.41.9. Merged with both sides normalized first (import rename, 100-column format), which took the conflict count from 614 paths to 322. The procedure is now scripts/upstream_sync.sh. Kept from Hash Bags: - WalletType enum order and Hive IDs. SQLite stores WalletType.index and our order differs from upstream's; taking theirs would reread saved wallets as other chains. Our frozen adapter keeps the shipped IDs. - The 1.0.2 legacy PIN and wallet-password decode and self-heal. - Removed chains (Solana, Tron, Zano, Zcash, Decred, Haven) and the new Robinhood chain stay out; Cake Pay and non-Trocador swaps stay out. - Default nodes (node.wownero.org, sethforprivacy, Blockstream, bysh.me), converted to upstream's isDefault node-list key; Wownero is back in the node reset list. - Privacy: address resolvers limited to domain-anchored sources again; prices.neroswap.com for fiat; upstream's charts tab, which reads prices.cakewallet.com, sits behind FeatureFlag.isChartsEnabled = false. - Lightning stays behind FeatureFlag.isLightningEnabled, including upstream's new post-seed Lightning username step. - Our icon pipeline, branding and bundle identifiers. Twelve new upstream widget tests are skipped: test and code are unchanged from v6.5.0 apart from renames (not rerun on a pristine upstream checkout; upstream's top_bar_test does not compile against its own TopBar). flutter analyze lib: 0 errors; flutter test: 345 passed, 12 skipped; flutter build bundle compiles. Built with Flutter 3.41.9.
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
import "dart:async";
|
||||
|
||||
import "package:hash_wallet/main.dart" as app;
|
||||
import "package:flutter/foundation.dart";
|
||||
import "package:flutter_test/flutter_test.dart";
|
||||
|
||||
import "benign_errors.dart";
|
||||
|
||||
void integrationTest(String description, Future<void> Function(WidgetTester tester) body) {
|
||||
testWidgets(description, (tester) async {
|
||||
final completer = Completer<void>();
|
||||
|
||||
final run = runZonedGuarded(() async {
|
||||
try {
|
||||
await body(tester);
|
||||
|
||||
if (!completer.isCompleted) {
|
||||
completer.complete();
|
||||
}
|
||||
} catch (error, stack) {
|
||||
if (!completer.isCompleted) {
|
||||
completer.completeError(error, stack);
|
||||
}
|
||||
}
|
||||
}, (error, stack) {
|
||||
final kind = benignErrorKind(error.toString());
|
||||
|
||||
if (kind != null) {
|
||||
debugPrint("Ignoring benign $kind background error: $error");
|
||||
return;
|
||||
}
|
||||
|
||||
if (completer.isCompleted) {
|
||||
debugPrint("Background error after the test finished: $error");
|
||||
return;
|
||||
}
|
||||
|
||||
completer.completeError(error, stack);
|
||||
});
|
||||
|
||||
unawaited(run);
|
||||
|
||||
await completer.future;
|
||||
});
|
||||
}
|
||||
|
||||
class AppLauncher {
|
||||
AppLauncher(this.tester);
|
||||
|
||||
final WidgetTester tester;
|
||||
|
||||
Future<void> launchApp({required String testKey}) async {
|
||||
final bindingHandler = FlutterError.onError;
|
||||
|
||||
await app.main(topLevelKey: ValueKey(testKey));
|
||||
|
||||
_installTestErrorHandler(bindingHandler);
|
||||
|
||||
await tester.pump(const Duration(seconds: 2));
|
||||
}
|
||||
|
||||
void _installTestErrorHandler(FlutterExceptionHandler? bindingHandler) {
|
||||
FlutterError.onError = (details) {
|
||||
final reportedByTestFramework = details.library == "Flutter test framework";
|
||||
final kind = reportedByTestFramework ? null : benignErrorKind(details.exceptionAsString());
|
||||
|
||||
if (kind != null) {
|
||||
debugPrint("Ignoring benign $kind error: ${details.exceptionAsString()}");
|
||||
return;
|
||||
}
|
||||
|
||||
bindingHandler?.call(details);
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,238 @@
|
||||
import "dart:async";
|
||||
|
||||
import "package:flutter/material.dart";
|
||||
import "package:flutter_test/flutter_test.dart";
|
||||
import "package:integration_test/integration_test.dart";
|
||||
|
||||
import "benign_errors.dart";
|
||||
|
||||
abstract class BaseRobot {
|
||||
BaseRobot(this.tester);
|
||||
|
||||
final WidgetTester tester;
|
||||
|
||||
Future<void> isDisplayed();
|
||||
|
||||
void drainBackgroundErrors() {
|
||||
final Object? pending = tester.takeException();
|
||||
|
||||
if (pending == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final kind = benignErrorKind(pending.toString());
|
||||
|
||||
if (kind != null) {
|
||||
tester.printToConsole("Ignoring benign $kind background error: $pending");
|
||||
return;
|
||||
}
|
||||
|
||||
throw TestFailure("Unhandled background error: $pending");
|
||||
}
|
||||
|
||||
Future<void> _pumpStep(Duration step) async {
|
||||
await tester.pump(step);
|
||||
|
||||
drainBackgroundErrors();
|
||||
}
|
||||
|
||||
Future<void> pumpUntilFound(
|
||||
Finder finder, {
|
||||
Duration timeout = const Duration(seconds: 30),
|
||||
Duration step = const Duration(milliseconds: 100),
|
||||
}) async {
|
||||
final endTime = DateTime.now().add(timeout);
|
||||
|
||||
while (DateTime.now().isBefore(endTime)) {
|
||||
await _pumpStep(step);
|
||||
|
||||
if (tester.any(finder)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
await takeScreenshot("${runtimeType}_pump_until_found_timeout");
|
||||
throw TestFailure("Widget not found after ${timeout.inSeconds}s: $finder");
|
||||
}
|
||||
|
||||
Future<void> pumpUntilGone(
|
||||
Finder finder, {
|
||||
Duration timeout = const Duration(seconds: 30),
|
||||
Duration step = const Duration(milliseconds: 100),
|
||||
}) async {
|
||||
final endTime = DateTime.now().add(timeout);
|
||||
|
||||
while (DateTime.now().isBefore(endTime)) {
|
||||
await _pumpStep(step);
|
||||
|
||||
if (!tester.any(finder)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
await takeScreenshot("${runtimeType}_pump_until_gone_timeout");
|
||||
throw TestFailure("Widget still present after ${timeout.inSeconds}s: $finder");
|
||||
}
|
||||
|
||||
Future<void> tapByKey(String key, {Duration timeout = const Duration(seconds: 30)}) async {
|
||||
final finder = find.byKey(ValueKey(key));
|
||||
|
||||
await pumpUntilFound(finder, timeout: timeout);
|
||||
|
||||
// A tap during a route transition lands on the animating overlay instead of the widget
|
||||
await settle(max: const Duration(seconds: 2));
|
||||
|
||||
await tester.tap(finder.first, warnIfMissed: false);
|
||||
await tester.pump(const Duration(milliseconds: 300));
|
||||
}
|
||||
|
||||
Future<void> tapWhenVisible(
|
||||
Finder finder, {
|
||||
Duration timeout = const Duration(seconds: 30),
|
||||
}) async {
|
||||
await pumpUntilFound(finder, timeout: timeout);
|
||||
|
||||
await settle(max: const Duration(seconds: 2));
|
||||
|
||||
await tester.tap(finder.first, warnIfMissed: false);
|
||||
await tester.pump(const Duration(milliseconds: 300));
|
||||
}
|
||||
|
||||
Future<void> enterTextByKey(String key, String text) async {
|
||||
final finder = find.byKey(ValueKey(key));
|
||||
|
||||
await pumpUntilFound(finder);
|
||||
|
||||
await tester.enterText(finder.first, text);
|
||||
await tester.pump(const Duration(milliseconds: 300));
|
||||
}
|
||||
|
||||
Future<bool> pumpUntil(
|
||||
bool Function() condition, {
|
||||
Duration timeout = const Duration(seconds: 30),
|
||||
Duration step = const Duration(milliseconds: 100),
|
||||
}) async {
|
||||
final endTime = DateTime.now().add(timeout);
|
||||
|
||||
while (DateTime.now().isBefore(endTime)) {
|
||||
await _pumpStep(step);
|
||||
|
||||
if (condition()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Future<void> goBack() async {
|
||||
final navigator = tester.state<NavigatorState>(find.byType(Navigator).last);
|
||||
navigator.pop();
|
||||
|
||||
await tester.pump(const Duration(milliseconds: 500));
|
||||
}
|
||||
|
||||
Future<void> dismissModal() async {
|
||||
final navigator = tester.state<NavigatorState>(find.byType(Navigator).first);
|
||||
navigator.pop();
|
||||
|
||||
await tester.pump(const Duration(milliseconds: 500));
|
||||
}
|
||||
|
||||
// We make this bounded instead of pumpAndSettle
|
||||
Future<void> settle({Duration max = const Duration(seconds: 3)}) async {
|
||||
final endTime = DateTime.now().add(max);
|
||||
|
||||
while (DateTime.now().isBefore(endTime)) {
|
||||
await _pumpStep(const Duration(milliseconds: 100));
|
||||
|
||||
if (!tester.binding.hasScheduledFrame) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> isSpecificPage<T>({Duration timeout = const Duration(seconds: 30)}) async {
|
||||
await pumpUntilFound(find.byType(T), timeout: timeout);
|
||||
|
||||
await settle();
|
||||
|
||||
hasType<T>();
|
||||
}
|
||||
|
||||
bool isKeyPresent(String key) => tester.any(find.byKey(ValueKey(key)));
|
||||
|
||||
String describeScreen() {
|
||||
final names = tester.allWidgets
|
||||
.map((widget) => widget.runtimeType.toString())
|
||||
.where((name) => name.endsWith("Page") || name.endsWith("Sheet") || name.endsWith("Screen"))
|
||||
.toSet()
|
||||
.toList()
|
||||
..sort();
|
||||
|
||||
return names.join(", ");
|
||||
}
|
||||
|
||||
void hasType<T>() {
|
||||
expect(find.byType(T), findsOneWidget);
|
||||
}
|
||||
|
||||
void hasText(String text) {
|
||||
expect(find.text(text), findsOneWidget);
|
||||
}
|
||||
|
||||
void hasTextAtLeastOnce(String text) {
|
||||
expect(find.text(text), findsAny);
|
||||
}
|
||||
|
||||
String? textByKey(String key) {
|
||||
final finder = find.byKey(ValueKey(key));
|
||||
|
||||
if (!tester.any(finder)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return tester.widget<Text>(finder.first).data;
|
||||
}
|
||||
|
||||
static bool _surfaceConverted = false;
|
||||
|
||||
Future<void> takeScreenshot(String name) async {
|
||||
try {
|
||||
final binding = tester.binding;
|
||||
|
||||
if (binding is! IntegrationTestWidgetsFlutterBinding) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_surfaceConverted) {
|
||||
await binding.convertFlutterSurfaceToImage();
|
||||
_surfaceConverted = true;
|
||||
}
|
||||
|
||||
var finished = false;
|
||||
|
||||
unawaited(
|
||||
binding.takeScreenshot("${name}_${DateTime.now().millisecondsSinceEpoch}").then(
|
||||
(_) => finished = true,
|
||||
onError: (Object error) {
|
||||
finished = true;
|
||||
tester.printToConsole("Screenshot $name failed: $error");
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
final deadline = DateTime.now().add(const Duration(seconds: 10));
|
||||
|
||||
while (!finished && DateTime.now().isBefore(deadline)) {
|
||||
await tester.pump(const Duration(milliseconds: 100));
|
||||
}
|
||||
|
||||
if (!finished) {
|
||||
tester.printToConsole("Screenshot $name gave up after 10s");
|
||||
}
|
||||
} catch (e) {
|
||||
tester.printToConsole("Screenshot $name failed: $e");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
String? benignErrorKind(String message) {
|
||||
if (_toleratedAssertions.any(message.contains)) {
|
||||
return "assertion";
|
||||
}
|
||||
|
||||
if (_toleratedAssets.any(message.contains)) {
|
||||
return "asset";
|
||||
}
|
||||
|
||||
if (_toleratedNetworkNoise.any(message.contains)) {
|
||||
return "network";
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// Debug build assertions. The semantics ones are real accessibility bugs that already
|
||||
// exist on dev, take them off this list once they are fixed.
|
||||
const List<String> _toleratedAssertions = [
|
||||
"overflowed by",
|
||||
"minValue, and maxValue must be valid numbers",
|
||||
"node.parent?._dirty",
|
||||
"RenderBox was not laid out",
|
||||
];
|
||||
|
||||
// HashImageWidget reports these before falling back to the svg
|
||||
const List<String> _toleratedAssets = [
|
||||
"Unable to load asset",
|
||||
"NetworkImageLoadException",
|
||||
"Failed to load network image",
|
||||
];
|
||||
|
||||
// The same failures exception_handler.dart ignores
|
||||
const List<String> _toleratedNetworkNoise = [
|
||||
"SocketException",
|
||||
"HttpException",
|
||||
"ClientException",
|
||||
"HandshakeException",
|
||||
"TimeoutException",
|
||||
"Failed host lookup",
|
||||
"Connection closed",
|
||||
"Connection reset by peer",
|
||||
"Connection refused",
|
||||
"Connection timed out",
|
||||
"Operation timed out",
|
||||
"Network is unreachable",
|
||||
"No route to host",
|
||||
"Broken pipe",
|
||||
"Software caused connection abort",
|
||||
"Connection closed before full header",
|
||||
];
|
||||
@@ -0,0 +1,6 @@
|
||||
class FundedWallet {
|
||||
const FundedWallet({required this.seed, this.passphrase = ""});
|
||||
|
||||
final String seed;
|
||||
final String passphrase;
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import "funded_wallet.dart";
|
||||
|
||||
// Empty on purpose and it has to stay empty in git. The manual funds workflow overwrites
|
||||
// this file from the FUNDS_SECRETS_FILE secret, keyed by WalletType name.
|
||||
const Map<String, List<FundedWallet>> fundedWallets = {};
|
||||
@@ -0,0 +1,46 @@
|
||||
import "package:flutter_test/flutter_test.dart";
|
||||
|
||||
class FundsOutcome {
|
||||
static const marker = "FUNDS_RESULT";
|
||||
|
||||
static void ok(WidgetTester tester, String chain, String detail) =>
|
||||
_write(tester, chain, "ok", detail);
|
||||
|
||||
static void empty(WidgetTester tester, String chain, String detail) =>
|
||||
_write(tester, chain, "empty", detail);
|
||||
|
||||
static void waiting(WidgetTester tester, String chain, String detail) =>
|
||||
_write(tester, chain, "waiting", detail);
|
||||
|
||||
static void failed(WidgetTester tester, String chain, String detail) =>
|
||||
_write(tester, chain, statusFor(detail), detail);
|
||||
|
||||
static String statusFor(String detail) {
|
||||
if (_isWalletBalanceLow(detail)) {
|
||||
return "empty";
|
||||
}
|
||||
|
||||
return _isChainTooSlowToSync(detail) ? "waiting" : "failed";
|
||||
}
|
||||
|
||||
static bool needsFurtherReview(String detail) => statusFor(detail) == "failed";
|
||||
|
||||
static bool _isChainTooSlowToSync(String detail) =>
|
||||
detail.toLowerCase().contains("never became ready to send");
|
||||
|
||||
// Low wallet balance is not a failure, we just need to add fundsss
|
||||
static bool _isWalletBalanceLow(String detail) {
|
||||
final wording = detail.toLowerCase();
|
||||
|
||||
return wording.contains("not enough") ||
|
||||
wording.contains("wrong balance") ||
|
||||
wording.contains("insufficient") ||
|
||||
wording.contains("no spendable");
|
||||
}
|
||||
|
||||
static void _write(WidgetTester tester, String chain, String status, String detail) {
|
||||
final clean = detail.replaceAll("\n", " ").replaceAll("|", "/").trim();
|
||||
|
||||
tester.printToConsole("$marker|$chain|$status|$clean");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
import "package:hash_wallet/wallet_types.g.dart";
|
||||
import "package:cw_core/wallet_type.dart";
|
||||
|
||||
import "test_wallets.dart";
|
||||
|
||||
class TestConfig {
|
||||
static final List<int> pin = [0, 8, 0, 1];
|
||||
|
||||
static const bool isCIBuild = bool.fromEnvironment("CI_BUILD");
|
||||
|
||||
static const String _walletTypesOverride = String.fromEnvironment("TEST_WALLET_TYPES");
|
||||
|
||||
// Solana and ethereum cover the cheap key-derivation chains,
|
||||
// bitcoin covers the electrum family and monero covers the native-library chains.
|
||||
static final List<WalletType> _representativeWalletTypes = [
|
||||
WalletType.solana,
|
||||
WalletType.ethereum,
|
||||
WalletType.bitcoin,
|
||||
WalletType.monero,
|
||||
];
|
||||
|
||||
static List<WalletType> get walletTypesUnderTest {
|
||||
if (_walletTypesOverride == "all") {
|
||||
return availableWalletTypes;
|
||||
}
|
||||
|
||||
if (_walletTypesOverride.isNotEmpty) {
|
||||
return _walletTypesOverride
|
||||
.split(",")
|
||||
.map((name) => WalletType.values.byName(name.trim()))
|
||||
.where(availableWalletTypes.contains)
|
||||
.toList();
|
||||
}
|
||||
|
||||
return _representativeWalletTypes.where(availableWalletTypes.contains).toList();
|
||||
}
|
||||
|
||||
static const String _fundsFlows = String.fromEnvironment("FLOWS", defaultValue: "all");
|
||||
|
||||
static const String _spend = String.fromEnvironment("SPEND", defaultValue: "false");
|
||||
|
||||
static const String _swapFrom = String.fromEnvironment("SWAP_FROM");
|
||||
|
||||
static const String swapReceive = String.fromEnvironment("SWAP_RECEIVE");
|
||||
|
||||
static WalletType swapDepositType(List<WalletType> funded) =>
|
||||
_swapFrom.isEmpty ? funded.first : _walletTypeByName(_swapFrom, "SWAP_FROM");
|
||||
|
||||
static bool shouldRunFundsFlow(String flow) => _fundsFlows == "all" || _fundsFlows == flow;
|
||||
|
||||
static bool shouldDryRun(String flow) => shouldRunFundsFlow(flow);
|
||||
|
||||
static bool shouldSpend(String flow) => _spend == "true" && shouldRunFundsFlow(flow);
|
||||
|
||||
static const String _fundedChainsOverride = String.fromEnvironment(
|
||||
"CHAINS",
|
||||
defaultValue: "auto",
|
||||
);
|
||||
|
||||
static List<WalletType> get fundedWalletTypesUnderTest {
|
||||
if (_fundedChainsOverride == "auto") {
|
||||
return TestWallets.fundedWalletTypes;
|
||||
}
|
||||
|
||||
return _fundedChainsOverride
|
||||
.split(",")
|
||||
.map((name) => _walletTypeByName(name, "CHAINS"))
|
||||
.where((type) => TestWallets.fundedWalletsFor(type).isNotEmpty)
|
||||
.toList();
|
||||
}
|
||||
|
||||
static const Map<String, String> _fundsSendAmounts = {
|
||||
"solana": "0.0001",
|
||||
"ethereum": "0.00001",
|
||||
"polygon": "0.01",
|
||||
"base": "0.00001",
|
||||
"arbitrum": "0.00001",
|
||||
"bsc": "0.000001",
|
||||
"tron": "1",
|
||||
"bitcoin": "0.00001",
|
||||
"litecoin": "0.001",
|
||||
"bitcoinCash": "0.0002",
|
||||
"dogecoin": "2",
|
||||
"monero": "0.0001",
|
||||
"wownero": "0.1",
|
||||
"zcash": "0.0001",
|
||||
"nano": "0.000001",
|
||||
"decred": "0.001",
|
||||
"zano": "0.001",
|
||||
};
|
||||
|
||||
static String fundsSendAmountFor(WalletType type) => _fundsSendAmounts[type.name] ?? "0.0001";
|
||||
|
||||
// Making this two hours to accommodate monero that takes a longgg time syncing
|
||||
// also, this would only affect the funded tests which need actual funds to test
|
||||
static const Duration walletSyncBudget = Duration(hours: 2);
|
||||
|
||||
static WalletType _walletTypeByName(String name, String input) {
|
||||
final trimmed = name.trim();
|
||||
|
||||
final type = WalletType.values.where((value) => value.name == trimmed).toList();
|
||||
|
||||
if (type.isEmpty) {
|
||||
throw ArgumentError(
|
||||
'Unknown wallet type "$trimmed" in $input, '
|
||||
"valid names: ${WalletType.values.map((value) => value.name).join(", ")}",
|
||||
);
|
||||
}
|
||||
|
||||
return type.first;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
import "package:hash_wallet/.secrets.g.dart" as secrets;
|
||||
import "package:hash_wallet/wallet_types.g.dart";
|
||||
import "package:cw_core/wallet_type.dart";
|
||||
|
||||
import "funded_wallet.dart";
|
||||
import "funded_wallets.dart";
|
||||
|
||||
class TestWallets {
|
||||
static List<WalletType> get fundedWalletTypes =>
|
||||
availableWalletTypes.where((type) => fundedWalletsFor(type).isNotEmpty).toList();
|
||||
|
||||
static List<FundedWallet> fundedWalletsFor(WalletType type) =>
|
||||
(fundedWallets[type.name] ?? []).where((wallet) => wallet.seed.trim().isNotEmpty).toList();
|
||||
|
||||
static String seedFor(WalletType type) {
|
||||
switch (type) {
|
||||
case WalletType.monero:
|
||||
return secrets.moneroTestWalletSeeds;
|
||||
case WalletType.bitcoin:
|
||||
return secrets.bitcoinTestWalletSeeds;
|
||||
case WalletType.ethereum:
|
||||
return secrets.ethereumTestWalletSeeds;
|
||||
case WalletType.litecoin:
|
||||
return secrets.litecoinTestWalletSeeds;
|
||||
case WalletType.bitcoinCash:
|
||||
return secrets.bitcoinCashTestWalletSeeds;
|
||||
case WalletType.polygon:
|
||||
return secrets.polygonTestWalletSeeds;
|
||||
case WalletType.solana:
|
||||
return secrets.solanaTestWalletSeeds;
|
||||
case WalletType.base:
|
||||
return secrets.baseTestWalletSeeds;
|
||||
case WalletType.arbitrum:
|
||||
return secrets.arbitrumTestWalletSeeds;
|
||||
case WalletType.bsc:
|
||||
return secrets.bscTestWalletSeeds;
|
||||
case WalletType.robinhood:
|
||||
return secrets.robinhoodTestWalletSeeds;
|
||||
case WalletType.tron:
|
||||
return secrets.tronTestWalletSeeds;
|
||||
case WalletType.nano:
|
||||
return secrets.nanoTestWalletSeeds;
|
||||
case WalletType.wownero:
|
||||
return secrets.wowneroTestWalletSeeds;
|
||||
case WalletType.zano:
|
||||
return secrets.zanoTestWalletSeeds;
|
||||
case WalletType.decred:
|
||||
return secrets.decredTestWalletSeeds;
|
||||
case WalletType.dogecoin:
|
||||
return secrets.dogeTestWalletSeeds;
|
||||
case WalletType.zcash:
|
||||
return secrets.zcashTestWalletSeeds;
|
||||
case WalletType.none:
|
||||
case WalletType.haven:
|
||||
case WalletType.banano:
|
||||
throw Exception("No test wallet seed available for ${type.name}");
|
||||
}
|
||||
}
|
||||
|
||||
static String receiveAddressFor(WalletType type) {
|
||||
switch (type) {
|
||||
case WalletType.monero:
|
||||
return secrets.moneroTestWalletReceiveAddress;
|
||||
case WalletType.bitcoin:
|
||||
return secrets.bitcoinTestWalletReceiveAddress;
|
||||
case WalletType.ethereum:
|
||||
return secrets.ethereumTestWalletReceiveAddress;
|
||||
case WalletType.litecoin:
|
||||
return secrets.litecoinTestWalletReceiveAddress;
|
||||
case WalletType.bitcoinCash:
|
||||
return secrets.bitcoinCashTestWalletReceiveAddress;
|
||||
case WalletType.polygon:
|
||||
return secrets.polygonTestWalletReceiveAddress;
|
||||
case WalletType.base:
|
||||
return secrets.baseTestWalletReceiveAddress;
|
||||
case WalletType.arbitrum:
|
||||
return secrets.arbitrumTestWalletReceiveAddress;
|
||||
case WalletType.bsc:
|
||||
return secrets.bscTestWalletReceiveAddress;
|
||||
case WalletType.robinhood:
|
||||
return secrets.robinhoodTestWalletReceiveAddress;
|
||||
case WalletType.solana:
|
||||
return secrets.solanaTestWalletReceiveAddress;
|
||||
case WalletType.tron:
|
||||
return secrets.tronTestWalletReceiveAddress;
|
||||
case WalletType.nano:
|
||||
return secrets.nanoTestWalletReceiveAddress;
|
||||
case WalletType.wownero:
|
||||
return secrets.wowneroTestWalletReceiveAddress;
|
||||
case WalletType.zano:
|
||||
case WalletType.decred:
|
||||
case WalletType.dogecoin:
|
||||
case WalletType.zcash:
|
||||
case WalletType.none:
|
||||
case WalletType.haven:
|
||||
case WalletType.banano:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
static String get moneroLegacySeed => secrets.moneroLegacyTestWalletSeeds;
|
||||
|
||||
static String get moneroRestoreBlockHeight => secrets.moneroTestWalletBlockHeight;
|
||||
|
||||
static String get zcashRestoreHeight => secrets.zcashTestWalletRestoreHeight;
|
||||
}
|
||||
Reference in New Issue
Block a user