CW-584-WalletConnect-For-Solana (#1362)

* 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

* Sync with remote

* feat: First run for walletconnect for solana

* chore: Add ankr api key to secrets

* remove duplicate transaction [skip ci]

---------

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-09 01:26:11 +01:00 committed by GitHub
parent 69587e813f
commit f9679fecbe
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 40 additions and 18 deletions

View file

@ -139,6 +139,7 @@ jobs:
echo "const anonPayReferralCode = '${{ secrets.ANON_PAY_REFERRAL_CODE }}';" >> lib/.secrets.g.dart echo "const anonPayReferralCode = '${{ secrets.ANON_PAY_REFERRAL_CODE }}';" >> lib/.secrets.g.dart
echo "const fiatApiKey = '${{ secrets.FIAT_API_KEY }}';" >> lib/.secrets.g.dart echo "const fiatApiKey = '${{ secrets.FIAT_API_KEY }}';" >> lib/.secrets.g.dart
echo "const payfuraApiKey = '${{ secrets.PAYFURA_API_KEY }}';" >> lib/.secrets.g.dart echo "const payfuraApiKey = '${{ secrets.PAYFURA_API_KEY }}';" >> lib/.secrets.g.dart
echo "const ankrApiKey = '${{ secrets.ANKR_API_KEY }}';" >> lib/.secrets.g.dart
echo "const etherScanApiKey = '${{ secrets.ETHER_SCAN_API_KEY }}';" >> cw_evm/lib/.secrets.g.dart echo "const etherScanApiKey = '${{ secrets.ETHER_SCAN_API_KEY }}';" >> cw_evm/lib/.secrets.g.dart
echo "const moralisApiKey = '${{ secrets.MORALIS_API_KEY }}';" >> cw_evm/lib/.secrets.g.dart echo "const moralisApiKey = '${{ secrets.MORALIS_API_KEY }}';" >> cw_evm/lib/.secrets.g.dart
echo "const chatwootWebsiteToken = '${{ secrets.CHATWOOT_WEBSITE_TOKEN }}';" >> lib/.secrets.g.dart echo "const chatwootWebsiteToken = '${{ secrets.CHATWOOT_WEBSITE_TOKEN }}';" >> lib/.secrets.g.dart

View file

@ -2,8 +2,8 @@ import 'solana_chain_service.dart';
enum SolanaChainId { enum SolanaChainId {
mainnet, mainnet,
testnet, // testnet,
devnet, // devnet,
} }
extension SolanaChainIdX on SolanaChainId { extension SolanaChainIdX on SolanaChainId {
@ -13,13 +13,16 @@ extension SolanaChainIdX on SolanaChainId {
switch (this) { switch (this) {
case SolanaChainId.mainnet: case SolanaChainId.mainnet:
name = '4sGjMW1sUnHzSxGspuhpqLDx6wiyjNtZ'; name = '4sGjMW1sUnHzSxGspuhpqLDx6wiyjNtZ';
// solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp
break; break;
case SolanaChainId.testnet: // case SolanaChainId.devnet:
name = '8E9rvCKLFQia2Y35HXjjpWzj8weVo44K'; // name = '8E9rvCKLFQia2Y35HXjjpWzj8weVo44K';
break; // // solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1
case SolanaChainId.devnet: // break;
name = ''; // case SolanaChainId.testnet:
break; // name = '';
// // solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z
// break;
} }
return '${SolanaChainServiceImpl.namespace}:$name'; return '${SolanaChainServiceImpl.namespace}:$name';

View file

@ -43,7 +43,7 @@ class SolanaChainServiceImpl implements ChainService {
SolanaClient( SolanaClient(
rpcUrl: rpcUrl, rpcUrl: rpcUrl,
websocketUrl: Uri.parse(webSocketUrl), websocketUrl: Uri.parse(webSocketUrl),
timeout: const Duration(minutes: 2), timeout: const Duration(minutes: 5),
) { ) {
for (final String event in getEvents()) { for (final String event in getEvents()) {
wallet.registerEventEmitter(chainId: getChainId(), event: event); wallet.registerEventEmitter(chainId: getChainId(), event: event);
@ -72,7 +72,7 @@ class SolanaChainServiceImpl implements ChainService {
@override @override
List<String> getEvents() { List<String> getEvents() {
return ['']; return ['chainChanged', 'accountsChanged'];
} }
Future<String?> requestAuthorization(String? text) async { Future<String?> requestAuthorization(String? text) async {
@ -100,8 +100,7 @@ class SolanaChainServiceImpl implements ChainService {
Future<String> solanaSignTransaction(String topic, dynamic parameters) async { Future<String> solanaSignTransaction(String topic, dynamic parameters) async {
log('received solana sign transaction request $parameters'); log('received solana sign transaction request $parameters');
final solanaSignTx = final solanaSignTx = SolanaSignTransaction.fromJson(parameters as Map<String, dynamic>);
SolanaSignTransaction.fromJson(parameters as Map<String, dynamic>);
final String? authError = await requestAuthorization('Confirm request to sign transaction?'); final String? authError = await requestAuthorization('Confirm request to sign transaction?');
@ -122,10 +121,13 @@ class SolanaChainServiceImpl implements ChainService {
return ''; return '';
} }
String signature = sign.signatures.first.toBase58(); String signature = await solanaClient.sendAndConfirmTransaction(
message: message,
signers: [ownerKeyPair!],
commitment: Commitment.confirmed,
);
print(signature); print(signature);
print(signature.runtimeType);
bottomSheetService.queueBottomSheet( bottomSheetService.queueBottomSheet(
isModalDismissible: true, isModalDismissible: true,

View file

@ -133,13 +133,27 @@ abstract class Web3WalletServiceBase with Store {
if (appStore.wallet!.type == WalletType.solana) { if (appStore.wallet!.type == WalletType.solana) {
for (final cId in SolanaChainId.values) { for (final cId in SolanaChainId.values) {
final node = appStore.settingsStore.getCurrentNode(appStore.wallet!.type); final node = appStore.settingsStore.getCurrentNode(appStore.wallet!.type);
final rpcUri = node.uri;
final webSocketUri = 'wss://${node.uriRaw}/ws${node.uri.path}'; Uri? rpcUri;
String webSocketUrl;
bool isModifiedNodeUri = false;
if (node.uriRaw == 'rpc.ankr.com') {
isModifiedNodeUri = true;
//A better way to handle this instead of adding this to the general secrets?
String ankrApiKey = secrets.ankrApiKey;
rpcUri = Uri.https(node.uriRaw, '/solana/$ankrApiKey');
webSocketUrl = 'wss://${node.uriRaw}/solana/ws/$ankrApiKey';
} else {
webSocketUrl = 'wss://${node.uriRaw}';
}
SolanaChainServiceImpl( SolanaChainServiceImpl(
reference: cId, reference: cId,
rpcUrl: rpcUri, rpcUrl: isModifiedNodeUri ? rpcUri! : node.uri,
webSocketUrl: webSocketUri, webSocketUrl: webSocketUrl,
wcKeyService: walletKeyService, wcKeyService: walletKeyService,
bottomSheetService: _bottomSheetHandler, bottomSheetService: _bottomSheetHandler,
wallet: _web3Wallet, wallet: _web3Wallet,

View file

@ -16,6 +16,7 @@ bool isWalletConnectCompatibleChain(WalletType walletType) {
switch (walletType) { switch (walletType) {
case WalletType.polygon: case WalletType.polygon:
case WalletType.ethereum: case WalletType.ethereum:
case WalletType.solana:
return true; return true;
default: default:
return false; return false;

View file

@ -37,6 +37,7 @@ class SecretKey {
SecretKey('exchangeHelperApiKey', () => ''), SecretKey('exchangeHelperApiKey', () => ''),
SecretKey('walletConnectProjectId', () => ''), SecretKey('walletConnectProjectId', () => ''),
SecretKey('moralisApiKey', () => ''), SecretKey('moralisApiKey', () => ''),
SecretKey('ankrApiKey', () => ''),
]; ];
static final evmChainsSecrets = [ static final evmChainsSecrets = [