feat(spl): add Solana token handling in wallet send/receive view
What changed, and why it matters
This commit adds a placeholder UI message ('WIP') for sending Solana tokens on the desktop wallet view. It does not implement actual token-sending logic, nor does it change any security-sensitive code. The change is purely a UI stub to avoid falling through to the generic token-send widget for Solana wallets.
No security action required. Treat as normal feature work. When the TODO is implemented, review the Solana token send flow for address validation, amount parsing, and transaction signing.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The diff modifies my_wallet.dart to detect Solana wallets and, when a contract address is present (indicating an SPL token), render a centered ‘WIP’ text instead of the DesktopTokenSend widget. The change is guarded by an existing widget.contractAddress == null / != null branch and adds no network, cryptographic, or transaction-construction code. Formatting/indentation changes dominate the diff.
Changed components
lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/my_wallet.dartInspect captured patch +67 / −46
diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/my_wallet.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/my_wallet.dart
index 9a8d94d..9585cf9 100644
--- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/my_wallet.dart
+++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/my_wallet.dart
@@ -18,6 +18,7 @@ import '../../../../pages/wallet_view/transaction_views/tx_v2/transaction_v2_lis
import '../../../../providers/global/wallets_provider.dart';
import '../../../../wallets/crypto_currency/crypto_currency.dart';
import '../../../../wallets/wallet/impl/bitcoin_frost_wallet.dart';
+import '../../../../wallets/wallet/impl/solana_wallet.dart' show SolanaWallet;
import '../../../../wallets/wallet/wallet_mixin_interfaces/view_only_option_interface.dart';
import '../../../../widgets/custom_tab_view.dart';
import '../../../../widgets/desktop/secondary_button.dart';
@@ -42,6 +43,7 @@ class _MyWalletState extends ConsumerState<MyWallet> {
final titles = ["Send", "Receive"];
late final bool isEth;
+ late final bool isSolana;
late final CryptoCurrency coin;
late final bool isFrost;
late final bool isMimblewimblecoin;
@@ -53,6 +55,7 @@ class _MyWalletState extends ConsumerState<MyWallet> {
coin = wallet.info.coin;
isFrost = wallet is BitcoinFrostWallet;
isEth = coin is Ethereum;
+ isSolana = wallet is SolanaWallet;
isMimblewimblecoin = coin is Mimblewimblecoin;
if (isMimblewimblecoin) {
@@ -101,58 +104,76 @@ class _MyWalletState extends ConsumerState<MyWallet> {
children: [
widget.contractAddress == null
? isFrost
- ? Column(
- children: [
- Row(
- mainAxisAlignment: MainAxisAlignment.center,
+ ? Column(
children: [
- Padding(
- padding: const EdgeInsets.fromLTRB(0, 20, 0, 0),
- child: SecondaryButton(
- width: 200,
- buttonHeight: ButtonHeight.l,
- label: "Import sign config",
- onPressed: () async {
- final wallet =
+ Row(
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ Padding(
+ padding: const EdgeInsets.fromLTRB(
+ 0,
+ 20,
+ 0,
+ 0,
+ ),
+ child: SecondaryButton(
+ width: 200,
+ buttonHeight: ButtonHeight.l,
+ label: "Import sign config",
+ onPressed: () async {
+ final wallet =
+ ref
+ .read(pWallets)
+ .getWallet(widget.walletId)
+ as BitcoinFrostWallet;
ref
- .read(pWallets)
- .getWallet(widget.walletId)
- as BitcoinFrostWallet;
- ref.read(pFrostScaffoldArgs.state).state = (
- info: (
- walletName: wallet.info.name,
- frostCurrency: wallet.cryptoCurrency,
- ),
- walletId: widget.walletId,
- stepRoutes:
- FrostRouteGenerator
+ .read(pFrostScaffoldArgs.state)
+ .state = (
+ info: (
+ walletName: wallet.info.name,
+ frostCurrency:
+ wallet.cryptoCurrency,
+ ),
+ walletId: widget.walletId,
+ stepRoutes: FrostRouteGenerator
.signFrostTxStepRoutes,
- parentNav: Navigator.of(context),
- frostInterruptionDialogType:
- FrostInterruptionDialogType
- .transactionCreation,
- callerRouteName: MyStackView.routeName,
- );
-
- await Navigator.of(
- context,
- ).pushNamed(FrostStepScaffold.routeName);
- },
- ),
+ parentNav: Navigator.of(context),
+ frostInterruptionDialogType:
+ FrostInterruptionDialogType
+ .transactionCreation,
+ callerRouteName:
+ MyStackView.routeName,
+ );
+
+ await Navigator.of(context).pushNamed(
+ FrostStepScaffold.routeName,
+ );
+ },
+ ),
+ ),
+ ],
+ ),
+ FrostSendView(
+ walletId: widget.walletId,
+ coin: coin,
),
],
- ),
- FrostSendView(walletId: widget.walletId, coin: coin),
- ],
- )
- : Padding(
- padding: const EdgeInsets.all(20),
- child: DesktopSend(walletId: widget.walletId),
- )
+ )
+ : Padding(
+ padding: const EdgeInsets.all(20),
+ child: DesktopSend(walletId: widget.walletId),
+ )
: Padding(
- padding: const EdgeInsets.all(20),
- child: DesktopTokenSend(walletId: widget.walletId),
- ),
+ padding: const EdgeInsets.all(20),
+ child: isSolana
+ ? Center(
+ child: Text(
+ "WIP", // TODO [prio=high]: Implement.
+ style: Theme.of(context).textTheme.bodyMedium,
+ ),
+ )
+ : DesktopTokenSend(walletId: widget.walletId),
+ ),
Padding(
padding: const EdgeInsets.all(20),
child: DesktopReceive(
Why this scored 15/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.