CW-589-WalletConnect-Connections-Independent (#1361)

* chore: Create cw_solana package and clean up files

* feat: Add Solana Wallet - Create, Restore form seed, restore from Key, Restore from QR, Send, Receive, transaction history, spl tokens

* fix: Make transactions file specific to solana only for solana transactions

* chore: Revert inject app details script

* fix: Fix issue with node and switch current node to main beta instead of testnet

* fix: Fix merge conflicts and adjust migration version

* fix: Fetch spl token error

Signed-off-by: Blazebrain <davidadegoke16@gmail.com>

* fix: Diplay and activate spl tokens bug

* fix: Review and fixes

* fix: reverted formatting for cryptocurrency class

* fix: Review comments, split sending flow into signing and sending separately, fix issues

* fix: Revert throwing unimplenented error

* chore: Fix comment

* chore: Fix comment

* fix: Errors in flow

* Update provider_types.dart [skip ci]

* fix: Issues with solana wallet

* Update solana_wallet.dart [skip ci]

* fix: Review comments

* fix: Date time config

* fix: Revert bash script for app details

* fix: Error with balance, displaying fees, fixing sent or received identifier bug, displaying token symbol with token transaction item in transactions list

* fix: Issues with address validation when sending spl tokens and walletconnect initial setup

* fix: Issues with sending, fetching transactions history, almost wrapping up walletconnect

* fix: Adjust imports that would affect monerocom building successfully

* fix: Refine transaction direction and continue work on walletconnect

* feat: Display SPL token transfers in the transaction history and finally settle the transaction direction

* fix: Delay in transactions history dispaly, show native token transactions first, then process spl token transactions

* feat: Switch node and revert solana chain id to previous id

* fix: Remove print statement

* fix: Remove await for transactions, fetch all transaction histories instantly and adjust solana send success message

* chore: Code refactoring and streamlined wallet type check for solana send success message

* fix: Make timeout error for node silent and add spl token images

* fix: Still trying to figure out what's wrong

* feat: Make walletconnect connections independent to wallet

* fix: Add proper return type to method

* fix: Alphabetizing translation files

---------

Signed-off-by: Blazebrain <davidadegoke16@gmail.com>
Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com>
This commit is contained in:
Adegoke David 2024-04-12 01:33:43 +01:00 committed by GitHub
parent dcf8ef0d71
commit 7abe5735c0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 84 additions and 10 deletions

View file

@ -1,10 +1,12 @@
import 'dart:async'; import 'dart:async';
import 'dart:convert';
import 'dart:developer'; import 'dart:developer';
import 'dart:typed_data'; import 'dart:typed_data';
import 'package:cake_wallet/core/wallet_connect/chain_service/eth/evm_chain_id.dart'; import 'package:cake_wallet/core/wallet_connect/chain_service/eth/evm_chain_id.dart';
import 'package:cake_wallet/core/wallet_connect/chain_service/eth/evm_chain_service.dart'; import 'package:cake_wallet/core/wallet_connect/chain_service/eth/evm_chain_service.dart';
import 'package:cake_wallet/core/wallet_connect/wallet_connect_key_service.dart'; import 'package:cake_wallet/core/wallet_connect/wallet_connect_key_service.dart';
import 'package:cake_wallet/entities/preferences_key.dart';
import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/core/wallet_connect/models/auth_request_model.dart'; import 'package:cake_wallet/core/wallet_connect/models/auth_request_model.dart';
import 'package:cake_wallet/core/wallet_connect/models/chain_key_model.dart'; import 'package:cake_wallet/core/wallet_connect/models/chain_key_model.dart';
@ -19,6 +21,7 @@ import 'package:cw_core/wallet_type.dart';
import 'package:eth_sig_util/eth_sig_util.dart'; import 'package:eth_sig_util/eth_sig_util.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:mobx/mobx.dart'; import 'package:mobx/mobx.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:walletconnect_flutter_v2/walletconnect_flutter_v2.dart'; import 'package:walletconnect_flutter_v2/walletconnect_flutter_v2.dart';
import 'chain_service/solana/solana_chain_id.dart'; import 'chain_service/solana/solana_chain_id.dart';
@ -32,6 +35,7 @@ class Web3WalletService = Web3WalletServiceBase with _$Web3WalletService;
abstract class Web3WalletServiceBase with Store { abstract class Web3WalletServiceBase with Store {
final AppStore appStore; final AppStore appStore;
final SharedPreferences sharedPreferences;
final BottomSheetService _bottomSheetHandler; final BottomSheetService _bottomSheetHandler;
final WalletConnectKeyService walletKeyService; final WalletConnectKeyService walletKeyService;
@ -52,7 +56,8 @@ abstract class Web3WalletServiceBase with Store {
@observable @observable
ObservableList<StoredCacao> auth; ObservableList<StoredCacao> auth;
Web3WalletServiceBase(this._bottomSheetHandler, this.walletKeyService, this.appStore) Web3WalletServiceBase(
this._bottomSheetHandler, this.walletKeyService, this.appStore, this.sharedPreferences)
: pairings = ObservableList<PairingInfo>(), : pairings = ObservableList<PairingInfo>(),
sessions = ObservableList<SessionData>(), sessions = ObservableList<SessionData>(),
auth = ObservableList<StoredCacao>(), auth = ObservableList<StoredCacao>(),
@ -191,13 +196,6 @@ abstract class Web3WalletServiceBase with Store {
_refreshPairings(); _refreshPairings();
} }
@action
void _refreshPairings() {
pairings.clear();
final allPairings = _web3Wallet.pairings.getAll();
pairings.addAll(allPairings);
}
Future<void> _onSessionProposalError(SessionProposalErrorEvent? args) async { Future<void> _onSessionProposalError(SessionProposalErrorEvent? args) async {
log(args.toString()); log(args.toString());
} }
@ -260,14 +258,37 @@ abstract class Web3WalletServiceBase with Store {
} }
} }
@action
void _refreshPairings() {
print('Refreshing pairings');
pairings.clear();
final allPairings = _web3Wallet.pairings.getAll();
final keyForWallet = getKeyForStoringTopicsForWallet();
final currentTopicsForWallet = getPairingTopicsForWallet(keyForWallet);
final filteredPairings =
allPairings.where((pairing) => currentTopicsForWallet.contains(pairing.topic)).toList();
pairings.addAll(filteredPairings);
}
void _onPairingCreate(PairingEvent? args) { void _onPairingCreate(PairingEvent? args) {
log('Pairing Create Event: $args'); log('Pairing Create Event: $args');
} }
@action @action
void _onSessionConnect(SessionConnect? args) { Future<void> _onSessionConnect(SessionConnect? args) async {
if (args != null) { if (args != null) {
log('Session Connected $args');
await savePairingTopicToLocalStorage(args.session.pairingTopic);
sessions.add(args.session); sessions.add(args.session);
_refreshPairings();
} }
} }
@ -335,4 +356,53 @@ abstract class Web3WalletServiceBase with Store {
List<SessionData> getSessionsForPairingInfo(PairingInfo pairing) { List<SessionData> getSessionsForPairingInfo(PairingInfo pairing) {
return sessions.where((element) => element.pairingTopic == pairing.topic).toList(); return sessions.where((element) => element.pairingTopic == pairing.topic).toList();
} }
String getKeyForStoringTopicsForWallet() {
List<ChainKeyModel> chainKeys = walletKeyService.getKeysForChain(appStore.wallet!);
final keyForPairingTopic =
PreferencesKey.walletConnectPairingTopicsListForWallet(chainKeys.first.publicKey);
return keyForPairingTopic;
}
List<String> getPairingTopicsForWallet(String key) {
// Get the JSON-encoded string from shared preferences
final jsonString = sharedPreferences.getString(key);
// If the string is null, return an empty list
if (jsonString == null) {
return [];
}
// Decode the JSON string to a list of strings
final List<dynamic> jsonList = jsonDecode(jsonString) as List<dynamic>;
// Cast each item to a string
return jsonList.map((item) => item as String).toList();
}
Future<void> savePairingTopicToLocalStorage(String pairingTopic) async {
// Get key specific to the current wallet
final key = getKeyForStoringTopicsForWallet();
// Get all pairing topics attached to this key
final pairingTopicsForWallet = getPairingTopicsForWallet(key);
print(pairingTopicsForWallet);
bool isPairingTopicAlreadySaved = pairingTopicsForWallet.contains(pairingTopic);
print('Is Pairing Topic Saved: $isPairingTopicAlreadySaved');
if (!isPairingTopicAlreadySaved) {
// Update the list with the most recent pairing topic
pairingTopicsForWallet.add(pairingTopic);
// Convert the list of updated pairing topics to a JSON-encoded string
final jsonString = jsonEncode(pairingTopicsForWallet);
// Save the encoded string to shared preferences
await sharedPreferences.setString(key, jsonString);
}
}
} }

View file

@ -493,6 +493,7 @@ Future<void> setup({
getIt.get<BottomSheetService>(), getIt.get<BottomSheetService>(),
getIt.get<WalletConnectKeyService>(), getIt.get<WalletConnectKeyService>(),
appStore, appStore,
getIt.get<SharedPreferences>()
); );
web3WalletService.create(); web3WalletService.create();
return web3WalletService; return web3WalletService;

View file

@ -75,4 +75,7 @@ class PreferencesKey {
static const shouldShowMarketPlaceInDashboard = 'should_show_marketplace_in_dashboard'; static const shouldShowMarketPlaceInDashboard = 'should_show_marketplace_in_dashboard';
static const isNewInstall = 'is_new_install'; static const isNewInstall = 'is_new_install';
static const serviceStatusShaKey = 'service_status_sha_key'; static const serviceStatusShaKey = 'service_status_sha_key';
static const walletConnectPairingTopicsList = 'wallet_connect_pairing_topics_list';
static String walletConnectPairingTopicsListForWallet(String publicKey) =>
'${PreferencesKey.walletConnectPairingTopicsList}_${publicKey}';
} }

View file

@ -30,7 +30,7 @@ class PairingItemWidget extends StatelessWidget {
leading: CakeImageWidget( leading: CakeImageWidget(
imageUrl: metadata.icons.isNotEmpty ? metadata.icons[0]: null, imageUrl: metadata.icons.isNotEmpty ? metadata.icons[0]: null,
displayOnError: CircleAvatar( displayOnError: CircleAvatar(
backgroundImage: AssetImage('assets/images/default_icon.png'), backgroundImage: AssetImage('assets/images/walletconnect_logo.png'),
), ),
), ),
title: Text( title: Text(