What changed, and why it matters
This commit adds testnet support for the Salvium cryptocurrency in Stack Wallet. It lets developers or users create and use Salvium wallets on a local test network (localhost) instead of the real main network. There is no obvious security bug in the change itself, but it does add a hardcoded localhost node and changes how wallet network types are selected. The commit does not describe any security issue, and no independent security report is supplied.
No immediate security action is required. Reviewers may optionally verify that the network-type integer (0/1) is correctly constrained before reaching the native layer, and confirm that the localhost default node is only reachable in testnet builds and cannot be confused with mainnet.
Security signals we found
Hardcoded localhost default node for testnet (http://127.0.0.1:29081) with trusted=true and clearnetEnabled=true
New network-type parameter passed to native wallet operations without visible sanitization
Testnet coin added to supported-coins list in app configuration script
Evidence from the diff
The patch extends Salvium (SAL) integration to support CryptoCurrencyNetwork.test. It adds a testnet coin identifier (‘tSAL’), uses network type 1 for testnet in address validation and wallet creation/restoration/loading, and adds a default testnet node pointing to http://127.0.0.1:29081. The interface and generated template are updated to pass an optional network/networkType parameter down to the underlying lib_salvium bindings. No input validation, authentication, or transport security changes are introduced beyond the existing patterns.
Changed components
lib/wallets/crypto_currency/coins/salvium.dartlib/wallets/wallet/impl/salvium_wallet.dartlib/wl_gen/interfaces/cs_salvium_interface.dartscripts/app_config/configure_stack_wallet.shtool/wl_templates/SAL_cs_salvium_interface_impl.template.dartInspect captured patch +44 / −1
diff --git a/lib/wallets/crypto_currency/coins/salvium.dart b/lib/wallets/crypto_currency/coins/salvium.dart
index 931208c..ab0f1b5 100644
--- a/lib/wallets/crypto_currency/coins/salvium.dart
+++ b/lib/wallets/crypto_currency/coins/salvium.dart
@@ -14,6 +14,10 @@ class Salvium extends CryptonoteCurrency {
_id = _idMain;
_name = "Salvium";
_ticker = "SAL";
+ case CryptoCurrencyNetwork.test:
+ _id = "${_idMain}TestNet";
+ _name = "tSalvium";
+ _ticker = "tSAL";
default:
throw Exception("Unsupported network: $network");
}
@@ -53,6 +57,8 @@ class Salvium extends CryptonoteCurrency {
switch (network) {
case CryptoCurrencyNetwork.main:
return csSalvium.validateAddress(address, 0);
+ case CryptoCurrencyNetwork.test:
+ return csSalvium.validateAddress(address, 1);
default:
throw Exception("Unsupported network: $network");
}
@@ -77,6 +83,22 @@ class Salvium extends CryptonoteCurrency {
clearnetEnabled: true,
isPrimary: isPrimary,
);
+ case CryptoCurrencyNetwork.test:
+ return NodeModel(
+ host: "http://127.0.0.1",
+ port: 29081,
+ name: DefaultNodes.defaultName,
+ id: DefaultNodes.buildId(this),
+ useSSL: false,
+ enabled: true,
+ coinName: identifier,
+ isFailover: true,
+ isDown: false,
+ trusted: true,
+ torEnabled: true,
+ clearnetEnabled: true,
+ isPrimary: isPrimary,
+ );
default:
throw UnimplementedError();
diff --git a/lib/wallets/wallet/impl/salvium_wallet.dart b/lib/wallets/wallet/impl/salvium_wallet.dart
index c345fb0..68d04d4 100644
--- a/lib/wallets/wallet/impl/salvium_wallet.dart
+++ b/lib/wallets/wallet/impl/salvium_wallet.dart
@@ -38,7 +38,12 @@ class SalviumWallet extends LibSalviumWallet {
Future<WrappedWallet> loadWallet({
required String path,
required String password,
- }) => csSalvium.loadWallet(walletId, path: path, password: password);
+ }) => csSalvium.loadWallet(
+ walletId,
+ path: path,
+ password: password,
+ network: cryptoCurrency.network == CryptoCurrencyNetwork.main ? 0 : 1,
+ );
@override
Future<WrappedWallet> getCreatedWallet({
@@ -51,6 +56,7 @@ class SalviumWallet extends LibSalviumWallet {
password: password,
wordCount: wordCount,
seedOffset: seedOffset,
+ network: cryptoCurrency.network == CryptoCurrencyNetwork.main ? 0 : 1,
);
@override
@@ -66,6 +72,7 @@ class SalviumWallet extends LibSalviumWallet {
mnemonic: mnemonic,
height: height,
seedOffset: seedOffset,
+ network: cryptoCurrency.network == CryptoCurrencyNetwork.main ? 0 : 1,
walletId: walletId,
);
@@ -83,6 +90,7 @@ class SalviumWallet extends LibSalviumWallet {
address: address,
privateViewKey: privateViewKey,
height: height,
+ network: cryptoCurrency.network == CryptoCurrencyNetwork.main ? 0 : 1,
);
@override
diff --git a/lib/wl_gen/interfaces/cs_salvium_interface.dart b/lib/wl_gen/interfaces/cs_salvium_interface.dart
index 3ed43f7..53ad91b 100644
--- a/lib/wl_gen/interfaces/cs_salvium_interface.dart
+++ b/lib/wl_gen/interfaces/cs_salvium_interface.dart
@@ -25,6 +25,7 @@ abstract class CsSalviumInterface {
String walletId, {
required String path,
required String password,
+ int network = 0,
});
String getAddress(
@@ -38,6 +39,7 @@ abstract class CsSalviumInterface {
required String password,
required int wordCount,
required String seedOffset,
+ int network = 0,
});
Future<WrappedWallet> getRestoredWallet({
@@ -47,6 +49,7 @@ abstract class CsSalviumInterface {
required String mnemonic,
required String seedOffset,
int height = 0,
+ int network = 0,
});
Future<WrappedWallet> getRestoredFromViewKeyWallet({
@@ -56,6 +59,7 @@ abstract class CsSalviumInterface {
required String address,
required String privateViewKey,
int height = 0,
+ int network = 0,
});
String getTxKey(WrappedWallet wallet, String txid);
diff --git a/scripts/app_config/configure_stack_wallet.sh b/scripts/app_config/configure_stack_wallet.sh
index f468180..cbcead4 100755
--- a/scripts/app_config/configure_stack_wallet.sh
+++ b/scripts/app_config/configure_stack_wallet.sh
@@ -115,6 +115,7 @@ final List<CryptoCurrency> _supportedCoins = List.unmodifiable([
Firo(CryptoCurrencyNetwork.test),
Litecoin(CryptoCurrencyNetwork.test),
Peercoin(CryptoCurrencyNetwork.test),
+ Salvium(CryptoCurrencyNetwork.test),
Stellar(CryptoCurrencyNetwork.test),
Xelis(CryptoCurrencyNetwork.test),
]);
diff --git a/tool/wl_templates/SAL_cs_salvium_interface_impl.template.dart b/tool/wl_templates/SAL_cs_salvium_interface_impl.template.dart
index dd6f398..e6d8303 100644
--- a/tool/wl_templates/SAL_cs_salvium_interface_impl.template.dart
+++ b/tool/wl_templates/SAL_cs_salvium_interface_impl.template.dart
@@ -68,10 +68,12 @@ class _CsSalviumInterfaceImpl extends CsSalviumInterface {
String walletId, {
required String path,
required String password,
+ int network = 0,
}) async {
final wallet = await lib_salvium.SalviumWallet.loadWallet(
path: path,
password: password,
+ networkType: network,
);
return WrappedWallet(wallet);
}
@@ -100,6 +102,7 @@ class _CsSalviumInterfaceImpl extends CsSalviumInterface {
required String password,
required int wordCount,
required String seedOffset,
+ int network = 0,
}) async {
final type = switch (wordCount) {
16 => lib_salvium.SalviumSeedType.sixteen,
@@ -112,6 +115,7 @@ class _CsSalviumInterfaceImpl extends CsSalviumInterface {
password: password,
seedType: type,
seedOffset: seedOffset,
+ networkType: network,
);
return WrappedWallet(wallet);
@@ -124,6 +128,7 @@ class _CsSalviumInterfaceImpl extends CsSalviumInterface {
required String password,
required String mnemonic,
required String seedOffset,
+ int network = 0,
int height = 0,
}) async {
final wallet = await lib_salvium.SalviumWallet.restoreWalletFromSeed(
@@ -132,6 +137,7 @@ class _CsSalviumInterfaceImpl extends CsSalviumInterface {
seed: mnemonic,
restoreHeight: height,
seedOffset: seedOffset,
+ networkType: network,
);
return WrappedWallet(wallet);
@@ -145,6 +151,7 @@ class _CsSalviumInterfaceImpl extends CsSalviumInterface {
required String address,
required String privateViewKey,
int height = 0,
+ int network = 0,
}) async {
final wallet = await lib_salvium.SalviumWallet.createViewOnlyWallet(
path: path,
@@ -152,6 +159,7 @@ class _CsSalviumInterfaceImpl extends CsSalviumInterface {
address: address,
viewKey: privateViewKey,
restoreHeight: height,
+ networkType: network,
);
return WrappedWallet(wallet);
Why this scored 18/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.