diff --git a/.github/workflows/release_dapp_android_internal.yml b/.github/workflows/release_dapp_android_internal.yml
index e3ade37..a3d80d0 100644
--- a/.github/workflows/release_dapp_android_internal.yml
+++ b/.github/workflows/release_dapp_android_internal.yml
@@ -6,6 +6,11 @@ on:
types:
- closed
+# inputs:
+# working-directory
+# flavor
+# BUNDLE_ID
+
jobs:
build:
if: (github.event.pull_request.merged == true && github.event.pull_request.base.ref == 'develop') || github.event_name == 'workflow_dispatch'
diff --git a/.github/workflows/release_wallet_android_internal.yml b/.github/workflows/release_wallet_android_internal.yml
index 19e803d..95b91b6 100644
--- a/.github/workflows/release_wallet_android_internal.yml
+++ b/.github/workflows/release_wallet_android_internal.yml
@@ -6,6 +6,11 @@ on:
types:
- closed
+# inputs:
+# working-directory
+# flavor
+# BUNDLE_ID
+
jobs:
build:
if: (github.event.pull_request.merged == true && github.event.pull_request.base.ref == 'develop') || github.event_name == 'workflow_dispatch'
diff --git a/packages/reown_appkit/CHANGELOG.md b/packages/reown_appkit/CHANGELOG.md
index 7301ae1..d87c71e 100644
--- a/packages/reown_appkit/CHANGELOG.md
+++ b/packages/reown_appkit/CHANGELOG.md
@@ -1,5 +1,6 @@
-## 1.1.0-beta03
+## 1.2.0-beta01
+- Non-EVM Chains support
- Social Logins
## 1.0.1
diff --git a/packages/reown_appkit/example/base/ios/Runner/AppDelegate.swift b/packages/reown_appkit/example/base/ios/Runner/AppDelegate.swift
index 805d27d..53e1dfa 100644
--- a/packages/reown_appkit/example/base/ios/Runner/AppDelegate.swift
+++ b/packages/reown_appkit/example/base/ios/Runner/AppDelegate.swift
@@ -1,5 +1,6 @@
import UIKit
import Flutter
+import CoinbaseWalletSDK
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
@@ -48,14 +49,31 @@ import Flutter
}
override func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
+ if #available(iOS 13.0, *) {
+ if (CoinbaseWalletSDK.isConfigured == true) {
+ if (try? CoinbaseWalletSDK.shared.handleResponse(url)) == true {
+ return true
+ }
+ }
+ }
+
return linkStreamHandler.handleLink(url.absoluteString)
}
override func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
+ if #available(iOS 13.0, *) {
+ if (CoinbaseWalletSDK.isConfigured == true) {
+ if let url = userActivity.webpageURL, (try? CoinbaseWalletSDK.shared.handleResponse(url)) == true {
+ return true
+ }
+ }
+ }
+
if userActivity.activityType == NSUserActivityTypeBrowsingWeb {
handleIncomingUniversalLink(userActivity: userActivity)
return true
}
+
return false
}
diff --git a/packages/reown_appkit/example/base/ios/Runner/Info-internal.plist b/packages/reown_appkit/example/base/ios/Runner/Info-internal.plist
index dbaa42e..0327438 100644
--- a/packages/reown_appkit/example/base/ios/Runner/Info-internal.plist
+++ b/packages/reown_appkit/example/base/ios/Runner/Info-internal.plist
@@ -41,8 +41,53 @@
LSApplicationQueriesSchemes
- wcflutterwallet-internal
+ wirexwallet
+ stasis
+ omni
+ strikex
+ bitcoincom
+ bnc
+ kryptogo
+ roninwallet
+ moonstake
+ ripio
+ frontier
+ qubic
+ dropp
+ safepalwallet
+ bee
+ shido
+ foxwallet
+ exodus
+ coolwallet
+ shinobi-wallet
+ halowallet
+ spotonchain
+ rainbow
+ obvious
+ robinhood-wallet
+ cbwallet
+ okto
+ bitkeep
+ bitizen
+ ape
+ uniswap
+ zerion
+ oasys-wallet
+ coinstats
+ ledgerlive
+ safe
+ okex
+ trust
+ thorwallet
+ krakenwallet
+ coinwallet
+ mewwallet
+ metamask
+ avacus
walletapp
+ wcflutterwallet-internal
+ rn-web3wallet-internal
ITSAppUsesNonExemptEncryption
diff --git a/packages/reown_appkit/example/base/ios/Runner/Info.plist b/packages/reown_appkit/example/base/ios/Runner/Info.plist
index f70379f..43ad88f 100644
--- a/packages/reown_appkit/example/base/ios/Runner/Info.plist
+++ b/packages/reown_appkit/example/base/ios/Runner/Info.plist
@@ -43,8 +43,53 @@
LSApplicationQueriesSchemes
- wcflutterwallet
+ wirexwallet
+ stasis
+ omni
+ strikex
+ bitcoincom
+ bnc
+ kryptogo
+ roninwallet
+ moonstake
+ ripio
+ frontier
+ qubic
+ dropp
+ safepalwallet
+ bee
+ shido
+ foxwallet
+ exodus
+ coolwallet
+ shinobi-wallet
+ halowallet
+ spotonchain
+ rainbow
+ obvious
+ robinhood-wallet
+ cbwallet
+ okto
+ bitkeep
+ bitizen
+ ape
+ uniswap
+ zerion
+ oasys-wallet
+ coinstats
+ ledgerlive
+ safe
+ okex
+ trust
+ thorwallet
+ krakenwallet
+ coinwallet
+ mewwallet
+ metamask
+ avacus
walletapp
+ wcflutterwallet
+ rn-web3wallet
LSRequiresIPhoneOS
diff --git a/packages/reown_appkit/example/base/lib/main.dart b/packages/reown_appkit/example/base/lib/main.dart
index 1a4c7f2..fe38282 100644
--- a/packages/reown_appkit/example/base/lib/main.dart
+++ b/packages/reown_appkit/example/base/lib/main.dart
@@ -1,22 +1,21 @@
import 'dart:convert';
import 'dart:developer';
+import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:reown_appkit/reown_appkit.dart';
-
-import 'package:reown_appkit_dapp/models/chain_metadata.dart';
import 'package:reown_appkit_dapp/models/page_data.dart';
import 'package:reown_appkit_dapp/pages/connect_page.dart';
import 'package:reown_appkit_dapp/pages/pairings_page.dart';
-import 'package:reown_appkit_dapp/pages/sessions_page.dart';
import 'package:reown_appkit_dapp/utils/constants.dart';
-import 'package:reown_appkit_dapp/utils/crypto/chain_data.dart';
import 'package:reown_appkit_dapp/utils/crypto/helpers.dart';
import 'package:reown_appkit_dapp/utils/dart_defines.dart';
import 'package:reown_appkit_dapp/utils/deep_link_handler.dart';
import 'package:reown_appkit_dapp/utils/string_constants.dart';
import 'package:reown_appkit_dapp/widgets/event_widget.dart';
+// ignore: depend_on_referenced_packages
+import 'package:shared_preferences/shared_preferences.dart';
void main() {
WidgetsFlutterBinding.ensureInitialized();
@@ -24,18 +23,55 @@ void main() {
runApp(const MyApp());
}
-class MyApp extends StatelessWidget {
+class MyApp extends StatefulWidget {
const MyApp({super.key});
- // This widget is the root of your application.
+ @override
+ State createState() => _MyAppState();
+}
+
+class _MyAppState extends State with WidgetsBindingObserver {
+ bool _isDarkMode = false;
+
+ @override
+ void initState() {
+ super.initState();
+ WidgetsBinding.instance.addObserver(this);
+ WidgetsBinding.instance.addPostFrameCallback((_) {
+ setState(() {
+ final platformDispatcher = View.of(context).platformDispatcher;
+ final platformBrightness = platformDispatcher.platformBrightness;
+ _isDarkMode = platformBrightness == Brightness.dark;
+ });
+ });
+ }
+
+ @override
+ void dispose() {
+ WidgetsBinding.instance.removeObserver(this);
+ super.dispose();
+ }
+
+ @override
+ void didChangePlatformBrightness() {
+ if (mounted) {
+ setState(() {
+ final platformDispatcher = View.of(context).platformDispatcher;
+ final platformBrightness = platformDispatcher.platformBrightness;
+ _isDarkMode = platformBrightness == Brightness.dark;
+ });
+ }
+ super.didChangePlatformBrightness();
+ }
+
@override
Widget build(BuildContext context) {
- return MaterialApp(
- title: StringConstants.appTitle,
- theme: ThemeData(
- primarySwatch: Colors.blue,
+ return ReownAppKitModalTheme(
+ isDarkMode: _isDarkMode,
+ child: MaterialApp(
+ title: StringConstants.appTitle,
+ home: const MyHomePage(),
),
- home: const MyHomePage(),
);
}
}
@@ -48,8 +84,6 @@ class MyHomePage extends StatefulWidget {
}
class _MyHomePageState extends State {
- bool _initializing = true;
-
ReownAppKit? _appKit;
ReownAppKitModal? _appKitModal;
@@ -101,13 +135,11 @@ class _MyHomePageState extends State {
_appKit = ReownAppKit(
core: ReownCore(
projectId: DartDefines.projectId,
- logLevel: LogLevel.error,
+ logLevel: LogLevel.all,
),
metadata: _pairingMetadata(),
);
- _appKit!.core.addLogListener(_logListener);
-
// Register event handlers
_appKit!.core.relayClient.onRelayClientError.subscribe(
_relayClientError,
@@ -125,13 +157,40 @@ class _MyHomePageState extends State {
_appKit!.onSessionAuthResponse.subscribe(_onSessionAuthResponse);
// See https://docs.reown.com/appkit/flutter/core/custom-chains
- final testNetworks = ReownAppKitModalNetworks.test['eip155'] ?? [];
- ReownAppKitModalNetworks.addNetworks('eip155', testNetworks);
+ // final extraChains = ReownAppKitModalNetworks.extra['eip155']!;
+ // ReownAppKitModalNetworks.addSupportedNetworks('eip155', extraChains);
+ // ReownAppKitModalNetworks.removeSupportedNetworks('solana');
+ // ReownAppKitModalNetworks.removeTestNetworks();
+
+ final prefs = await SharedPreferences.getInstance();
+ final linkMode = prefs.getBool('appkit_sample_linkmode') ?? false;
+ if (!linkMode) {
+ ReownAppKitModalNetworks.addSupportedNetworks('polkadot', [
+ ReownAppKitModalNetworkInfo(
+ name: 'Polkadot',
+ chainId: '91b171bb158e2d3848fa23a9f1c25182',
+ chainIcon: 'https://cryptologos.cc/logos/polkadot-new-dot-logo.png',
+ currency: 'DOT',
+ rpcUrl: 'https://rpc.polkadot.io',
+ explorerUrl: 'https://polkadot.subscan.io',
+ ),
+ ReownAppKitModalNetworkInfo(
+ name: 'Westend',
+ chainId: 'e143f23803ac50e8f6f8e62695d1ce9e',
+ currency: 'DOT',
+ rpcUrl: 'https://westend-rpc.polkadot.io',
+ explorerUrl: 'https://westend.subscan.io',
+ isTestNetwork: true,
+ ),
+ ]);
+ } else {
+ ReownAppKitModalNetworks.removeSupportedNetworks('solana');
+ }
_appKitModal = ReownAppKitModal(
context: context,
appKit: _appKit,
- siweConfig: _siweConfig(),
+ siweConfig: _siweConfig(linkMode),
enableAnalytics: true,
featuresConfig: FeaturesConfig(
email: true,
@@ -141,7 +200,7 @@ class _MyHomePageState extends State {
AppKitSocialOption.Apple,
AppKitSocialOption.Discord,
],
- showMainWallets: false,
+ showMainWallets: false, // OPTIONAL - true by default
),
// requiredNamespaces: {},
// optionalNamespaces: {},
@@ -158,6 +217,38 @@ class _MyHomePageState extends State {
// 'fd20dc426fb37566d803205b19bbc1d4096b248ac04548e3cfb6b3a38bd033aa', // Coinbase
// },
// MORE WALLETS https://explorer.walletconnect.com/?type=wallet&chains=eip155%3A1
+ optionalNamespaces: !linkMode
+ ? {
+ // This is needed if more chains besides EVM and Solana are supported
+ // mostly because we can not define internally every possible method for every possible chain
+ 'eip155': RequiredNamespace.fromJson({
+ 'chains': ReownAppKitModalNetworks.getAllSupportedNetworks(
+ namespace: 'eip155',
+ ).map((chain) => 'eip155:${chain.chainId}').toList(),
+ 'methods':
+ NetworkUtils.defaultNetworkMethods['eip155']!.toList(),
+ 'events': NetworkUtils.defaultNetworkEvents['eip155']!.toList(),
+ }),
+ 'solana': RequiredNamespace.fromJson({
+ 'chains': ReownAppKitModalNetworks.getAllSupportedNetworks(
+ namespace: 'solana',
+ ).map((chain) => 'solana:${chain.chainId}').toList(),
+ 'methods':
+ NetworkUtils.defaultNetworkMethods['solana']!.toList(),
+ 'events': [],
+ }),
+ 'polkadot': RequiredNamespace.fromJson({
+ 'chains': ReownAppKitModalNetworks.getAllSupportedNetworks(
+ namespace: 'polkadot',
+ ).map((chain) => 'polkadot:${chain.chainId}').toList(),
+ 'methods': [
+ 'polkadot_signMessage',
+ 'polkadot_signTransaction',
+ ],
+ 'events': []
+ }),
+ }
+ : null,
);
_appKitModal!.onModalConnect.subscribe(_onModalConnect);
@@ -166,44 +257,73 @@ class _MyHomePageState extends State {
_appKitModal!.onModalDisconnect.subscribe(_onModalDisconnect);
_appKitModal!.onModalError.subscribe(_onModalError);
+ _pageDatas = [
+ PageData(
+ page: ConnectPage(
+ appKitModal: _appKitModal!,
+ linkMode: linkMode,
+ reinitialize: (bool linkMode) async {
+ final result = await showDialog(
+ context: context,
+ builder: (BuildContext context) {
+ return AlertDialog(
+ content: Text('App will be closed to apply changes'),
+ actions: [
+ TextButton(
+ onPressed: () => Navigator.of(context).pop(false),
+ child: Text('Cancel'),
+ ),
+ TextButton(
+ onPressed: () => Navigator.of(context).pop(true),
+ child: Text('Ok'),
+ ),
+ ],
+ );
+ },
+ );
+ if (result == true) {
+ await prefs.setBool('appkit_sample_linkmode', linkMode);
+ if (!kDebugMode) {
+ exit(0);
+ }
+ }
+ },
+ ),
+ title: StringConstants.connectPageTitle,
+ icon: Icons.home,
+ ),
+ PageData(
+ page: PairingsPage(appKitModal: _appKitModal!),
+ title: StringConstants.pairingsPageTitle,
+ icon: Icons.vertical_align_center_rounded,
+ ),
+ // PageData(
+ // page: SessionsPage(appKitModal: _appKitModal!),
+ // title: StringConstants.sessionsPageTitle,
+ // icon: Icons.workspaces_filled,
+ // ),
+ ];
+
await _appKitModal!.init();
await _registerEventHandlers();
- DeepLinkHandler.init(_appKit!);
+ DeepLinkHandler.init(_appKitModal!);
DeepLinkHandler.checkInitialLink();
+ final allChains = ReownAppKitModalNetworks.getAllSupportedNetworks();
// Loop through all the chain data
- for (final ChainMetadata chain in ChainData.allChains) {
+ for (final chain in allChains) {
// Loop through the events for that chain
- for (final event in getChainEvents(chain.type)) {
+ final namespace = ReownAppKitModalNetworks.getNamespaceForChainId(
+ chain.chainId,
+ );
+ for (final event in getChainEvents(namespace)) {
_appKit!.registerEventHandler(
chainId: chain.chainId,
event: event,
);
}
}
-
- setState(() {
- _pageDatas = [
- PageData(
- page: ConnectPage(appKitModal: _appKitModal!),
- title: StringConstants.connectPageTitle,
- icon: Icons.home,
- ),
- PageData(
- page: PairingsPage(appKitModal: _appKitModal!),
- title: StringConstants.pairingsPageTitle,
- icon: Icons.vertical_align_center_rounded,
- ),
- PageData(
- page: SessionsPage(appKitModal: _appKitModal!),
- title: StringConstants.sessionsPageTitle,
- icon: Icons.workspaces_filled,
- ),
- ];
-
- _initializing = false;
- });
}
Future _registerEventHandlers() async {
@@ -215,9 +335,13 @@ class _MyHomePageState extends State {
}
// Loop through all the chain data
- for (final ChainMetadata chain in ChainData.allChains) {
+ final allChains = ReownAppKitModalNetworks.getAllSupportedNetworks();
+ for (final chain in allChains) {
// Loop through the events for that chain
- for (final event in getChainEvents(chain.type)) {
+ final namespace = ReownAppKitModalNetworks.getNamespaceForChainId(
+ chain.chainId,
+ );
+ for (final event in getChainEvents(namespace)) {
_appKit!.registerEventHandler(
chainId: chain.chainId,
event: event,
@@ -227,22 +351,14 @@ class _MyHomePageState extends State {
}
void _onSessionConnect(SessionConnect? event) {
- debugPrint('[SampleDapp] _onSessionConnect $event');
- Future.delayed(const Duration(milliseconds: 500), () {
- setState(() => _selectedIndex = 2);
- });
+ log('[SampleDapp] _onSessionConnect ${jsonEncode(event?.session.toJson())}');
}
void _onSessionAuthResponse(SessionAuthResponse? response) {
debugPrint('[SampleDapp] _onSessionAuthResponse $response');
- if (response?.session != null) {
- Future.delayed(const Duration(milliseconds: 500), () {
- setState(() => _selectedIndex = 2);
- });
- }
}
- void _setState(dynamic args) => setState(() {});
+ void _setState(_) => setState(() {});
void _relayClientError(ErrorEvent? event) {
debugPrint('[SampleDapp] _relayClientError ${event?.error}');
@@ -252,8 +368,6 @@ class _MyHomePageState extends State {
@override
void dispose() {
// Unregister event handlers
- _appKit!.core.removeLogListener(_logListener);
-
_appKit!.core.relayClient.onRelayClientError.unsubscribe(
_relayClientError,
);
@@ -278,26 +392,11 @@ class _MyHomePageState extends State {
super.dispose();
}
- void _logListener(event) {
- if ('${event.level}' == 'Level.debug' ||
- '${event.level}' == 'Level.error') {
- // TODO send to mixpanel
- log('${event.message}');
- } else {
- debugPrint('${event.message}');
- }
- }
-
@override
Widget build(BuildContext context) {
- if (_initializing) {
- return const Center(
- child: CircularProgressIndicator(
- color: StyleConstants.primaryColor,
- ),
- );
+ if (_pageDatas.isEmpty) {
+ return Center(child: CircularProgressIndicator());
}
-
final List navRail = [];
if (MediaQuery.of(context).size.width >= Constants.smallScreen) {
navRail.add(_buildNavigationRail());
@@ -423,7 +522,7 @@ class _MyHomePageState extends State {
}
}
- SIWEConfig _siweConfig() => SIWEConfig(
+ SIWEConfig _siweConfig(bool enabled) => SIWEConfig(
getNonce: () async {
// this has to be called at the very moment of creating the pairing uri
return SIWEUtils.generateNonce();
@@ -467,8 +566,11 @@ class _MyHomePageState extends State {
},
getSession: () async {
// Return proper session from your Web Service
- final address = _appKitModal!.session!.address!;
- final chainId = _appKitModal!.session!.chainId;
+ final chainId = _appKitModal!.selectedChain?.chainId ?? '1';
+ final namespace = ReownAppKitModalNetworks.getNamespaceForChainId(
+ chainId,
+ );
+ final address = _appKitModal!.session!.getAddress(namespace)!;
return SIWESession(address: address, chains: [chainId]);
},
onSignIn: (SIWESession session) {
@@ -483,7 +585,7 @@ class _MyHomePageState extends State {
// Called when disconnecting WalletConnect session was successfull
debugPrint('[SIWEConfig] onSignOut()');
},
- enabled: true,
+ enabled: enabled,
signOutOnDisconnect: true,
signOutOnAccountChange: true,
signOutOnNetworkChange: false,
diff --git a/packages/reown_appkit/example/base/lib/models/chain_metadata.dart b/packages/reown_appkit/example/base/lib/models/chain_metadata.dart
deleted file mode 100644
index 834a0ba..0000000
--- a/packages/reown_appkit/example/base/lib/models/chain_metadata.dart
+++ /dev/null
@@ -1,51 +0,0 @@
-import 'package:flutter/foundation.dart';
-import 'package:flutter/material.dart';
-
-enum ChainType {
- eip155,
- solana,
- kadena,
- cosmos,
- polkadot,
-}
-
-class ChainMetadata {
- final String chainId;
- final String name;
- final String logo;
- final bool isTestnet;
- final Color color;
- final ChainType type;
- final List rpc;
-
- const ChainMetadata({
- required this.chainId,
- required this.name,
- required this.logo,
- this.isTestnet = false,
- required this.color,
- required this.type,
- required this.rpc,
- });
-
- @override
- bool operator ==(Object other) {
- if (identical(this, other)) return true;
-
- return other is ChainMetadata &&
- other.chainId == chainId &&
- other.name == name &&
- other.logo == logo &&
- other.isTestnet == isTestnet &&
- listEquals(other.rpc, rpc);
- }
-
- @override
- int get hashCode {
- return chainId.hashCode ^
- name.hashCode ^
- logo.hashCode ^
- rpc.hashCode ^
- isTestnet.hashCode;
- }
-}
diff --git a/packages/reown_appkit/example/base/lib/pages/connect_page.dart b/packages/reown_appkit/example/base/lib/pages/connect_page.dart
index 7090342..163af43 100644
--- a/packages/reown_appkit/example/base/lib/pages/connect_page.dart
+++ b/packages/reown_appkit/example/base/lib/pages/connect_page.dart
@@ -1,4 +1,5 @@
import 'dart:async';
+import 'dart:convert';
import 'package:fl_toast/fl_toast.dart';
import 'package:flutter/foundation.dart';
@@ -7,13 +8,11 @@ import 'package:flutter/services.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:qr_flutter/qr_flutter.dart';
import 'package:reown_appkit/reown_appkit.dart';
-import 'package:reown_appkit_dapp/models/chain_metadata.dart';
import 'package:reown_appkit_dapp/utils/constants.dart';
-import 'package:reown_appkit_dapp/utils/crypto/chain_data.dart';
import 'package:reown_appkit_dapp/utils/crypto/eip155.dart';
+import 'package:reown_appkit_dapp/utils/crypto/helpers.dart';
import 'package:reown_appkit_dapp/utils/crypto/polkadot.dart';
import 'package:reown_appkit_dapp/utils/crypto/solana.dart';
-import 'package:reown_appkit_dapp/utils/sample_wallets.dart';
import 'package:reown_appkit_dapp/utils/string_constants.dart';
import 'package:reown_appkit_dapp/widgets/chain_button.dart';
import 'package:reown_appkit_dapp/widgets/method_dialog.dart';
@@ -22,16 +21,20 @@ class ConnectPage extends StatefulWidget {
const ConnectPage({
super.key,
required this.appKitModal,
+ required this.reinitialize,
+ this.linkMode = false,
});
final ReownAppKitModal appKitModal;
+ final Function(bool linkMode) reinitialize;
+ final bool linkMode;
@override
ConnectPageState createState() => ConnectPageState();
}
class ConnectPageState extends State {
- final List _selectedChains = [];
+ final List _selectedChains = [];
bool _shouldDismissQrCode = true;
@override
@@ -73,7 +76,7 @@ class ConnectPageState extends State {
super.dispose();
}
- void _selectChain(ChainMetadata chain) {
+ void _selectChain(ReownAppKitModalNetworkInfo chain) {
setState(() {
if (_selectedChains.contains(chain)) {
_selectedChains.remove(chain);
@@ -90,61 +93,58 @@ class ConnectPageState extends State {
void _updateNamespaces() {
optionalNamespaces = {};
- final evmChains =
- _selectedChains.where((e) => e.type == ChainType.eip155).toList();
+ final evmChains = _selectedChains.where((c) {
+ final ns = ReownAppKitModalNetworks.getNamespaceForChainId(c.chainId);
+ return ns == 'eip155';
+ }).toList();
if (evmChains.isNotEmpty) {
optionalNamespaces['eip155'] = RequiredNamespace(
- chains: evmChains.map((c) => c.chainId).toList(),
+ chains: evmChains.map((c) => 'eip155:${c.chainId}').toList(),
methods: EIP155.methods.values.toList(),
events: EIP155.events.values.toList(),
);
}
- final solanaChains =
- _selectedChains.where((e) => e.type == ChainType.solana).toList();
+ final solanaChains = _selectedChains.where((c) {
+ final ns = ReownAppKitModalNetworks.getNamespaceForChainId(c.chainId);
+ return ns == 'solana';
+ }).toList();
if (solanaChains.isNotEmpty) {
optionalNamespaces['solana'] = RequiredNamespace(
- chains: solanaChains.map((c) => c.chainId).toList(),
+ chains: solanaChains.map((c) => 'solana:${c.chainId}').toList(),
methods: Solana.methods.values.toList(),
events: Solana.events.values.toList(),
);
}
- final polkadotChains =
- _selectedChains.where((e) => e.type == ChainType.polkadot).toList();
+ final polkadotChains = _selectedChains.where((c) {
+ final ns = ReownAppKitModalNetworks.getNamespaceForChainId(c.chainId);
+ return ns == 'polkadot';
+ }).toList();
if (polkadotChains.isNotEmpty) {
optionalNamespaces['polkadot'] = RequiredNamespace(
- chains: polkadotChains.map((c) => c.chainId).toList(),
+ chains: polkadotChains.map((c) => 'polkadot:${c.chainId}').toList(),
methods: Polkadot.methods.values.toList(),
events: Polkadot.events.values.toList(),
);
}
- if (optionalNamespaces.isEmpty) {
- requiredNamespaces = {};
- } else {
- // WalletConnectModal still requires to have requiredNamespaces
- // this has to be changed in that SDK
- requiredNamespaces = {
- 'eip155': const RequiredNamespace(
- chains: ['eip155:1'],
- methods: ['personal_sign', 'eth_signTransaction'],
- events: ['chainChanged'],
- ),
- };
- }
+ debugPrint(
+ '[$runtimeType] optionalNamespaces ${jsonEncode(optionalNamespaces)}',
+ );
}
@override
Widget build(BuildContext context) {
// Build the list of chain buttons, clear if the textnet changed
- final testChains = ChainData.allChains.where((e) => e.isTestnet).toList();
- final mainChains = ChainData.allChains.where((e) => !e.isTestnet).toList();
+ final allChains = ReownAppKitModalNetworks.getAllSupportedNetworks();
+ final mainChains = allChains.where((e) => !e.isTestNetwork).toList();
+ final testChains = allChains.where((e) => e.isTestNetwork).toList();
final List chainButtons = [];
final List testButtons = [];
- for (final ChainMetadata chain in mainChains) {
+ for (final chain in mainChains) {
// Build the button
chainButtons.add(
ChainButton(
@@ -154,7 +154,7 @@ class ConnectPageState extends State {
),
);
}
- for (final ChainMetadata chain in testChains) {
+ for (final chain in testChains) {
// Build the button
testButtons.add(
ChainButton(
@@ -166,28 +166,23 @@ class ConnectPageState extends State {
}
return ListView(
- padding: const EdgeInsets.symmetric(horizontal: StyleConstants.linear8),
+ padding: const EdgeInsets.symmetric(
+ horizontal: StyleConstants.linear8,
+ ),
children: [
Text(
widget.appKitModal.appKit!.metadata.name,
style: StyleConstants.subtitleText,
textAlign: TextAlign.center,
),
- const SizedBox(height: StyleConstants.linear8),
- const Divider(),
+ const SizedBox(height: StyleConstants.linear16),
+ const Divider(height: 1.0),
+ const SizedBox(height: StyleConstants.linear16),
const Text(
- 'Connect With AppKit Modal and Link Mode:',
+ 'Connect With AppKit Modal',
style: StyleConstants.buttonText,
textAlign: TextAlign.center,
),
- Text(
- 'Only EVM chains',
- style: TextStyle(
- color: Colors.black.withOpacity(0.7),
- fontSize: 12.0,
- ),
- textAlign: TextAlign.center,
- ),
const SizedBox(height: StyleConstants.linear8),
Row(
mainAxisAlignment: MainAxisAlignment.center,
@@ -207,7 +202,22 @@ class ConnectPageState extends State {
child: Column(
children: [
AppKitModalAccountButton(
- appKit: widget.appKitModal,
+ appKitModal: widget.appKitModal,
+ ),
+ const SizedBox.square(dimension: 8.0),
+ Row(
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ AppKitModalBalanceButton(
+ appKitModal: widget.appKitModal,
+ onTap: widget.appKitModal.openNetworksView,
+ ),
+ const SizedBox.square(dimension: 8.0),
+ AppKitModalAddressButton(
+ appKitModal: widget.appKitModal,
+ onTap: widget.appKitModal.openModalView,
+ ),
+ ],
),
const SizedBox.square(dimension: 8.0),
...(_buildRequestButtons()),
@@ -220,244 +230,93 @@ class ConnectPageState extends State {
child: Column(
children: [
Row(
+ mainAxisAlignment: MainAxisAlignment.center,
children: [
Expanded(
- child: const Divider(),
- ),
- const Text(
- ' Or ',
- style: StyleConstants.buttonText,
- textAlign: TextAlign.center,
- ),
- Expanded(
- child: const Divider(),
- ),
- ],
- ),
- const SizedBox(height: StyleConstants.linear8),
- const Text(
- 'Connect With AppKit multichain',
- style: StyleConstants.buttonText,
- textAlign: TextAlign.center,
- ),
- const SizedBox(height: StyleConstants.linear8),
- Wrap(
- spacing: 10.0,
- children: chainButtons,
- ),
- // const Divider(),
- const Text('Test chains'),
- Wrap(
- spacing: 10.0,
- children: testButtons,
- ),
- const SizedBox(height: StyleConstants.linear16),
- // const Divider(),
- Row(
- children: [
- Expanded(
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.center,
- children: [
- const Text(
- 'Session Propose:',
- style: StyleConstants.buttonText,
- ),
- const SizedBox(height: StyleConstants.linear8),
- Column(
- children:
- WCSampleWallets.getSampleWallets().map((wallet) {
- return Padding(
- padding: const EdgeInsets.only(bottom: 8.0),
- child: ElevatedButton(
- style: _buttonStyle,
- onPressed: _selectedChains.isEmpty
- ? null
- : () {
- _onConnect(
- nativeLink: '${wallet['schema']}',
- closeModal: () {
- if (Navigator.canPop(context)) {
- Navigator.of(context).pop();
- }
- },
- showToast: (m) async {
- showPlatformToast(
- child: Text(m),
- context: context,
- );
- },
- );
- },
- child: Text(
- '${wallet['name']}',
- style: StyleConstants.buttonText,
- ),
- ),
- );
- }).toList(),
- ),
- ],
+ child: Text(
+ 'non-EVM\nSession Proposal',
+ textAlign: TextAlign.end,
+ style: TextStyle(
+ fontWeight: !widget.linkMode
+ ? FontWeight.bold
+ : FontWeight.normal,
+ ),
),
),
- const SizedBox.square(dimension: 8.0),
+ Switch(
+ value: widget.linkMode,
+ onChanged: (value) {
+ widget.reinitialize(value);
+ },
+ ),
Expanded(
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.center,
- children: [
- const Text(
- 'Link Mode:',
- style: StyleConstants.buttonText,
- ),
- const SizedBox(height: StyleConstants.linear8),
- Column(
- children:
- WCSampleWallets.getSampleWallets().map((wallet) {
- return Padding(
- padding: const EdgeInsets.only(bottom: 8.0),
- child: ElevatedButton(
- style: _buttonStyle,
- onPressed: _selectedChains.isEmpty
- ? null
- : () {
- _sessionAuthenticate(
- nativeLink: '${wallet['schema']}',
- universalLink:
- '${wallet['universal']}',
- closeModal: () {
- if (Navigator.canPop(context)) {
- Navigator.of(context).pop();
- }
- },
- showToast: (message) {
- showPlatformToast(
- child: Text(message),
- context: context,
- );
- },
- );
- },
- child: Text(
- '${wallet['name']}',
- style: StyleConstants.buttonText,
- ),
- ),
- );
- }).toList(),
- ),
- ],
+ child: Text(
+ 'only EVM\nLink Mode',
+ style: TextStyle(
+ fontWeight: widget.linkMode
+ ? FontWeight.bold
+ : FontWeight.normal,
+ ),
),
),
],
),
- const SizedBox(height: StyleConstants.linear16),
- const Divider(height: 1.0),
],
),
),
const SizedBox(height: StyleConstants.linear16),
- const Text(
- 'Redirect:',
- style: TextStyle(fontWeight: FontWeight.bold),
- ),
- Row(
- mainAxisAlignment: MainAxisAlignment.start,
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- const Text('Native: '),
- Expanded(
- child: Text(
- '${widget.appKitModal.appKit!.metadata.redirect?.native}',
- style: const TextStyle(fontWeight: FontWeight.bold),
- ),
- ),
- ],
- ),
- Row(
- mainAxisAlignment: MainAxisAlignment.start,
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- const Text('Universal: '),
- Expanded(
- child: Text(
- '${widget.appKitModal.appKit!.metadata.redirect?.universal}',
- style: const TextStyle(fontWeight: FontWeight.bold),
- ),
- ),
- ],
- ),
- Row(
- children: [
- const Text('Link Mode: '),
- Text(
- '${widget.appKitModal.appKit!.metadata.redirect?.linkMode}',
- style: const TextStyle(fontWeight: FontWeight.bold),
- ),
- ],
- ),
+ const Divider(height: 1.0),
+ const SizedBox(height: StyleConstants.linear8),
+ _FooterWidget(appKitModal: widget.appKitModal),
const SizedBox(height: StyleConstants.linear8),
- FutureBuilder(
- future: PackageInfo.fromPlatform(),
- builder: (context, snapshot) {
- if (!snapshot.hasData) {
- return const SizedBox.shrink();
- }
- final v = snapshot.data!.version;
- final b = snapshot.data!.buildNumber;
- const f = String.fromEnvironment('FLUTTER_APP_FLAVOR');
- // return Text('App Version: $v-$f ($b) - SDK v$packageVersion');
- return Row(
- mainAxisAlignment: MainAxisAlignment.start,
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- const Text('App Version: '),
- Expanded(
- child: Text(
- '$v-$f ($b) - SDK v$packageVersion',
- style: const TextStyle(fontWeight: FontWeight.bold),
- ),
- ),
- ],
- );
- },
- ),
- const SizedBox(height: StyleConstants.linear16),
],
);
}
List _buildRequestButtons() {
- return widget.appKitModal.getApprovedMethods()?.map((method) {
+ final chainId = widget.appKitModal.selectedChain?.chainId ?? '1';
+ final ns = ReownAppKitModalNetworks.getNamespaceForChainId(chainId);
+ return widget.appKitModal.getApprovedMethods(namespace: ns)?.map((method) {
final topic = widget.appKitModal.session!.topic ?? '';
final chainId = widget.appKitModal.selectedChain!.chainId;
- final address = widget.appKitModal.session!.address!;
- final requestParams = EIP155.getParams(method, address);
- final enabled = requestParams != null;
+ final address = widget.appKitModal.session!.getAddress(ns)!;
+ final chainInfo = ReownAppKitModalNetworks.getNetworkById(
+ ns,
+ chainId,
+ );
+ // final requestParams = await getParams(method, address);
+ // final enabled = requestParams != null;
return Container(
height: 40.0,
width: double.infinity,
margin: const EdgeInsets.symmetric(
vertical: StyleConstants.linear8,
),
- child: ElevatedButton(
- onPressed: enabled
- ? () {
- widget.appKitModal.launchConnectedWallet();
- final future = widget.appKitModal.request(
- topic: topic,
- chainId: chainId,
- request: requestParams,
- );
- MethodDialog.show(context, method, future);
- }
- : null,
- child: Text(method),
- ),
+ child: FutureBuilder(
+ future: getParams(method, address, rpcUrl: chainInfo?.rpcUrl),
+ builder: (_, snapshot) {
+ final enabled = snapshot.data != null;
+ return ElevatedButton(
+ onPressed: enabled
+ ? () {
+ widget.appKitModal.launchConnectedWallet();
+ final future = widget.appKitModal.request(
+ topic: topic,
+ chainId: chainId,
+ request: snapshot.data!,
+ );
+ MethodDialog.show(context, method, future);
+ }
+ : null,
+ child: Text(method),
+ );
+ }),
);
}).toList() ??
[];
}
+ // ignore: unused_element
Future _onConnect({
required String nativeLink,
VoidCallback? closeModal,
@@ -489,6 +348,7 @@ class ConnectPageState extends State {
closeModal?.call();
}
+ // ignore: unused_element
void _sessionAuthenticate({
required String nativeLink,
required String universalLink,
@@ -496,12 +356,13 @@ class ConnectPageState extends State {
Function(String message)? showToast,
}) async {
debugPrint(
- '[SampleDapp] Creating authenticate with $nativeLink, $universalLink');
+ '[SampleDapp] Creating authentication with $nativeLink, $universalLink',
+ );
final methods1 = requiredNamespaces['eip155']?.methods ?? [];
final methods2 = optionalNamespaces['eip155']?.methods ?? [];
final authResponse = await widget.appKitModal.appKit!.authenticate(
params: SessionAuthRequestParams(
- chains: _selectedChains.map((e) => e.chainId).toList(),
+ chains: _selectedChains.map((e) => 'eip155:${e.chainId}').toList(),
domain: Uri.parse(widget.appKitModal.appKit!.metadata.url).authority,
nonce: AuthUtils.generateNonce(),
uri: widget.appKitModal.appKit!.metadata.url,
@@ -629,13 +490,14 @@ class ConnectPageState extends State {
setState(() {});
}
+ // ignore: unused_element
ButtonStyle get _buttonStyle => ButtonStyle(
backgroundColor: MaterialStateProperty.resolveWith(
(states) {
if (states.contains(MaterialState.disabled)) {
return StyleConstants.grayColor;
}
- return StyleConstants.primaryColor;
+ return Colors.blue;
},
),
textStyle: MaterialStateProperty.resolveWith(
@@ -661,6 +523,106 @@ class ConnectPageState extends State {
);
}
+class _FooterWidget extends StatefulWidget {
+ const _FooterWidget({required this.appKitModal});
+ final ReownAppKitModal appKitModal;
+
+ @override
+ State<_FooterWidget> createState() => __FooterWidgetState();
+}
+
+class __FooterWidgetState extends State<_FooterWidget> {
+ @override
+ Widget build(BuildContext context) {
+ final textStyle = TextStyle(fontSize: 12.0);
+ final textStyleBold = textStyle.copyWith(fontWeight: FontWeight.bold);
+ final redirect = widget.appKitModal.appKit!.metadata.redirect;
+ return Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ const SizedBox(height: StyleConstants.linear8),
+ Text('Redirect:', style: textStyleBold),
+ Row(
+ mainAxisAlignment: MainAxisAlignment.start,
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Text('Native: ', style: textStyle),
+ Expanded(
+ child: Text('${redirect?.native}', style: textStyleBold),
+ ),
+ ],
+ ),
+ Row(
+ mainAxisAlignment: MainAxisAlignment.start,
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Text('Universal: ', style: textStyle),
+ Expanded(
+ child: Text('${redirect?.universal}', style: textStyleBold),
+ ),
+ ],
+ ),
+ Row(
+ children: [
+ Text('Link Mode: ', style: textStyle),
+ Text('${redirect?.linkMode}', style: textStyleBold),
+ ],
+ ),
+ FutureBuilder(
+ future: PackageInfo.fromPlatform(),
+ builder: (context, snapshot) {
+ if (!snapshot.hasData) {
+ return const SizedBox.shrink();
+ }
+ final v = snapshot.data!.version;
+ final b = snapshot.data!.buildNumber;
+ const f = String.fromEnvironment('FLUTTER_APP_FLAVOR');
+ // return Text('App Version: $v-$f ($b) - SDK v$packageVersion');
+ return Row(
+ mainAxisAlignment: MainAxisAlignment.start,
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Text('App Version: ', style: textStyle),
+ Expanded(
+ child: Text(
+ '$v-$f ($b) - SDK v$packageVersion',
+ style: textStyleBold,
+ ),
+ ),
+ ],
+ );
+ },
+ ),
+ const SizedBox(height: StyleConstants.linear8),
+ Row(
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ Visibility(
+ visible: !widget.appKitModal.isConnected,
+ child: SizedBox(
+ height: 30.0,
+ child: ElevatedButton(
+ onPressed: () async {
+ await widget.appKitModal.appKit!.core.storage.deleteAll();
+ ScaffoldMessenger.of(context).showSnackBar(SnackBar(
+ content: Text('Storage cleared'),
+ duration: Duration(seconds: 1),
+ ));
+ },
+ child: Text(
+ 'CLEAR STORAGE',
+ style: TextStyle(fontSize: 10.0),
+ ),
+ ),
+ ),
+ ),
+ ],
+ ),
+ ],
+ );
+ }
+}
+
class QRCodeScreen extends StatefulWidget {
const QRCodeScreen({
super.key,
diff --git a/packages/reown_appkit/example/base/lib/utils/crypto/chain_data.dart b/packages/reown_appkit/example/base/lib/utils/crypto/chain_data.dart
deleted file mode 100644
index b6b4396..0000000
--- a/packages/reown_appkit/example/base/lib/utils/crypto/chain_data.dart
+++ /dev/null
@@ -1,199 +0,0 @@
-import 'package:flutter/material.dart';
-import 'package:reown_appkit_dapp/models/chain_metadata.dart';
-
-class ChainData {
- static final List eip155Chains = [
- ChainMetadata(
- type: ChainType.eip155,
- chainId: 'eip155:1',
- name: 'Ethereum',
- logo: '/chain-logos/eip155-1.png',
- color: Colors.blue.shade300,
- rpc: ['https://eth.drpc.org'],
- ),
- ChainMetadata(
- type: ChainType.eip155,
- chainId: 'eip155:137',
- name: 'Polygon',
- logo: '/chain-logos/eip155-137.png',
- color: Colors.purple.shade300,
- rpc: ['https://polygon-rpc.com/'],
- ),
- const ChainMetadata(
- type: ChainType.eip155,
- chainId: 'eip155:42161',
- name: 'Arbitrum',
- logo: '/chain-logos/eip155-42161.png',
- color: Colors.blue,
- rpc: ['https://arbitrum.blockpi.network/v1/rpc/public'],
- ),
- const ChainMetadata(
- type: ChainType.eip155,
- chainId: 'eip155:10',
- name: 'OP Mainnet',
- logo: '/chain-logos/eip155-10.png',
- color: Colors.red,
- rpc: ['https://mainnet.optimism.io/'],
- ),
- const ChainMetadata(
- type: ChainType.eip155,
- chainId: 'eip155:43114',
- name: 'Avalanche',
- logo: '/chain-logos/eip155-43114.png',
- color: Colors.orange,
- rpc: ['https://api.avax.network/ext/bc/C/rpc'],
- ),
- const ChainMetadata(
- type: ChainType.eip155,
- chainId: 'eip155:56',
- name: 'BNB Smart Chain Mainnet',
- logo: '/chain-logos/eip155-56.png',
- color: Colors.orange,
- rpc: ['https://bsc-dataseed1.bnbchain.org'],
- ),
- const ChainMetadata(
- type: ChainType.eip155,
- chainId: 'eip155:42220',
- name: 'Celo',
- logo: '/chain-logos/eip155-42220.png',
- color: Colors.green,
- rpc: ['https://forno.celo.org/'],
- ),
- const ChainMetadata(
- type: ChainType.eip155,
- chainId: 'eip155:100',
- name: 'Gnosis',
- logo: '/chain-logos/eip155-100.png',
- color: Colors.greenAccent,
- rpc: ['https://rpc.gnosischain.com/'],
- ),
- const ChainMetadata(
- type: ChainType.eip155,
- chainId: 'eip155:324',
- name: 'zkSync',
- logo: '/chain-logos/eip155-324.png',
- color: Colors.black,
- rpc: ['https://mainnet.era.zksync.io'],
- ),
- ChainMetadata(
- type: ChainType.eip155,
- chainId: 'eip155:11155111',
- name: 'Sepolia',
- logo: '/chain-logos/eip155-1.png',
- color: Colors.blue.shade300,
- isTestnet: true,
- rpc: ['https://ethereum-sepolia.publicnode.com'],
- ),
- ChainMetadata(
- type: ChainType.eip155,
- chainId: 'eip155:80001',
- name: 'Polygon Mumbai',
- logo: '/chain-logos/eip155-137.png',
- color: Colors.purple.shade300,
- isTestnet: true,
- rpc: ['https://matic-mumbai.chainstacklabs.com'],
- ),
- ];
-
- static final List solanaChains = [
- const ChainMetadata(
- type: ChainType.solana,
- chainId: 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp',
- name: 'Solana Mainnet',
- logo: '/chain-logos/solana.png',
- color: Color.fromARGB(255, 247, 0, 255),
- rpc: ['https://api.mainnet-beta.solana.com'],
- ),
- const ChainMetadata(
- type: ChainType.solana,
- chainId: 'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1',
- name: 'Solana Devnet',
- logo: '/chain-logos/solana.png',
- color: Color.fromARGB(255, 247, 0, 255),
- rpc: ['https://api.devnet.solana.com'],
- ),
- const ChainMetadata(
- type: ChainType.solana,
- chainId: 'solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z',
- name: 'Solana Testnet',
- logo: '/chain-logos/solana.png',
- color: Colors.black,
- isTestnet: true,
- rpc: ['https://api.testnet.solana.com'],
- ),
- ];
-
- static final List cosmosChains = [
- // TODO TO BE SUPPORTED
- const ChainMetadata(
- type: ChainType.cosmos,
- chainId: 'cosmos:cosmoshub-4',
- name: 'Cosmos Mainnet',
- logo: '/chain-logos/cosmos.png',
- color: Colors.purple,
- rpc: [
- 'https://cosmos-rpc.polkachu.com:443',
- 'https://rpc-cosmoshub-ia.cosmosia.notional.ventures:443',
- 'https://rpc.cosmos.network:443',
- ],
- ),
- ];
-
- static final List kadenaChains = [
- // TODO TO BE SUPPORTED
- const ChainMetadata(
- type: ChainType.kadena,
- chainId: 'kadena:mainnet01',
- name: 'Kadena Mainnet',
- logo: '/chain-logos/kadena.png',
- color: Colors.green,
- rpc: [
- 'https://api.chainweb.com',
- ],
- ),
- const ChainMetadata(
- type: ChainType.kadena,
- chainId: 'kadena:testnet04',
- name: 'Kadena Testnet',
- logo: '/chain-logos/kadena.png',
- color: Colors.green,
- isTestnet: true,
- rpc: [
- 'https://api.chainweb.com',
- ],
- ),
- ];
-
- static final List polkadotChains = [
- const ChainMetadata(
- type: ChainType.polkadot,
- chainId: 'polkadot:91b171bb158e2d3848fa23a9f1c25182',
- name: 'Polkadot Mainnet',
- logo: '/chain-logos/polkadot.png',
- color: Color.fromARGB(255, 174, 57, 220),
- rpc: [
- 'wss://rpc.polkadot.io',
- // 'wss://rpc.matrix.canary.enjin.io'
- ],
- ),
- const ChainMetadata(
- type: ChainType.polkadot,
- chainId: 'polkadot:e143f23803ac50e8f6f8e62695d1ce9e',
- name: 'Polkadot Testnet (Westend)',
- logo: '/chain-logos/polkadot.png',
- color: Color.fromARGB(255, 174, 57, 220),
- isTestnet: true,
- rpc: [
- 'wss://westend-rpc.polkadot.io',
- ],
- ),
- ];
-
- static final List allChains = [
- ...eip155Chains,
- ...solanaChains,
- ...polkadotChains,
- // ...kadenaChains,
- // ...cosmosChains,
- ];
-}
diff --git a/packages/reown_appkit/example/base/lib/utils/crypto/eip155.dart b/packages/reown_appkit/example/base/lib/utils/crypto/eip155.dart
index 5cfde85..594bb28 100644
--- a/packages/reown_appkit/example/base/lib/utils/crypto/eip155.dart
+++ b/packages/reown_appkit/example/base/lib/utils/crypto/eip155.dart
@@ -1,12 +1,9 @@
import 'dart:convert';
-import 'package:eth_sig_util/util/utils.dart';
import 'package:intl/intl.dart';
import 'package:reown_appkit/reown_appkit.dart';
-import 'package:reown_appkit_dapp/models/chain_metadata.dart';
-import 'package:reown_appkit_dapp/utils/crypto/chain_data.dart';
+import 'package:reown_appkit_dapp/utils/crypto/helpers.dart';
import 'package:reown_appkit_dapp/utils/smart_contracts.dart';
-import 'package:reown_appkit_dapp/utils/test_data.dart';
enum EIP155Methods {
personalSign,
@@ -39,7 +36,7 @@ class EIP155 {
required IReownAppKit appKit,
required String topic,
required String method,
- required ChainMetadata chainData,
+ required ReownAppKitModalNetworkInfo chainData,
required String address,
}) {
switch (method) {
@@ -96,21 +93,23 @@ class EIP155 {
EthereumAddress.fromHex(SepoliaTestContract.contractAddress),
);
- final sepolia =
- ChainData.allChains.firstWhere((e) => e.chainId == 'eip155:11155111');
+ final sepolia = ReownAppKitModalNetworks.getNetworkById(
+ 'eip155',
+ '11155111',
+ )!;
switch (action) {
case 'read':
return readSmartContract(
appKit: appKit,
- rpcUrl: sepolia.rpc.first,
+ rpcUrl: sepolia.rpcUrl,
contract: deployedContract,
address: address,
);
case 'write':
return appKit.requestWriteContract(
topic: topic,
- chainId: sepolia.chainId,
+ chainId: 'eip155:${sepolia.chainId}',
deployedContract: deployedContract,
functionName: 'transfer',
transaction: Transaction(
@@ -138,8 +137,8 @@ class EIP155 {
}) async {
return await appKit.request(
topic: topic,
- chainId: chainId,
- request: getParams('personal_sign', address)!,
+ chainId: 'eip155:$chainId',
+ request: (await getParams('personal_sign', address))!,
);
}
@@ -151,8 +150,8 @@ class EIP155 {
}) async {
return await appKit.request(
topic: topic,
- chainId: chainId,
- request: getParams('eth_sign', address)!,
+ chainId: 'eip155:$chainId',
+ request: (await getParams('eth_sign', address))!,
);
}
@@ -164,8 +163,8 @@ class EIP155 {
}) async {
return await appKit.request(
topic: topic,
- chainId: chainId,
- request: getParams('eth_signTypedData', address)!,
+ chainId: 'eip155:$chainId',
+ request: (await getParams('eth_signTypedData', address))!,
);
}
@@ -176,8 +175,8 @@ class EIP155 {
}) async {
return await appKit.request(
topic: topic,
- chainId: chainId,
- request: getParams('eth_signTransaction', '')!,
+ chainId: 'eip155:$chainId',
+ request: (await getParams('eth_signTransaction', ''))!,
);
}
@@ -188,8 +187,8 @@ class EIP155 {
}) async {
return await appKit.request(
topic: topic,
- chainId: chainId,
- request: getParams('eth_sendTransaction', '')!,
+ chainId: 'eip155:$chainId',
+ request: (await getParams('eth_sendTransaction', ''))!,
);
}
@@ -234,54 +233,4 @@ class EIP155 {
'balance': oCcy.format(balance),
};
}
-
- static SessionRequestParams? getParams(String method, String address) {
- switch (method) {
- case 'personal_sign':
- final bytes = utf8.encode(testSignData);
- final encoded = bytesToHex(bytes, include0x: true);
- return SessionRequestParams(
- method: methods[EIP155Methods.personalSign]!,
- params: [encoded, address],
- );
- case 'eth_sign':
- return SessionRequestParams(
- method: methods[EIP155Methods.ethSign]!,
- params: [address, testSignData],
- );
- case 'eth_signTypedData':
- return SessionRequestParams(
- method: methods[EIP155Methods.ethSignTypedData]!,
- params: [address, typedData],
- );
- case 'eth_signTransaction':
- return SessionRequestParams(
- method: methods[EIP155Methods.ethSignTransaction]!,
- params: [
- Transaction(
- from: EthereumAddress.fromHex(address),
- to: EthereumAddress.fromHex(
- '0x59e2f66C0E96803206B6486cDb39029abAE834c0',
- ),
- value: EtherAmount.fromInt(EtherUnit.finney, 12), // == 0.012
- ).toJson(),
- ],
- );
- case 'eth_sendTransaction':
- return SessionRequestParams(
- method: methods[EIP155Methods.ethSendTransaction]!,
- params: [
- Transaction(
- from: EthereumAddress.fromHex(address),
- to: EthereumAddress.fromHex(
- '0x59e2f66C0E96803206B6486cDb39029abAE834c0',
- ),
- value: EtherAmount.fromInt(EtherUnit.finney, 12), // == 0.012
- ).toJson(),
- ],
- );
- default:
- return null;
- }
- }
}
diff --git a/packages/reown_appkit/example/base/lib/utils/crypto/helpers.dart b/packages/reown_appkit/example/base/lib/utils/crypto/helpers.dart
index 6ead377..5caf4b9 100644
--- a/packages/reown_appkit/example/base/lib/utils/crypto/helpers.dart
+++ b/packages/reown_appkit/example/base/lib/utils/crypto/helpers.dart
@@ -1,55 +1,155 @@
-import 'package:flutter/material.dart';
-import 'package:reown_appkit_dapp/models/chain_metadata.dart';
-import 'package:reown_appkit_dapp/utils/crypto/chain_data.dart';
+import 'dart:convert';
+
+import 'package:bs58/bs58.dart';
+import 'package:eth_sig_util/util/utils.dart';
+import 'package:reown_appkit/reown_appkit.dart';
import 'package:reown_appkit_dapp/utils/crypto/eip155.dart';
import 'package:reown_appkit_dapp/utils/crypto/polkadot.dart';
import 'package:reown_appkit_dapp/utils/crypto/solana.dart';
+import 'package:reown_appkit_dapp/utils/test_data.dart';
-String getChainName(String chain) {
- try {
- return ChainData.allChains
- .where((element) => element.chainId == chain)
- .first
- .name;
- } catch (e) {
- debugPrint('[SampleDapp] Invalid chain');
- }
- return 'Unknown';
-}
+import 'package:solana_web3/solana_web3.dart' as solana;
-ChainMetadata getChainMetadataFromChain(String chain) {
- try {
- return ChainData.allChains
- .where((element) => element.chainId == chain)
- .first;
- } catch (e) {
- debugPrint('[SampleDapp] Invalid chain');
- }
- return ChainData.eip155Chains[0];
-}
-
-List getChainMethods(ChainType value) {
- switch (value) {
- case ChainType.eip155:
+List getChainMethods(String namespace) {
+ switch (namespace) {
+ case 'eip155':
return EIP155.methods.values.toList();
- case ChainType.solana:
+ case 'solana':
return Solana.methods.values.toList();
- case ChainType.polkadot:
+ case 'polkadot':
return Polkadot.methods.values.toList();
default:
return [];
}
}
-List getChainEvents(ChainType value) {
- switch (value) {
- case ChainType.eip155:
+List getChainEvents(String namespace) {
+ switch (namespace) {
+ case 'eip155':
return EIP155.events.values.toList();
- case ChainType.solana:
+ case 'solana':
return Solana.events.values.toList();
- case ChainType.polkadot:
+ case 'polkadot':
return Polkadot.events.values.toList();
default:
return [];
}
}
+
+Future getParams(
+ String method,
+ String address, {
+ String? rpcUrl,
+}) async {
+ switch (method) {
+ case 'personal_sign':
+ final bytes = utf8.encode(testSignData);
+ final encoded = bytesToHex(bytes, include0x: true);
+ return SessionRequestParams(
+ method: method,
+ params: [encoded, address],
+ );
+ case 'eth_sign':
+ return SessionRequestParams(
+ method: method,
+ params: [address, testSignData],
+ );
+ case 'eth_signTypedData':
+ return SessionRequestParams(
+ method: method,
+ params: [address, typedData],
+ );
+ case 'eth_signTransaction':
+ return SessionRequestParams(
+ method: method,
+ params: [
+ Transaction(
+ from: EthereumAddress.fromHex(address),
+ to: EthereumAddress.fromHex(
+ '0x59e2f66C0E96803206B6486cDb39029abAE834c0',
+ ),
+ value: EtherAmount.fromInt(EtherUnit.finney, 12), // == 0.012
+ ).toJson(),
+ ],
+ );
+ case 'eth_sendTransaction':
+ return SessionRequestParams(
+ method: method,
+ params: [
+ Transaction(
+ from: EthereumAddress.fromHex(address),
+ to: EthereumAddress.fromHex(
+ '0x59e2f66C0E96803206B6486cDb39029abAE834c0',
+ ),
+ value: EtherAmount.fromInt(EtherUnit.finney, 12), // == 0.012
+ ).toJson(),
+ ],
+ );
+ case 'solana_signMessage':
+ final bytes = utf8.encode(testSignData);
+ final message = base58.encode(bytes);
+ return SessionRequestParams(
+ method: method,
+ params: {'pubkey': address, 'message': message},
+ );
+ case 'solana_signTransaction':
+ // Create a connection to the devnet cluster.
+ final cluster = solana.Cluster.https(
+ Uri.parse(rpcUrl!).authority,
+ );
+ // final cluster = solana.Cluster.devnet;
+ final connection = solana.Connection(cluster);
+
+ // Fetch the latest blockhash.
+ final blockhash = await connection.getLatestBlockhash();
+
+ // Create a System Program instruction to transfer 0.5 SOL from [address1] to [address2].
+ final transactionv0 = solana.Transaction.v0(
+ payer: solana.Pubkey.fromBase58(address),
+ recentBlockhash: blockhash.blockhash,
+ instructions: [
+ solana.TransactionInstruction.fromJson({
+ 'programId': '11111111111111111111111111111111',
+ 'data': [2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0],
+ 'keys': [
+ {
+ 'isSigner': true,
+ 'isWritable': true,
+ 'pubkey': address,
+ },
+ {
+ 'isSigner': false,
+ 'isWritable': true,
+ 'pubkey': '8vCyX7oB6Pc3pbWMGYYZF5pbSnAdQ7Gyr32JqxqCy8ZR'
+ }
+ ]
+ }),
+ // SystemProgram.transfer(
+ // fromPubkey: solana.Pubkey.fromBase58(address),
+ // toPubkey: solana.Pubkey.fromBase58(
+ // '8vCyX7oB6Pc3pbWMGYYZF5pbSnAdQ7Gyr32JqxqCy8ZR',
+ // ),
+ // lamports: solana.solToLamports(0.5),
+ // ),
+ ],
+ );
+
+ const config = solana.TransactionSerializableConfig(
+ verifySignatures: false,
+ );
+ final bytes = transactionv0.serialize(config).asUint8List();
+ final encodedV0Trx = base64.encode(bytes);
+
+ return SessionRequestParams(
+ method: method,
+ params: {
+ 'transaction': encodedV0Trx,
+ // 'pubkey': address,
+ // 'feePayer': address,
+ // ...transactionv0.message.toJson(),
+ },
+ );
+ default:
+ return null;
+ }
+}
diff --git a/packages/reown_appkit/example/base/lib/utils/crypto/polkadot.dart b/packages/reown_appkit/example/base/lib/utils/crypto/polkadot.dart
index 02d770b..194aacb 100644
--- a/packages/reown_appkit/example/base/lib/utils/crypto/polkadot.dart
+++ b/packages/reown_appkit/example/base/lib/utils/crypto/polkadot.dart
@@ -1,5 +1,4 @@
import 'package:reown_appkit/reown_appkit.dart';
-import 'package:reown_appkit_dapp/models/chain_metadata.dart';
enum PolkadotMethods {
polkadotSignTransaction,
@@ -22,7 +21,7 @@ class Polkadot {
required IReownAppKit appKit,
required String topic,
required String method,
- required ChainMetadata chainData,
+ required ReownAppKitModalNetworkInfo chainData,
required String address,
}) {
switch (method) {
diff --git a/packages/reown_appkit/example/base/lib/utils/crypto/solana.dart b/packages/reown_appkit/example/base/lib/utils/crypto/solana.dart
index f060d5b..57266e1 100644
--- a/packages/reown_appkit/example/base/lib/utils/crypto/solana.dart
+++ b/packages/reown_appkit/example/base/lib/utils/crypto/solana.dart
@@ -1,8 +1,5 @@
-import 'dart:convert';
-import 'package:bs58/bs58.dart';
-import 'package:solana_web3/solana_web3.dart' as solana;
+import 'package:reown_appkit_dapp/utils/crypto/helpers.dart';
import 'package:reown_appkit/reown_appkit.dart';
-import 'package:reown_appkit_dapp/models/chain_metadata.dart';
enum SolanaMethods {
solanaSignTransaction,
@@ -25,86 +22,25 @@ class Solana {
required IReownAppKit appKit,
required String topic,
required String method,
- required ChainMetadata chainData,
+ required ReownAppKitModalNetworkInfo chainData,
required String address,
}) async {
switch (method) {
case 'solana_signMessage':
- final bytes = utf8.encode(
- 'This is an example message to be signed - ${DateTime.now()}',
- );
- final message = base58.encode(bytes);
return appKit.request(
topic: topic,
chainId: chainData.chainId,
- request: SessionRequestParams(
- method: method,
- params: {
- 'pubkey': address,
- 'message': message,
- },
- ),
+ request: (await getParams(method, address))!,
);
case 'solana_signTransaction':
- // Create a connection to the devnet cluster.
- final cluster = solana.Cluster.https(
- Uri.parse(chainData.rpc.first).authority,
- );
- // final cluster = solana.Cluster.devnet;
- final connection = solana.Connection(cluster);
-
- // Fetch the latest blockhash.
- final blockhash = await connection.getLatestBlockhash();
-
- // Create a System Program instruction to transfer 0.5 SOL from [address1] to [address2].
- final transactionv0 = solana.Transaction.v0(
- payer: solana.Pubkey.fromBase58(address),
- recentBlockhash: blockhash.blockhash,
- instructions: [
- solana.TransactionInstruction.fromJson({
- 'programId': '11111111111111111111111111111111',
- 'data': [2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0],
- 'keys': [
- {
- 'isSigner': true,
- 'isWritable': true,
- 'pubkey': address,
- },
- {
- 'isSigner': false,
- 'isWritable': true,
- 'pubkey': '8vCyX7oB6Pc3pbWMGYYZF5pbSnAdQ7Gyr32JqxqCy8ZR'
- }
- ]
- }),
- // SystemProgram.transfer(
- // fromPubkey: solana.Pubkey.fromBase58(address),
- // toPubkey: solana.Pubkey.fromBase58(
- // '8vCyX7oB6Pc3pbWMGYYZF5pbSnAdQ7Gyr32JqxqCy8ZR',
- // ),
- // lamports: solana.solToLamports(0.5),
- // ),
- ],
- );
-
- const config = solana.TransactionSerializableConfig(
- verifySignatures: false,
- );
- final bytes = transactionv0.serialize(config).asUint8List();
- final encodedV0Trx = base64.encode(bytes);
-
return appKit.request(
topic: topic,
chainId: chainData.chainId,
- request: SessionRequestParams(
- method: method,
- params: {
- 'transaction': encodedV0Trx,
- 'pubkey': address,
- 'feePayer': address,
- ...transactionv0.message.toJson(),
- },
- ),
+ request: (await getParams(
+ method,
+ address,
+ rpcUrl: chainData.rpcUrl,
+ ))!,
);
default:
throw 'Method unimplemented';
diff --git a/packages/reown_appkit/example/base/lib/utils/deep_link_handler.dart b/packages/reown_appkit/example/base/lib/utils/deep_link_handler.dart
index ccf15e9..10eedaa 100644
--- a/packages/reown_appkit/example/base/lib/utils/deep_link_handler.dart
+++ b/packages/reown_appkit/example/base/lib/utils/deep_link_handler.dart
@@ -1,6 +1,6 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
-import 'package:reown_appkit/reown_appkit.dart';
+import 'package:reown_appkit/modal/i_appkit_modal_impl.dart';
class DeepLinkHandler {
static const _methodChannel = MethodChannel(
@@ -10,7 +10,7 @@ class DeepLinkHandler {
'com.walletconnect.flutterdapp/events',
);
static final waiting = ValueNotifier(false);
- static late IReownAppKit _appKit;
+ static late IReownAppKitModal _appKitModal;
static void initListener() {
if (kIsWeb) return;
@@ -24,9 +24,9 @@ class DeepLinkHandler {
}
}
- static void init(IReownAppKit appKit) {
+ static void init(IReownAppKitModal appKitModal) {
if (kIsWeb) return;
- _appKit = appKit;
+ _appKitModal = appKitModal;
}
static void checkInitialLink() async {
@@ -39,17 +39,17 @@ class DeepLinkHandler {
}
static Uri get nativeUri =>
- Uri.parse(_appKit.metadata.redirect?.native ?? '');
+ Uri.parse(_appKitModal.appKit!.metadata.redirect?.native ?? '');
static Uri get universalUri =>
- Uri.parse(_appKit.metadata.redirect?.universal ?? '');
+ Uri.parse(_appKitModal.appKit!.metadata.redirect?.universal ?? '');
static String get host => universalUri.host;
static void _onLink(dynamic link) async {
+ debugPrint('[SampleDapp] _onLink $link');
if (link == null) return;
- final envelope = ReownCoreUtils.getSearchParamFromURL(link, 'wc_ev');
- if (envelope.isNotEmpty) {
- debugPrint('[SampleDapp] is linkMode $link');
- await _appKit.dispatchEnvelope(link);
+ final handled = await _appKitModal.dispatchEnvelope(link);
+ if (!handled) {
+ debugPrint('[SampleDapp] _onLink not handled by AppKit');
}
}
diff --git a/packages/reown_appkit/example/base/lib/utils/sample_wallets.dart b/packages/reown_appkit/example/base/lib/utils/sample_wallets.dart
index 24b43c3..cc3a800 100644
--- a/packages/reown_appkit/example/base/lib/utils/sample_wallets.dart
+++ b/packages/reown_appkit/example/base/lib/utils/sample_wallets.dart
@@ -23,7 +23,7 @@ class WCSampleWallets {
'name': 'RN Wallet (internal)',
'platform': ['ios', 'android'],
'id': '1234567890123456789012345678922',
- 'schema': 'rn-web3wallet://wc',
+ 'schema': 'rn-web3wallet-internal://',
'bundleId': 'com.walletconnect.web3wallet.rnsample.internal',
'universal': 'https://appkit-lab.reown.com/rn_walletkit_internal',
},
@@ -58,7 +58,7 @@ class WCSampleWallets {
'name': 'RN Wallet',
'platform': ['ios', 'android'],
'id': '123456789012345678901234567892',
- 'schema': 'rn-web3wallet://wc',
+ 'schema': 'rn-web3wallet://',
'bundleId': 'com.walletconnect.web3wallet.rnsample',
'universal': 'https://appkit-lab.reown.com/rn_walletkit',
},
diff --git a/packages/reown_appkit/example/base/lib/widgets/chain_button.dart b/packages/reown_appkit/example/base/lib/widgets/chain_button.dart
index b923c1e..2184019 100644
--- a/packages/reown_appkit/example/base/lib/widgets/chain_button.dart
+++ b/packages/reown_appkit/example/base/lib/widgets/chain_button.dart
@@ -1,7 +1,7 @@
import 'dart:math';
import 'package:flutter/material.dart';
-import 'package:reown_appkit_dapp/models/chain_metadata.dart';
+import 'package:reown_appkit/reown_appkit.dart';
import 'package:reown_appkit_dapp/utils/constants.dart';
class ChainButton extends StatelessWidget {
@@ -12,7 +12,7 @@ class ChainButton extends StatelessWidget {
this.selected = false,
});
- final ChainMetadata chain;
+ final ReownAppKitModalNetworkInfo chain;
final VoidCallback onPressed;
final bool selected;
@@ -24,19 +24,20 @@ class ChainButton extends StatelessWidget {
2) -
14.0,
height: StyleConstants.linear48,
- margin: const EdgeInsets.symmetric(
- vertical: StyleConstants.linear8,
+ margin: const EdgeInsets.only(
+ bottom: StyleConstants.linear8,
),
child: ElevatedButton(
onPressed: onPressed,
style: ButtonStyle(
+ elevation: MaterialStateProperty.all(0.0),
backgroundColor: MaterialStateProperty.all(
- selected ? Colors.grey.shade400 : Colors.white,
+ selected ? Colors.white : Colors.grey.shade300,
),
shape: MaterialStateProperty.all(
RoundedRectangleBorder(
side: BorderSide(
- color: selected ? Colors.grey.shade400 : chain.color,
+ color: selected ? Colors.blue : Colors.grey.shade300,
width: selected ? 4 : 2,
),
borderRadius: BorderRadius.circular(
diff --git a/packages/reown_appkit/example/base/lib/widgets/session_widget.dart b/packages/reown_appkit/example/base/lib/widgets/session_widget.dart
index 88b5399..86c7b32 100644
--- a/packages/reown_appkit/example/base/lib/widgets/session_widget.dart
+++ b/packages/reown_appkit/example/base/lib/widgets/session_widget.dart
@@ -1,8 +1,6 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:reown_appkit/reown_appkit.dart';
-
-import 'package:reown_appkit_dapp/models/chain_metadata.dart';
import 'package:reown_appkit_dapp/utils/constants.dart';
import 'package:reown_appkit_dapp/utils/crypto/eip155.dart';
import 'package:reown_appkit_dapp/utils/crypto/helpers.dart';
@@ -100,11 +98,17 @@ class SessionWidgetState extends State {
Widget _buildAccountWidget(String namespaceAccount) {
final chainId = NamespaceUtils.getChainFromAccount(namespaceAccount);
final account = NamespaceUtils.getAccount(namespaceAccount);
- final chainMetadata = getChainMetadataFromChain(chainId);
+ final namespace = NamespaceUtils.getNamespaceFromChain(
+ chainId,
+ );
+ final chainData = ReownAppKitModalNetworks.getNetworkById(
+ namespace,
+ chainId.split(':').last,
+ );
final List children = [
Text(
- chainMetadata.name,
+ chainData!.name,
style: StyleConstants.subtitleText,
),
const SizedBox(
@@ -123,7 +127,7 @@ class SessionWidgetState extends State {
),
];
- children.addAll(_buildChainMethodButtons(chainMetadata, account));
+ children.addAll(_buildChainMethodButtons(chainData, account));
children.add(const Divider());
@@ -141,11 +145,7 @@ class SessionWidgetState extends State {
style: StyleConstants.subtitleText,
),
]);
- children.addAll(
- _buildChainEventsTiles(
- chainMetadata,
- ),
- );
+ children.addAll(_buildChainEventsTiles(chainData));
// final ChainMetadata
return Container(
@@ -159,7 +159,7 @@ class SessionWidgetState extends State {
),
decoration: BoxDecoration(
border: Border.all(
- color: chainMetadata.color,
+ color: Colors.blue,
),
borderRadius: const BorderRadius.all(
Radius.circular(
@@ -174,13 +174,16 @@ class SessionWidgetState extends State {
}
List _buildChainMethodButtons(
- ChainMetadata chainMetadata,
+ ReownAppKitModalNetworkInfo chainMetadata,
String address,
) {
final List buttons = [];
// Add Methods
- for (final String method in getChainMethods(chainMetadata.type)) {
- final namespaces = _session.namespaces[chainMetadata.type.name];
+ final namespace = ReownAppKitModalNetworks.getNamespaceForChainId(
+ chainMetadata.chainId,
+ );
+ for (final String method in getChainMethods(namespace)) {
+ final namespaces = _session.namespaces[namespace];
final supported = namespaces?.methods.contains(method) ?? false;
buttons.add(
Container(
@@ -205,7 +208,7 @@ class SessionWidgetState extends State {
backgroundColor: MaterialStateProperty.resolveWith(
(states) => states.contains(MaterialState.disabled)
? Colors.grey
- : chainMetadata.color,
+ : Colors.blue,
),
shape: MaterialStateProperty.all(
RoundedRectangleBorder(
@@ -230,11 +233,14 @@ class SessionWidgetState extends State {
Future callChainMethod(
String method,
- ChainMetadata chainMetadata,
+ ReownAppKitModalNetworkInfo chainMetadata,
String address,
) {
- switch (chainMetadata.type) {
- case ChainType.eip155:
+ final namespace = ReownAppKitModalNetworks.getNamespaceForChainId(
+ chainMetadata.chainId,
+ );
+ switch (namespace) {
+ case 'eip155':
return EIP155.callMethod(
appKit: _appKit,
topic: _session.topic,
@@ -242,7 +248,7 @@ class SessionWidgetState extends State {
chainData: chainMetadata,
address: address,
);
- case ChainType.polkadot:
+ case 'polkadot':
return Polkadot.callMethod(
appKit: _appKit,
topic: _session.topic,
@@ -250,7 +256,7 @@ class SessionWidgetState extends State {
chainData: chainMetadata,
address: address,
);
- case ChainType.solana:
+ case 'solana':
return Solana.callMethod(
appKit: _appKit,
topic: _session.topic,
@@ -371,10 +377,12 @@ class SessionWidgetState extends State {
return buttons;
}
- List _buildChainEventsTiles(ChainMetadata chainMetadata) {
+ List _buildChainEventsTiles(ReownAppKitModalNetworkInfo chainData) {
+ final namespace = ReownAppKitModalNetworks.getNamespaceForChainId(
+ chainData.chainId,
+ );
final List values = [];
-
- for (final String event in getChainEvents(chainMetadata.type)) {
+ for (final String event in getChainEvents(namespace)) {
values.add(
Container(
width: double.infinity,
@@ -384,7 +392,7 @@ class SessionWidgetState extends State {
),
decoration: BoxDecoration(
border: Border.all(
- color: chainMetadata.color,
+ color: Colors.blue,
),
borderRadius: const BorderRadius.all(
Radius.circular(
diff --git a/packages/reown_appkit/example/example.md b/packages/reown_appkit/example/example.md
index 2abf4a8..e998461 100644
--- a/packages/reown_appkit/example/example.md
+++ b/packages/reown_appkit/example/example.md
@@ -38,7 +38,7 @@ class _MyHomePageState extends State {
super.initState();
_appKitModal = ReownAppKitModal(
context: context,
- projectId: '07429........',
+ projectId: '074.....',
metadata: const PairingMetadata(
name: 'Example App',
description: 'Example app description',
@@ -51,7 +51,7 @@ class _MyHomePageState extends State {
),
);
- _appKitModal.init();
+ _appKitModal.init().then((value) => setState(() {}));
}
@override
@@ -61,25 +61,26 @@ class _MyHomePageState extends State {
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: Text(widget.title),
),
- body: Column(
- mainAxisAlignment: MainAxisAlignment.center,
- children: [
- AppKitModalNetworkSelectButton(
- appKit: _appKitModal,
- context: context,
- ),
- AppKitModalConnectButton(
- appKit: _appKitModal,
- context: context,
- ),
- Visibility(
- visible: _appKitModal.isConnected,
- child: AppKitModalAccountButton(
+ body: Center(
+ child: Column(
+ children: [
+ AppKitModalNetworkSelectButton(
appKit: _appKitModal,
context: context,
),
- )
- ],
+ AppKitModalConnectButton(
+ appKit: _appKitModal,
+ context: context,
+ ),
+ Visibility(
+ visible: _appKitModal.isConnected,
+ child: AppKitModalAccountButton(
+ appKit: _appKitModal,
+ context: context,
+ ),
+ )
+ ],
+ ),
),
);
}
diff --git a/packages/reown_appkit/example/modal/android/app/src/main/AndroidManifest.xml b/packages/reown_appkit/example/modal/android/app/src/main/AndroidManifest.xml
index 09087a0..dade05d 100644
--- a/packages/reown_appkit/example/modal/android/app/src/main/AndroidManifest.xml
+++ b/packages/reown_appkit/example/modal/android/app/src/main/AndroidManifest.xml
@@ -111,4 +111,4 @@
android:name="flutterEmbedding"
android:value="2" />
-
+
\ No newline at end of file
diff --git a/packages/reown_appkit/example/modal/ios/Runner/AppDelegate.swift b/packages/reown_appkit/example/modal/ios/Runner/AppDelegate.swift
index 242bf15..9002210 100644
--- a/packages/reown_appkit/example/modal/ios/Runner/AppDelegate.swift
+++ b/packages/reown_appkit/example/modal/ios/Runner/AppDelegate.swift
@@ -113,4 +113,5 @@ class LinkStreamHandler: NSObject, FlutterStreamHandler {
eventSink(link)
return true
}
-}
\ No newline at end of file
+}
+
diff --git a/packages/reown_appkit/example/modal/ios/Runner/Info.plist b/packages/reown_appkit/example/modal/ios/Runner/Info.plist
index 119d42e..a97c4c3 100644
--- a/packages/reown_appkit/example/modal/ios/Runner/Info.plist
+++ b/packages/reown_appkit/example/modal/ios/Runner/Info.plist
@@ -69,7 +69,6 @@
cbwallet
okto
bitkeep
- hyperPay
bitizen
ape
uniswap
@@ -90,6 +89,7 @@
wcflutterwallet
wcflutterwallet-internal
rn-web3wallet
+ rn-web3wallet-internal
LSRequiresIPhoneOS
diff --git a/packages/reown_appkit/example/modal/lib/home_page.dart b/packages/reown_appkit/example/modal/lib/home_page.dart
index a2a4490..f48418b 100644
--- a/packages/reown_appkit/example/modal/lib/home_page.dart
+++ b/packages/reown_appkit/example/modal/lib/home_page.dart
@@ -1,3 +1,4 @@
+import 'dart:convert';
import 'dart:developer';
import 'package:fl_toast/fl_toast.dart';
@@ -7,7 +8,6 @@ import 'package:reown_appkit_example/services/deep_link_handler.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:reown_appkit/reown_appkit.dart';
-
import 'package:reown_appkit_example/widgets/debug_drawer.dart';
import 'package:reown_appkit_example/utils/constants.dart';
import 'package:reown_appkit_example/services/siwe_service.dart';
@@ -34,7 +34,7 @@ class MyHomePage extends StatefulWidget {
}
class _MyHomePageState extends State {
- final overlay = OverlayController(const Duration(milliseconds: 200));
+ late OverlayController overlay;
late ReownAppKitModal _appKitModal;
late SIWESampleWebService _siweTestService;
bool _initialized = false;
@@ -44,7 +44,6 @@ class _MyHomePageState extends State {
super.initState();
_siweTestService = SIWESampleWebService();
WidgetsBinding.instance.addPostFrameCallback((_) {
- _toggleOverlay();
_initializeService(widget.prefs);
});
}
@@ -54,8 +53,6 @@ class _MyHomePageState extends State {
}
String get _flavor {
- // String flavor = '-${const String.fromEnvironment('FLUTTER_APP_FLAVOR')}';
- // return flavor.replaceAll('-production', '');
final internal = widget.bundleId.endsWith('.internal');
final debug = widget.bundleId.endsWith('.debug');
if (internal || debug || kDebugMode) {
@@ -168,8 +165,11 @@ class _MyHomePageState extends State {
} catch (error) {
debugPrint('[SIWEConfig] getSession error: $error');
// Fallback patch for testing purposes in case SIWE backend has issues
- final address = _appKitModal.session!.address!;
- final chainId = _appKitModal.session!.chainId;
+ final chainId = _appKitModal.selectedChain?.chainId ?? '1';
+ final namespace = ReownAppKitModalNetworks.getNamespaceForChainId(
+ chainId,
+ );
+ final address = _appKitModal.session!.getAddress(namespace)!;
return SIWESession(address: address, chains: [chainId]);
}
},
@@ -207,27 +207,56 @@ class _MyHomePageState extends State {
final siweAuthValue = prefs.getBool('appkit_siwe_auth') ?? true;
// See https://docs.reown.com/appkit/flutter/core/custom-chains
- final testNetworks = ReownAppKitModalNetworks.test['eip155'] ?? [];
- ReownAppKitModalNetworks.addNetworks('eip155', testNetworks);
+ // Add extra chains
+ // final extraChains = ReownAppKitModalNetworks.extra['eip155']!;
+ // ReownAppKitModalNetworks.addSupportedNetworks('eip155', extraChains);
+ // Remove every test network
+ // ReownAppKitModalNetworks.removeTestNetworks();
+ if (siweAuthValue) {
+ // Remove Solana support
+ ReownAppKitModalNetworks.removeSupportedNetworks('solana');
+ } else {
+ // Add custom chains
+ ReownAppKitModalNetworks.addSupportedNetworks('polkadot', [
+ ReownAppKitModalNetworkInfo(
+ name: 'Polkadot',
+ chainId: '91b171bb158e2d3848fa23a9f1c25182',
+ chainIcon: 'https://cryptologos.cc/logos/polkadot-new-dot-logo.png',
+ currency: 'DOT',
+ rpcUrl: 'https://rpc.polkadot.io',
+ explorerUrl: 'https://polkadot.subscan.io',
+ ),
+ ReownAppKitModalNetworkInfo(
+ name: 'Westend',
+ chainId: 'e143f23803ac50e8f6f8e62695d1ce9e',
+ currency: 'DOT',
+ rpcUrl: 'https://westend-rpc.polkadot.io',
+ explorerUrl: 'https://westend.subscan.io',
+ isTestNetwork: true,
+ ),
+ ]);
+ }
try {
_appKitModal = ReownAppKitModal(
context: context,
projectId: DartDefines.projectId,
- logLevel: LogLevel.error,
+ logLevel: LogLevel.all,
metadata: _pairingMetadata(),
siweConfig: _siweConfig(siweAuthValue),
enableAnalytics: analyticsValue, // OPTIONAL - null by default
- featuresConfig: FeaturesConfig(
- email: emailWalletValue,
- socials: [
- AppKitSocialOption.Farcaster,
- AppKitSocialOption.X,
- AppKitSocialOption.Apple,
- AppKitSocialOption.Discord,
- ],
- showMainWallets: true, // OPTIONAL - true by default
- ),
+ featuresConfig: emailWalletValue
+ ? FeaturesConfig(
+ email: true,
+ socials: [
+ AppKitSocialOption.Farcaster,
+ AppKitSocialOption.X,
+ AppKitSocialOption.Apple,
+ AppKitSocialOption.Discord,
+ ],
+ // showMainWallets: false, // OPTIONAL - true by default
+ )
+ : null,
// requiredNamespaces: {},
// optionalNamespaces: {},
// includedWalletIds: {},
@@ -239,11 +268,51 @@ class _MyHomePageState extends State {
'c03dfee351b6fcc421b4494ea33b9d4b92a984f87aa76d1663bb28705e95034a', // Uniswap
'38f5d18bd8522c244bdd70cb4a68e0e718865155811c043f052fb9f1c51de662', // Bitget
},
- // excludedWalletIds: {
- // 'fd20dc426fb37566d803205b19bbc1d4096b248ac04548e3cfb6b3a38bd033aa', // Coinbase
- // },
+ // excludedWalletIds: {},
// MORE WALLETS https://explorer.walletconnect.com/?type=wallet&chains=eip155%3A1
+ // getBalanceFallback: () async {
+ // // This method will be triggered if getting the balance from our blockchain API fails
+ // // You could place here your own getBalance method
+ // return 0.123;
+ // },
+ optionalNamespaces: siweAuthValue
+ ? null
+ : {
+ 'eip155': RequiredNamespace.fromJson({
+ 'chains': ReownAppKitModalNetworks.getAllSupportedNetworks(
+ namespace: 'eip155',
+ ).map((chain) => 'eip155:${chain.chainId}').toList(),
+ 'methods':
+ NetworkUtils.defaultNetworkMethods['eip155']!.toList(),
+ 'events':
+ NetworkUtils.defaultNetworkEvents['eip155']!.toList(),
+ }),
+ 'solana': RequiredNamespace.fromJson({
+ 'chains': ReownAppKitModalNetworks.getAllSupportedNetworks(
+ namespace: 'solana',
+ ).map((chain) => 'solana:${chain.chainId}').toList(),
+ 'methods':
+ NetworkUtils.defaultNetworkMethods['solana']!.toList(),
+ 'events': [],
+ }),
+ 'polkadot': RequiredNamespace.fromJson({
+ 'chains': [
+ 'polkadot:91b171bb158e2d3848fa23a9f1c25182',
+ 'polkadot:e143f23803ac50e8f6f8e62695d1ce9e'
+ ],
+ 'methods': [
+ 'polkadot_signMessage',
+ 'polkadot_signTransaction',
+ ],
+ 'events': []
+ }),
+ },
);
+ overlay = OverlayController(
+ const Duration(milliseconds: 200),
+ appKitModal: _appKitModal,
+ );
+ _toggleOverlay();
setState(() => _initialized = true);
} on ReownAppKitModalException catch (e) {
debugPrint('⛔️ ${e.message}');
@@ -269,7 +338,6 @@ class _MyHomePageState extends State {
_appKitModal.appKit!.core.relayClient.onRelayClientDisconnect.subscribe(
_onRelayClientDisconnect,
);
- _appKitModal.appKit!.core.addLogListener(_logListener);
//
await _appKitModal.init();
@@ -279,20 +347,9 @@ class _MyHomePageState extends State {
setState(() {});
}
- void _logListener(event) {
- if ('${event.level}' == 'Level.debug' ||
- '${event.level}' == 'Level.error') {
- // TODO send to mixpanel
- log('${event.message}');
- } else {
- debugPrint('${event.message}');
- }
- }
-
@override
void dispose() {
//
- _appKitModal.appKit!.core.removeLogListener(_logListener);
_appKitModal.appKit!.core.relayClient.onRelayClientConnect.unsubscribe(
_onRelayClientConnect,
);
@@ -318,7 +375,7 @@ class _MyHomePageState extends State {
void _onModalConnect(ModalConnect? event) async {
setState(() {});
- debugPrint('[ExampleApp] _onModalConnect ${event?.session.toJson()}');
+ log('[ExampleApp] _onModalConnect ${jsonEncode(event?.session.toJson())}');
}
void _onModalUpdate(ModalConnect? event) {
@@ -326,17 +383,17 @@ class _MyHomePageState extends State {
}
void _onModalNetworkChange(ModalNetworkChange? event) {
- debugPrint('[ExampleApp] _onModalNetworkChange ${event?.toString()}');
+ log('[ExampleApp] _onModalNetworkChange ${event?.toString()}');
setState(() {});
}
void _onModalDisconnect(ModalDisconnect? event) {
- debugPrint('[ExampleApp] _onModalDisconnect ${event?.toString()}');
+ log('[ExampleApp] _onModalDisconnect ${event?.toString()}');
setState(() {});
}
void _onModalError(ModalError? event) {
- debugPrint('[ExampleApp] _onModalError ${event?.toString()}');
+ log('[ExampleApp] _onModalError ${event?.toString()}');
// When user connected to Coinbase Wallet but Coinbase Wallet does not have a session anymore
// (for instance if user disconnected the dapp directly within Coinbase Wallet)
// Then Coinbase Wallet won't emit any event
@@ -366,7 +423,7 @@ class _MyHomePageState extends State {
showTextToast(text: 'Relay connected', context: context);
}
- void _onRelayClientError(EventArgs? event) {
+ void _onRelayClientError(ErrorEvent? event) {
setState(() {});
showTextToast(text: 'Relay disconnected', context: context);
}
@@ -501,7 +558,7 @@ class _ConnectedView extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.center,
children: [
AppKitModalAccountButton(
- appKit: appKit,
+ appKitModal: appKit,
// custom: ValueListenableBuilder(
// valueListenable: appKit.balanceNotifier,
// builder: (_, balance, __) {
@@ -519,7 +576,7 @@ class _ConnectedView extends StatelessWidget {
children: [
AppKitModalBalanceButton(
appKitModal: appKit,
- onTap: appKit.openModalView,
+ onTap: appKit.openNetworksView,
),
const SizedBox.square(dimension: 8.0),
AppKitModalAddressButton(
diff --git a/packages/reown_appkit/example/modal/lib/services/eip155_service.dart b/packages/reown_appkit/example/modal/lib/services/methods_service.dart
similarity index 74%
rename from packages/reown_appkit/example/modal/lib/services/eip155_service.dart
rename to packages/reown_appkit/example/modal/lib/services/methods_service.dart
index bcc1a3a..2dab1fe 100644
--- a/packages/reown_appkit/example/modal/lib/services/eip155_service.dart
+++ b/packages/reown_appkit/example/modal/lib/services/methods_service.dart
@@ -5,11 +5,13 @@ import 'package:reown_appkit/reown_appkit.dart';
// ignore: depend_on_referenced_packages
import 'package:convert/convert.dart';
+// ignore: depend_on_referenced_packages
+import 'package:bs58/bs58.dart';
import 'package:reown_appkit_example/services/contracts/aave_contract.dart';
import 'package:reown_appkit_example/services/contracts/test_data.dart';
-enum EIP155UIMethods {
+enum SupportedMethods {
personalSign,
ethSendTransaction,
requestAccounts,
@@ -17,7 +19,8 @@ enum EIP155UIMethods {
ethSignTypedDataV3,
ethSignTypedDataV4,
ethSignTransaction,
- walletWatchAsset;
+ walletWatchAsset,
+ solanaSignMessage;
String get name {
switch (this) {
@@ -37,69 +40,74 @@ enum EIP155UIMethods {
return 'eth_signTransaction';
case walletWatchAsset:
return 'wallet_watchAsset';
+ case solanaSignMessage:
+ return 'solana_signMessage';
}
}
}
-class EIP155 {
- static EIP155UIMethods methodFromName(String name) {
+class MethodsService {
+ static SupportedMethods methodFromName(String name) {
switch (name) {
case 'personal_sign':
- return EIP155UIMethods.personalSign;
+ return SupportedMethods.personalSign;
case 'eth_signTypedData_v4':
- return EIP155UIMethods.ethSignTypedDataV4;
+ return SupportedMethods.ethSignTypedDataV4;
case 'eth_sendTransaction':
- return EIP155UIMethods.ethSendTransaction;
+ return SupportedMethods.ethSendTransaction;
case 'eth_requestAccounts':
- return EIP155UIMethods.requestAccounts;
+ return SupportedMethods.requestAccounts;
case 'eth_signTypedData_v3':
- return EIP155UIMethods.ethSignTypedDataV3;
+ return SupportedMethods.ethSignTypedDataV3;
case 'eth_signTypedData':
- return EIP155UIMethods.ethSignTypedData;
+ return SupportedMethods.ethSignTypedData;
case 'eth_signTransaction':
- return EIP155UIMethods.ethSignTransaction;
+ return SupportedMethods.ethSignTransaction;
case 'wallet_watchAsset':
- return EIP155UIMethods.walletWatchAsset;
+ return SupportedMethods.walletWatchAsset;
+ case 'solana_signMessage':
+ return SupportedMethods.solanaSignMessage;
default:
- throw Exception('Unrecognized method');
+ throw Exception('Method not implemented');
}
}
static Future callMethod({
required ReownAppKitModal appKitModal,
required String topic,
- required EIP155UIMethods method,
+ required String method,
required String chainId,
required String address,
}) {
- final cid = int.parse(chainId);
- switch (method) {
- case EIP155UIMethods.requestAccounts:
+ // final cid = int.parse(chainId);
+ final supportedMethod = MethodsService.methodFromName(method);
+ switch (supportedMethod) {
+ case SupportedMethods.requestAccounts:
return requestAccounts(
appKitModal: appKitModal,
);
- case EIP155UIMethods.personalSign:
+ case SupportedMethods.personalSign:
return personalSign(
appKitModal: appKitModal,
message: testSignData,
);
- case EIP155UIMethods.ethSignTypedDataV3:
+ case SupportedMethods.ethSignTypedDataV3:
return ethSignTypedDataV3(
appKitModal: appKitModal,
- data: jsonEncode(typeDataV3(cid)),
+ data: jsonEncode(typeDataV3(int.parse(chainId))),
);
- case EIP155UIMethods.ethSignTypedData:
+ case SupportedMethods.ethSignTypedData:
return ethSignTypedData(
appKitModal: appKitModal,
data: jsonEncode(typedData()),
);
- case EIP155UIMethods.ethSignTypedDataV4:
+ case SupportedMethods.ethSignTypedDataV4:
return ethSignTypedDataV4(
appKitModal: appKitModal,
- data: jsonEncode(typeDataV4(cid)),
+ data: jsonEncode(typeDataV4(int.parse(chainId))),
);
- case EIP155UIMethods.ethSignTransaction:
- case EIP155UIMethods.ethSendTransaction:
+ case SupportedMethods.ethSignTransaction:
+ case SupportedMethods.ethSendTransaction:
return ethSendOrSignTransaction(
appKitModal: appKitModal,
method: method,
@@ -112,10 +120,15 @@ class EIP155 {
data: utf8.encode('0x'), // to make it work with some wallets
),
);
- case EIP155UIMethods.walletWatchAsset:
+ case SupportedMethods.walletWatchAsset:
return walletWatchAsset(
appKitModal: appKitModal,
);
+ case SupportedMethods.solanaSignMessage:
+ return solanaSignMessage(
+ appKitModal: appKitModal,
+ message: testSignData,
+ );
}
}
@@ -126,7 +139,7 @@ class EIP155 {
topic: appKitModal.session!.topic,
chainId: appKitModal.selectedChain!.chainId,
request: SessionRequestParams(
- method: EIP155UIMethods.requestAccounts.name,
+ method: SupportedMethods.requestAccounts.name,
params: [],
),
);
@@ -138,32 +151,59 @@ class EIP155 {
}) async {
final bytes = utf8.encode(message);
final encoded = hex.encode(bytes);
+ final namespace = ReownAppKitModalNetworks.getNamespaceForChainId(
+ appKitModal.selectedChain!.chainId,
+ );
return await appKitModal.request(
topic: appKitModal.session!.topic,
chainId: appKitModal.selectedChain!.chainId,
request: SessionRequestParams(
- method: EIP155UIMethods.personalSign.name,
+ method: SupportedMethods.personalSign.name,
params: [
'0x$encoded',
- appKitModal.session!.address!,
+ appKitModal.session!.getAddress(namespace)!,
],
),
);
}
+ static Future solanaSignMessage({
+ required ReownAppKitModal appKitModal,
+ required String message,
+ }) async {
+ final bytes = utf8.encode(testSignData);
+ final message = base58.encode(bytes);
+ final namespace = ReownAppKitModalNetworks.getNamespaceForChainId(
+ appKitModal.selectedChain!.chainId,
+ );
+ final address = appKitModal.session!.getAddress(namespace)!;
+
+ return await appKitModal.request(
+ topic: appKitModal.session!.topic,
+ chainId: appKitModal.selectedChain!.chainId,
+ request: SessionRequestParams(
+ method: SupportedMethods.solanaSignMessage.name,
+ params: {'pubkey': address, 'message': message},
+ ),
+ );
+ }
+
static Future ethSignTypedData({
required ReownAppKitModal appKitModal,
required String data,
}) async {
+ final namespace = ReownAppKitModalNetworks.getNamespaceForChainId(
+ appKitModal.selectedChain!.chainId,
+ );
return await appKitModal.request(
topic: appKitModal.session!.topic,
chainId: appKitModal.selectedChain!.chainId,
request: SessionRequestParams(
- method: EIP155UIMethods.ethSignTypedData.name,
+ method: SupportedMethods.ethSignTypedData.name,
params: [
data,
- appKitModal.session!.address!,
+ appKitModal.session!.getAddress(namespace)!,
],
),
);
@@ -173,14 +213,17 @@ class EIP155 {
required ReownAppKitModal appKitModal,
required String data,
}) async {
+ final namespace = ReownAppKitModalNetworks.getNamespaceForChainId(
+ appKitModal.selectedChain!.chainId,
+ );
return await appKitModal.request(
topic: appKitModal.session!.topic,
chainId: appKitModal.selectedChain!.chainId,
request: SessionRequestParams(
- method: EIP155UIMethods.ethSignTypedDataV3.name,
+ method: SupportedMethods.ethSignTypedDataV3.name,
params: [
data,
- appKitModal.session!.address!,
+ appKitModal.session!.getAddress(namespace)!,
],
),
);
@@ -190,14 +233,17 @@ class EIP155 {
required ReownAppKitModal appKitModal,
required String data,
}) async {
+ final namespace = ReownAppKitModalNetworks.getNamespaceForChainId(
+ appKitModal.selectedChain!.chainId,
+ );
return await appKitModal.request(
topic: appKitModal.session!.topic,
chainId: appKitModal.selectedChain!.chainId,
request: SessionRequestParams(
- method: EIP155UIMethods.ethSignTypedDataV4.name,
+ method: SupportedMethods.ethSignTypedDataV4.name,
params: [
data,
- appKitModal.session!.address!,
+ appKitModal.session!.getAddress(namespace)!,
],
),
);
@@ -206,13 +252,13 @@ class EIP155 {
static Future ethSendOrSignTransaction({
required ReownAppKitModal appKitModal,
required Transaction transaction,
- required EIP155UIMethods method,
+ required String method,
}) async {
return await appKitModal.request(
topic: appKitModal.session!.topic,
chainId: appKitModal.selectedChain!.chainId,
request: SessionRequestParams(
- method: method.name,
+ method: method,
params: [
transaction.toJson(),
],
@@ -227,7 +273,7 @@ class EIP155 {
topic: appKitModal.session!.topic,
chainId: appKitModal.selectedChain!.chainId,
request: SessionRequestParams(
- method: EIP155UIMethods.walletWatchAsset.name,
+ method: SupportedMethods.walletWatchAsset.name,
params: {
'type': 'ERC20',
'options': {
@@ -285,13 +331,18 @@ class EIP155 {
final d = (decimals.first as BigInt);
final requestValue = _formatValue(0.01, decimals: d);
// now we call `transfer` write function with the parsed value.
+ final namespace = ReownAppKitModalNetworks.getNamespaceForChainId(
+ appKitModal.selectedChain!.chainId,
+ );
return appKitModal.requestWriteContract(
topic: appKitModal.session!.topic,
chainId: appKitModal.selectedChain!.chainId,
deployedContract: deployedContract,
functionName: 'transfer',
transaction: Transaction(
- from: EthereumAddress.fromHex(appKitModal.session!.address!),
+ from: EthereumAddress.fromHex(
+ appKitModal.session!.getAddress(namespace)!,
+ ),
),
parameters: [
EthereumAddress.fromHex(
@@ -357,13 +408,18 @@ class EIP155 {
final d = (decimals.first as BigInt);
final requestValue = _formatValue(0.23, decimals: d);
// now we call `transfer` write function with the parsed value.
+ final namespace = ReownAppKitModalNetworks.getNamespaceForChainId(
+ appKitModal.selectedChain!.chainId,
+ );
return appKitModal.requestWriteContract(
topic: appKitModal.session!.topic,
chainId: appKitModal.selectedChain!.chainId,
deployedContract: deployedContract,
functionName: 'transfer',
transaction: Transaction(
- from: EthereumAddress.fromHex(appKitModal.session!.address!),
+ from: EthereumAddress.fromHex(
+ appKitModal.session!.getAddress(namespace)!,
+ ),
),
parameters: [
EthereumAddress.fromHex(
@@ -381,6 +437,9 @@ class EIP155 {
required ReownAppKitModal appKitModal,
required DeployedContract contract,
}) async {
+ final namespace = ReownAppKitModalNetworks.getNamespaceForChainId(
+ appKitModal.selectedChain!.chainId,
+ );
final results = await Future.wait([
// results[0]
appKitModal.requestReadContract(
@@ -403,7 +462,7 @@ class EIP155 {
deployedContract: contract,
functionName: 'balanceOf',
parameters: [
- EthereumAddress.fromHex(appKitModal.session!.address!),
+ EthereumAddress.fromHex(appKitModal.session!.getAddress(namespace)!),
],
),
// results[4]
diff --git a/packages/reown_appkit/example/modal/lib/widgets/debug_drawer.dart b/packages/reown_appkit/example/modal/lib/widgets/debug_drawer.dart
index 7db646e..c74f71a 100644
--- a/packages/reown_appkit/example/modal/lib/widgets/debug_drawer.dart
+++ b/packages/reown_appkit/example/modal/lib/widgets/debug_drawer.dart
@@ -182,7 +182,7 @@ class _DebugDrawerState extends State with WidgetsBindingObserver {
color:
ReownAppKitModalTheme.colorsOf(context).foreground100,
),
- title: const Text('Analytics On'),
+ title: const Text('Analytics'),
titleTextStyle: TextStyle(
color:
ReownAppKitModalTheme.colorsOf(context).foreground100,
@@ -203,7 +203,7 @@ class _DebugDrawerState extends State with WidgetsBindingObserver {
color:
ReownAppKitModalTheme.colorsOf(context).foreground100,
),
- title: const Text('Email Wallet On'),
+ title: const Text('Email & Socials'),
titleTextStyle: TextStyle(
color:
ReownAppKitModalTheme.colorsOf(context).foreground100,
@@ -224,7 +224,7 @@ class _DebugDrawerState extends State with WidgetsBindingObserver {
color:
ReownAppKitModalTheme.colorsOf(context).foreground100,
),
- title: const Text('1-CA + SIWE On'),
+ title: const Text('1-CA + SIWE'),
titleTextStyle: TextStyle(
color:
ReownAppKitModalTheme.colorsOf(context).foreground100,
diff --git a/packages/reown_appkit/example/modal/lib/widgets/logger_widget.dart b/packages/reown_appkit/example/modal/lib/widgets/logger_widget.dart
index 8bb0855..cdbd8f5 100644
--- a/packages/reown_appkit/example/modal/lib/widgets/logger_widget.dart
+++ b/packages/reown_appkit/example/modal/lib/widgets/logger_widget.dart
@@ -1,9 +1,10 @@
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
-import 'package:reown_appkit/modal/services/analytics_service/analytics_service_singleton.dart';
+import 'package:reown_appkit/reown_appkit.dart';
class DraggableCard extends StatefulWidget {
final OverlayController overlayController;
+ //
const DraggableCard({
super.key,
required this.overlayController,
@@ -19,14 +20,20 @@ class _DraggableCardState extends State {
@override
void initState() {
super.initState();
- analyticsService.instance.events.listen(_eventsListener);
+ widget.overlayController.appKitModal.appKit!.core.addLogListener(
+ _eventsListener,
+ );
}
- void _eventsListener(event) {
+ void _eventsListener(String event) {
if (!mounted) return;
+ if (!event.toString().contains('[AnalyticsService]')) return;
+ String message = event.replaceAll('[AnalyticsService] ', '');
+ message = message.replaceAll('send event 202: ', '');
+ message = message.replaceAll('info: ', '');
_logs.add(
Text(
- '=> $event',
+ '=> $message',
style: const TextStyle(
color: Colors.white,
fontSize: 12.0,
@@ -38,6 +45,9 @@ class _DraggableCardState extends State {
@override
void dispose() {
+ widget.overlayController.appKitModal.appKit!.core.removeLogListener(
+ _eventsListener,
+ );
widget.overlayController.remove();
super.dispose();
}
@@ -55,12 +65,12 @@ class _DraggableCardState extends State {
children: [
SizedBox(
width: MediaQuery.of(context).size.width,
- height: 200.0,
+ height: 300.0,
child: Row(
children: [
Expanded(
child: SizedBox(
- height: 200.0,
+ height: 300.0,
child: ListView(
reverse: true,
padding: const EdgeInsets.all(6.0),
@@ -99,7 +109,11 @@ class _DraggableCardState extends State {
}
class OverlayController extends AnimatedOverlay {
- OverlayController(super.duration);
+ OverlayController(
+ super.duration, {
+ required this.appKitModal,
+ });
+ final ReownAppKitModal appKitModal;
OverlayEntry? _entry;
final _defaultAlign = const Alignment(0.0, -30.0);
Alignment align = const Alignment(0.0, -30.0);
diff --git a/packages/reown_appkit/example/modal/lib/widgets/session_widget.dart b/packages/reown_appkit/example/modal/lib/widgets/session_widget.dart
index 10728f2..c1b5a4d 100644
--- a/packages/reown_appkit/example/modal/lib/widgets/session_widget.dart
+++ b/packages/reown_appkit/example/modal/lib/widgets/session_widget.dart
@@ -3,13 +3,14 @@ import 'dart:convert';
import 'package:fl_toast/fl_toast.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
+import 'package:reown_appkit/modal/utils/core_utils.dart';
import 'package:reown_appkit_example/utils/styles.dart';
import 'package:reown_appkit/reown_appkit.dart';
import 'package:reown_appkit_example/utils/constants.dart';
-import 'package:reown_appkit_example/services/eip155_service.dart';
+import 'package:reown_appkit_example/services/methods_service.dart';
import 'package:reown_appkit_example/widgets/method_dialog.dart';
class SessionWidget extends StatefulWidget {
@@ -38,7 +39,12 @@ class SessionWidgetState extends State {
children: [
CircleAvatar(
radius: 18.0,
- backgroundImage: NetworkImage(iconImage),
+ backgroundImage: NetworkImage(
+ iconImage,
+ headers: CoreUtils.getAPIHeaders(
+ widget.appKit.appKit!.core.projectId,
+ ),
+ ),
),
const SizedBox(width: 8.0),
],
@@ -102,15 +108,17 @@ class SessionWidgetState extends State {
),
),
Column(
- children: _buildSupportedChainsWidget(),
+ children: _buildSupportedChainsWidget(
+ widget.appKit.selectedChain!.chainId,
+ ),
),
const SizedBox(height: StyleConstants.linear8),
];
// Get current active account
- final accounts = session.getAccounts() ?? [];
final chainId = widget.appKit.selectedChain?.chainId ?? '';
final namespace = ReownAppKitModalNetworks.getNamespaceForChainId(chainId);
+ final accounts = session.getAccounts(namespace: namespace) ?? [];
final chainsNamespaces = NamespaceUtils.getChainsFromAccounts(accounts);
if (chainsNamespaces.contains('$namespace:$chainId')) {
final account = accounts.firstWhere(
@@ -165,6 +173,12 @@ class SessionWidgetState extends State {
}
Widget _buildAccountWidget(String account) {
+ final chainId = NamespaceUtils.getChainFromAccount(account);
+ // final chainMetadata = ChainDataWrapper.getChainMetadataFromChain(
+ // chainId.split(':').first,
+ // chainId.split(':').last,
+ // );
+
final List children = [
Text(
widget.appKit.selectedChain?.name ?? 'Unsupported chain',
@@ -213,7 +227,7 @@ class SessionWidgetState extends State {
),
),
]);
- children.add(_buildChainEventsTiles());
+ children.add(_buildChainEventsTiles(chainId));
return Container(
padding: const EdgeInsets.all(StyleConstants.linear8),
@@ -232,12 +246,14 @@ class SessionWidgetState extends State {
);
}
- List _buildChainMethodButtons(
- String address,
- ) {
+ List _buildChainMethodButtons(String address) {
// Add Methods
- final approvedMethods = widget.appKit.getApprovedMethods() ?? [];
- if (approvedMethods.isEmpty) {
+ final chainId = NamespaceUtils.getChainFromAccount(address);
+ final namespace = NamespaceUtils.getNamespaceFromChain(chainId);
+ final approvedMethods = widget.appKit.getApprovedMethods(
+ namespace: namespace,
+ );
+ if ((approvedMethods ?? []).isEmpty) {
return [
Text(
'No methods approved',
@@ -250,10 +266,10 @@ class SessionWidgetState extends State {
)
];
}
- final usableMethods = EIP155UIMethods.values.map((e) => e.name).toList();
+ final usableMethods = SupportedMethods.values.map((e) => e.name).toList();
//
final List children = [];
- for (final method in approvedMethods) {
+ for (final method in (approvedMethods ?? [])) {
final implemented = usableMethods.contains(method);
children.add(
Container(
@@ -264,9 +280,7 @@ class SessionWidgetState extends State {
onPressed: implemented
? () async {
widget.appKit.launchConnectedWallet();
- final future = callChainMethod(EIP155.methodFromName(
- method,
- ));
+ final future = callChainMethod(method);
MethodDialog.show(context, method, future);
}
: null,
@@ -277,6 +291,16 @@ class SessionWidgetState extends State {
);
}
+ if (namespace == 'eip155') {
+ children.addAll(_addSmartContractButtons());
+ }
+
+ return children;
+ }
+
+ List _addSmartContractButtons() {
+ final List children = [];
+
children.add(const Divider());
final onSepolia = widget.appKit.selectedChain?.chainId == '11155111';
if (!onSepolia) {
@@ -304,7 +328,7 @@ class SessionWidgetState extends State {
child: ElevatedButton(
onPressed: onSepolia
? () async {
- final future = EIP155.callTestSmartContract(
+ final future = MethodsService.callTestSmartContract(
appKitModal: widget.appKit,
action: 'read',
);
@@ -316,7 +340,7 @@ class SessionWidgetState extends State {
}
: onMainnet
? () async {
- final future = EIP155.callUSDTSmartContract(
+ final future = MethodsService.callUSDTSmartContract(
appKitModal: widget.appKit,
action: 'read',
);
@@ -341,7 +365,7 @@ class SessionWidgetState extends State {
onPressed: onSepolia
? () async {
widget.appKit.launchConnectedWallet();
- final future = EIP155.callTestSmartContract(
+ final future = MethodsService.callTestSmartContract(
appKitModal: widget.appKit,
action: 'write',
);
@@ -350,7 +374,7 @@ class SessionWidgetState extends State {
: onMainnet
? () async {
widget.appKit.launchConnectedWallet();
- final future = EIP155.callUSDTSmartContract(
+ final future = MethodsService.callUSDTSmartContract(
appKitModal: widget.appKit,
action: 'write',
);
@@ -369,7 +393,7 @@ class SessionWidgetState extends State {
return children;
}
- List _buildSupportedChainsWidget() {
+ List _buildSupportedChainsWidget(String chainId) {
List children = [];
children.addAll(
[
@@ -385,10 +409,11 @@ class SessionWidgetState extends State {
),
],
);
- final approvedChains = widget.appKit.getApprovedChains() ?? [];
+ final ns = ReownAppKitModalNetworks.getNamespaceForChainId(chainId);
+ final approvedChains = widget.appKit.getApprovedChains(namespace: ns);
children.add(
Text(
- approvedChains.join(', '),
+ (approvedChains ?? []).join(', '),
style: ReownAppKitModalTheme.getDataOf(context)
.textStyles
.small400
@@ -400,10 +425,13 @@ class SessionWidgetState extends State {
return children;
}
- Widget _buildChainEventsTiles() {
+ Widget _buildChainEventsTiles(String chainId) {
// Add Events
- final approvedEvents = widget.appKit.getApprovedEvents() ?? [];
- if (approvedEvents.isEmpty) {
+ final namespace = NamespaceUtils.getNamespaceFromChain(chainId);
+ final approvedEvents = widget.appKit.getApprovedEvents(
+ namespace: namespace,
+ );
+ if ((approvedEvents ?? []).isEmpty) {
return Text(
'No events approved',
style: ReownAppKitModalTheme.getDataOf(context)
@@ -415,7 +443,7 @@ class SessionWidgetState extends State {
);
}
final List children = [];
- for (final event in approvedEvents) {
+ for (final event in (approvedEvents ?? [])) {
children.add(
Container(
margin: const EdgeInsets.symmetric(
@@ -447,14 +475,17 @@ class SessionWidgetState extends State {
);
}
- Future callChainMethod(EIP155UIMethods method) {
+ Future callChainMethod(String method) {
final session = widget.appKit.session!;
- return EIP155.callMethod(
+ final chainId = widget.appKit.selectedChain!.chainId;
+ final namespace = ReownAppKitModalNetworks.getNamespaceForChainId(chainId);
+ final address = session.getAddress(namespace)!;
+ return MethodsService.callMethod(
appKitModal: widget.appKit,
topic: session.topic ?? '',
method: method,
chainId: widget.appKit.selectedChain!.chainId,
- address: session.address!,
+ address: address,
);
}
}
diff --git a/packages/reown_appkit/lib/appkit_modal.dart b/packages/reown_appkit/lib/appkit_modal.dart
index b9f37fb..a58eeb6 100644
--- a/packages/reown_appkit/lib/appkit_modal.dart
+++ b/packages/reown_appkit/lib/appkit_modal.dart
@@ -11,8 +11,8 @@ export 'modal/models/public/appkit_modal_models.dart';
// Theme
export 'modal/theme/public/appkit_modal_theme.dart';
-// Utils
-export 'modal/utils/public/appkit_modal_utils.dart';
+/// Utils
+export 'modal/utils/public/appkit_modal_networks_utils.dart';
// Widgets
export 'modal/widgets/public/appkit_modal_widgets.dart';
diff --git a/packages/reown_appkit/lib/modal/appkit_modal_impl.dart b/packages/reown_appkit/lib/modal/appkit_modal_impl.dart
index 8669975..2d36bbb 100644
--- a/packages/reown_appkit/lib/modal/appkit_modal_impl.dart
+++ b/packages/reown_appkit/lib/modal/appkit_modal_impl.dart
@@ -2,17 +2,25 @@ import 'dart:async';
import 'dart:convert';
import 'dart:math';
-import 'package:collection/collection.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:get_it/get_it.dart';
-import 'package:reown_appkit/modal/services/magic_service/i_magic_service.dart';
-import 'package:reown_core/store/i_store.dart';
+import 'package:reown_appkit/modal/services/analytics_service/i_analytics_service.dart';
+import 'package:reown_appkit/modal/services/explorer_service/i_explorer_service.dart';
+import 'package:reown_appkit/modal/services/network_service/i_network_service.dart';
+import 'package:reown_appkit/modal/services/siwe_service/i_siwe_service.dart';
+import 'package:reown_appkit/modal/services/toast_service/i_toast_service.dart';
+import 'package:reown_appkit/modal/services/toast_service/toast_service.dart';
+import 'package:reown_appkit/modal/services/uri_service/i_url_utils.dart';
+import 'package:reown_core/store/i_store.dart';
import 'package:reown_appkit/reown_appkit.dart';
+import 'package:reown_appkit/modal/services/blockchain_service/i_blockchain_service.dart';
+import 'package:reown_appkit/modal/services/magic_service/i_magic_service.dart';
+import 'package:reown_appkit/modal/services/toast_service/models/toast_message.dart';
+import 'package:reown_appkit/modal/services/network_service/network_service.dart';
import 'package:reown_appkit/modal/services/uri_service/launch_url_exception.dart';
import 'package:reown_appkit/modal/services/uri_service/url_utils.dart';
-import 'package:reown_appkit/modal/services/uri_service/url_utils_singleton.dart';
import 'package:reown_appkit/modal/utils/core_utils.dart';
import 'package:reown_appkit/modal/utils/platform_utils.dart';
import 'package:reown_appkit/modal/constants/key_constants.dart';
@@ -21,29 +29,22 @@ import 'package:reown_appkit/modal/pages/account_page.dart';
import 'package:reown_appkit/modal/pages/approve_magic_request_page.dart';
import 'package:reown_appkit/modal/pages/approve_siwe.dart';
import 'package:reown_appkit/modal/services/analytics_service/analytics_service.dart';
-import 'package:reown_appkit/modal/services/analytics_service/analytics_service_singleton.dart';
import 'package:reown_appkit/modal/services/analytics_service/models/analytics_event.dart';
import 'package:reown_appkit/modal/services/coinbase_service/coinbase_service.dart';
-import 'package:reown_appkit/modal/services/coinbase_service/coinbase_service_singleton.dart';
import 'package:reown_appkit/modal/services/coinbase_service/i_coinbase_service.dart';
import 'package:reown_appkit/modal/services/coinbase_service/models/coinbase_data.dart';
import 'package:reown_appkit/modal/services/coinbase_service/models/coinbase_events.dart';
import 'package:reown_appkit/modal/services/explorer_service/explorer_service.dart';
-import 'package:reown_appkit/modal/services/explorer_service/explorer_service_singleton.dart';
import 'package:reown_appkit/modal/services/explorer_service/models/redirect.dart';
import 'package:reown_appkit/modal/services/magic_service/magic_service.dart';
import 'package:reown_appkit/modal/services/magic_service/models/magic_data.dart';
import 'package:reown_appkit/modal/services/magic_service/models/magic_events.dart';
import 'package:reown_appkit/modal/services/siwe_service/siwe_service.dart';
-import 'package:reown_appkit/modal/services/siwe_service/siwe_service_singleton.dart';
import 'package:reown_appkit/modal/widgets/widget_stack/widget_stack_singleton.dart';
import 'package:reown_appkit/modal/services/blockchain_service/blockchain_service.dart';
-import 'package:reown_appkit/modal/services/blockchain_service/blockchain_service_singleton.dart';
-import 'package:reown_appkit/modal/services/network_service/network_service_singleton.dart';
import 'package:reown_appkit/modal/i_appkit_modal_impl.dart';
import 'package:reown_appkit/modal/widgets/modal_container.dart';
import 'package:reown_appkit/modal/widgets/modal_provider.dart';
-import 'package:reown_appkit/modal/services/toast_service/toast_service_singleton.dart';
/// Either a [projectId] and [metadata] must be provided or an already created [appKit].
/// optionalNamespaces is mostly not needed, if you use it, the values set here will override every optionalNamespaces set in evey chain
@@ -64,8 +65,11 @@ class ReownAppKitModal with ChangeNotifier implements IReownAppKitModal {
@override
ReownAppKitModalNetworkInfo? get selectedChain {
if (_currentSelectedChainId != null) {
+ final namespace = ReownAppKitModalNetworks.getNamespaceForChainId(
+ _currentSelectedChainId!,
+ );
return ReownAppKitModalNetworks.getNetworkById(
- CoreConstants.namespace,
+ namespace,
_currentSelectedChainId!,
);
}
@@ -129,6 +133,9 @@ class ReownAppKitModal with ChangeNotifier implements IReownAppKitModal {
late final FeaturesConfig featuresConfig;
///
+ late final Future Function()? _getBalance;
+ Completer _awaitRelayOnce = Completer();
+
ReownAppKitModal({
required BuildContext context,
IReownAppKit? appKit,
@@ -142,6 +149,7 @@ class ReownAppKitModal with ChangeNotifier implements IReownAppKitModal {
Set? featuredWalletIds,
Set? includedWalletIds,
Set? excludedWalletIds,
+ Future Function()? getBalanceFallback,
LogLevel logLevel = LogLevel.nothing,
}) {
if (appKit == null) {
@@ -160,40 +168,52 @@ class ReownAppKitModal with ChangeNotifier implements IReownAppKitModal {
this.featuresConfig = featuresConfig ?? FeaturesConfig(email: false);
_context = context;
+ _getBalance = getBalanceFallback;
_appKit = appKit ??
ReownAppKit(
- core: ReownCore(projectId: projectId!),
+ core: ReownCore(
+ projectId: projectId!,
+ logLevel: logLevel,
+ ),
metadata: metadata!,
);
_projectId = _appKit.core.projectId;
+ // TODO should be moved to init()
_setRequiredNamespaces(requiredNamespaces);
_setOptionalNamespaces(optionalNamespaces);
- uriService.instance = UriService(
- core: _appKit.core,
+ GetIt.I.registerSingletonIfAbsent(
+ () => UriService(core: _appKit.core),
);
-
- analyticsService.instance = AnalyticsService(
- core: _appKit.core,
- enableAnalytics: enableAnalytics,
- )..init().then((_) {
- analyticsService.instance.sendEvent(ModalLoadedEvent());
- });
-
- explorerService.instance = ExplorerService(
- core: _appKit.core,
- referer: _appKit.metadata.name.replaceAll(' ', ''),
- featuredWalletIds: featuredWalletIds,
- includedWalletIds: includedWalletIds,
- excludedWalletIds: excludedWalletIds,
+ GetIt.I.registerSingletonIfAbsent(
+ () => AnalyticsService(
+ core: _appKit.core,
+ enableAnalytics: enableAnalytics,
+ ),
);
-
- blockchainService.instance = BlockChainService(
- core: _appKit.core,
+ // TODO should be moved to init()
+ _analyticsService.init().then(
+ (_) => _analyticsService.sendEvent(ModalLoadedEvent()),
+ );
+ GetIt.I.registerSingletonIfAbsent(
+ () => ExplorerService(
+ core: _appKit.core,
+ referer: _appKit.metadata.name.replaceAll(' ', ''),
+ featuredWalletIds: featuredWalletIds,
+ includedWalletIds: includedWalletIds,
+ excludedWalletIds: excludedWalletIds,
+ namespaces: {..._requiredNamespaces, ..._optionalNamespaces},
+ ),
+ );
+ GetIt.I.registerSingletonIfAbsent(() => NetworkService());
+ GetIt.I.registerSingletonIfAbsent(() => ToastService());
+ GetIt.I.registerSingletonIfAbsent(
+ () => BlockChainService(
+ core: _appKit.core,
+ ),
);
-
GetIt.I.registerSingletonIfAbsent(
() => MagicService(
core: _appKit.core,
@@ -201,25 +221,37 @@ class ReownAppKitModal with ChangeNotifier implements IReownAppKitModal {
featuresConfig: this.featuresConfig,
),
);
-
- coinbaseService.instance = CoinbaseService(
- core: _appKit.core,
- metadata: _appKit.metadata,
- enabled: _initializeCoinbaseSDK,
+ GetIt.I.registerSingletonIfAbsent(
+ () => CoinbaseService(
+ core: _appKit.core,
+ metadata: _appKit.metadata,
+ enabled: _initializeCoinbaseSDK,
+ ),
);
-
- siweService.instance = SiweService(
- appKit: _appKit,
- siweConfig: siweConfig,
+ GetIt.I.registerSingletonIfAbsent(
+ () => SiweService(
+ appKit: _appKit,
+ siweConfig: siweConfig,
+ namespaces: {..._requiredNamespaces, ..._optionalNamespaces},
+ ),
);
}
+ IUriService get _uriService => GetIt.I();
+ IToastService get _toastService => GetIt.I();
+ IAnalyticsService get _analyticsService => GetIt.I();
+ IExplorerService get _explorerService => GetIt.I();
+ INetworkService get _networkService => GetIt.I();
IMagicService get _magicService => GetIt.I();
+ IBlockChainService get _blockchainService => GetIt.I();
+ ICoinbaseService get _coinbaseService => GetIt.I();
+ ISiweService get _siweService => GetIt.I();
////////* PUBLIC METHODS */////////
@override
Future dispatchEnvelope(String url) async {
+ _appKit.core.logger.d('[$runtimeType] dispatchEnvelope $url');
final envelope = ReownCoreUtils.getSearchParamFromURL(url, 'wc_ev');
if (envelope.isNotEmpty) {
await _appKit.dispatchEnvelope(url);
@@ -235,20 +267,14 @@ class ReownAppKitModal with ChangeNotifier implements IReownAppKitModal {
return false;
}
- Completer _awaitRelayOnce = Completer();
-
@override
Future init() async {
_relayConnected = false;
_awaitRelayOnce = Completer();
if (!CoreUtils.isValidProjectID(_projectId)) {
- _appKit.core.logger.e(
- '[$runtimeType] projectId $_projectId is invalid. '
- 'Please provide a valid projectId. '
- 'See ${UrlConstants.docsUrl}/appkit/flutter/core/options for details.',
- );
- return;
+ throw 'Please provide a valid projectId ($_projectId).'
+ 'See ${UrlConstants.docsUrl}/appkit/flutter/core/usage for details.';
}
if (_status == ReownAppKitModalStatus.initializing ||
_status == ReownAppKitModalStatus.initialized) {
@@ -260,10 +286,10 @@ class ReownAppKitModal with ChangeNotifier implements IReownAppKitModal {
_registerListeners();
await _appKit.init();
- await networkService.instance.init();
- await explorerService.instance.init();
- await coinbaseService.instance.init();
- await blockchainService.instance.init();
+ await _networkService.init();
+ await _explorerService.init();
+ await _coinbaseService.init();
+ await _blockchainService.init();
_currentSession = await _getStoredSession();
_currentSelectedChainId = _getStoredChainId(null);
@@ -273,7 +299,10 @@ class ReownAppKitModal with ChangeNotifier implements IReownAppKitModal {
_currentSelectedChainId ??= _currentSession!.chainId;
await _setSesionAndChainData(_currentSession!);
if (isMagic) {
- await _magicService.init();
+ final caip2Chain = ReownAppKitModalNetworks.getCaip2Chain(
+ _currentSelectedChainId!,
+ );
+ await _magicService.init(chainId: caip2Chain);
}
} else {
_magicService.init();
@@ -285,25 +314,31 @@ class ReownAppKitModal with ChangeNotifier implements IReownAppKitModal {
final wcSessions = _appKit.sessions.getAll();
// Loop through all the chain data
- final allNetworks = ReownAppKitModalNetworks.getNetworks(
- CoreConstants.namespace,
- );
+ final allNetworks = ReownAppKitModalNetworks.getAllSupportedNetworks();
for (final chain in allNetworks) {
- for (final event in EventsConstants.allEvents) {
+ final namespace = ReownAppKitModalNetworks.getNamespaceForChainId(
+ chain.chainId,
+ );
+ final requiredEvents = _requiredNamespaces[namespace]?.events ?? [];
+ final optionalEvents = _optionalNamespaces[namespace]?.events ?? [];
+ final events = [...requiredEvents, ...optionalEvents];
+ for (final event in events) {
_appKit.registerEventHandler(
- chainId: '${CoreConstants.namespace}:${chain.chainId}',
+ chainId: '$namespace:${chain.chainId}',
event: event,
);
}
}
+ _appKit.core.logger.d('[$runtimeType] wcSessions ${wcSessions.length}');
+ _appKit.core.logger
+ .d('[$runtimeType] _currentSession ${_currentSession?.toJson()}');
+
// There's a session stored
if (wcSessions.isNotEmpty) {
- await _storeSession(
- ReownAppKitModalSession(
- sessionData: wcSessions.first,
- ),
- );
+ await _storeSession(ReownAppKitModalSession(
+ sessionData: wcSessions.first,
+ ));
// session should not outlive the pairing
if (wcPairings.isEmpty) {
await disconnect();
@@ -314,7 +349,7 @@ class ReownAppKitModal with ChangeNotifier implements IReownAppKitModal {
// Check for other type of sessions stored
if (_currentSession != null) {
if (_currentSession!.sessionService.isCoinbase) {
- final isCbConnected = await coinbaseService.instance.isConnected();
+ final isCbConnected = await _coinbaseService.isConnected();
if (!isCbConnected) {
await _cleanSession();
}
@@ -335,6 +370,7 @@ class ReownAppKitModal with ChangeNotifier implements IReownAppKitModal {
await _selectChainFromStoredId();
onModalNetworkChange.subscribe(_onNetworkChainRequireSIWE);
+ onModalConnect.subscribe(_loadAccountData);
_relayConnected = _appKit.core.relayClient.isConnected;
if (!_relayConnected) {
@@ -353,11 +389,11 @@ class ReownAppKitModal with ChangeNotifier implements IReownAppKitModal {
Future _checkSIWEStatus() async {
// check if SIWE is enabled and should still sign the message
- if (siweService.instance!.enabled) {
+ if (_siweService.enabled) {
try {
// If getSession() throws it means message has not been signed and
// we should present modal with ApproveSIWEPage
- final siweSession = await siweService.instance!.getSession();
+ final siweSession = await _siweService.getSession();
final session = _currentSession!.copyWith(siweSession: siweSession);
await _setSesionAndChainData(session);
_notify();
@@ -370,16 +406,13 @@ class ReownAppKitModal with ChangeNotifier implements IReownAppKitModal {
}
}
- Future _setSesionAndChainData(ReownAppKitModalSession sData) async {
+ Future _setSesionAndChainData(ReownAppKitModalSession mSession) async {
try {
- await _storeSession(sData);
- _currentSelectedChainId = _currentSelectedChainId ?? sData.chainId;
+ await _storeSession(mSession);
+ _currentSelectedChainId = _currentSelectedChainId ?? mSession.chainId;
await _setLocalEthChain(_currentSelectedChainId!, logEvent: false);
- } catch (e, s) {
- _appKit.core.logger.d(
- '[$runtimeType] _setSesionAndChainData error $e',
- stackTrace: s,
- );
+ } catch (e) {
+ _appKit.core.logger.e('[$runtimeType] _setSesionAndChainData error $e');
}
}
@@ -387,15 +420,15 @@ class ReownAppKitModal with ChangeNotifier implements IReownAppKitModal {
try {
if (_storage.has(StorageConstants.modalSession)) {
final storedSession = _storage.get(StorageConstants.modalSession);
+ _appKit.core.logger.i(
+ '[$runtimeType] _getStoredSession, storedSession: $storedSession, key: ${StorageConstants.modalSession}',
+ );
if (storedSession != null) {
return ReownAppKitModalSession.fromMap(storedSession);
}
}
- } catch (e, s) {
- _appKit.core.logger.d(
- '[$runtimeType] _getStoredSession error: $e',
- stackTrace: s,
- );
+ } catch (e) {
+ _appKit.core.logger.e('[$runtimeType] _getStoredSession error: $e');
}
return null;
}
@@ -407,11 +440,8 @@ class ReownAppKitModal with ChangeNotifier implements IReownAppKitModal {
StorageConstants.modalSession,
_currentSession!.toMap(),
);
- } catch (e, s) {
- _appKit.core.logger.d(
- '[$runtimeType] _storeSession error: $e',
- stackTrace: s,
- );
+ } catch (e) {
+ _appKit.core.logger.e('[$runtimeType] _storeSession error: $e');
}
// _isConnected shoudl probably go at the very end of the connection
_isConnected = true;
@@ -421,8 +451,11 @@ class ReownAppKitModal with ChangeNotifier implements IReownAppKitModal {
if (_currentSession != null) {
final chainId = _getStoredChainId(null);
if (chainId != null) {
+ final namespace = ReownAppKitModalNetworks.getNamespaceForChainId(
+ chainId,
+ );
final chain = ReownAppKitModalNetworks.getNetworkById(
- CoreConstants.namespace,
+ namespace,
chainId,
);
if (chain != null) {
@@ -452,20 +485,23 @@ class ReownAppKitModal with ChangeNotifier implements IReownAppKitModal {
return;
}
- _chainBalance = null;
+ try {
+ _chainBalance = null;
+ final formattedBalance = CoreUtils.formatChainBalance(_chainBalance);
+ balanceNotifier.value = '$formattedBalance ${chainInfo.currency}';
- if (_currentSession?.sessionService.isMagic == true) {
- await _magicService.switchNetwork(chainId: chainInfo.chainId);
- // onModalNetworkChange.broadcast(ModalNetworkChange(
- // chainId: chainInfo.namespace,
- // ));
- } else {
final hasValidSession = _isConnected && _currentSession != null;
if (switchChain && hasValidSession && _currentSelectedChainId != null) {
- final approvedChains = _currentSession!.getApprovedChains() ?? [];
- final hasChainAlready = approvedChains.contains(
- '${CoreConstants.namespace}:${chainInfo.chainId}',
+ final namespace = ReownAppKitModalNetworks.getNamespaceForChainId(
+ chainInfo.chainId,
);
+ final approvedChains = _currentSession!.getApprovedChains(
+ namespace: namespace,
+ );
+ final newCaip2Chain = ReownAppKitModalNetworks.getCaip2Chain(
+ chainInfo.chainId,
+ );
+ final hasChainAlready = (approvedChains ?? []).contains(newCaip2Chain);
if (!hasChainAlready) {
requestSwitchToChain(chainInfo);
final hasSwitchMethod = _currentSession!.hasSwitchMethod();
@@ -478,6 +514,12 @@ class ReownAppKitModal with ChangeNotifier implements IReownAppKitModal {
} else {
await _setLocalEthChain(chainInfo.chainId, logEvent: logEvent);
}
+ } on JsonRpcError catch (e) {
+ onModalError.broadcast(ModalError(e.message ?? 'An error occurred'));
+ } on ReownAppKitModalException catch (e) {
+ onModalError.broadcast(ModalError(e.message));
+ } catch (e) {
+ onModalError.broadcast(ModalError('An error occurred'));
}
}
@@ -485,57 +527,80 @@ class ReownAppKitModal with ChangeNotifier implements IReownAppKitModal {
@override
List? getAvailableChains() {
// if there's no session or if supportsAddChain method then every chain can be used
- if (_currentSession == null || _currentSession!.hasSwitchMethod()) {
+ if (_currentSession == null) {
+ // meaning all chains in the list are available
return null;
}
- return getApprovedChains();
+ // Valid only for EVM chains
+ final hasSwitchMethod = _currentSession!.hasSwitchMethod();
+ if (!hasSwitchMethod) {
+ return getApprovedChains();
+ }
+
+ final isMagic = _currentSession!.sessionService.isMagic;
+ final isCoinbase = _currentSession!.sessionService.isCoinbase;
+ if (isMagic || isCoinbase) {
+ return getApprovedChains();
+ }
+
+ List availableChains = [];
+ final namespaces = ReownAppKitModalNetworks.getAllSupportedNamespaces();
+ for (var ns in namespaces) {
+ final chains =
+ ReownAppKitModalNetworks.getAllSupportedNetworks(namespace: ns)
+ .map((e) => '$ns:${e.chainId}')
+ .toList();
+ availableChains.addAll(chains);
+ }
+ if (availableChains.isEmpty) {
+ return getApprovedChains();
+ }
+
+ return availableChains;
}
/// Will get the list of already approved chains by the wallet (to switch to)
@override
- List? getApprovedChains() {
+ List? getApprovedChains({String? namespace}) {
if (_currentSession == null) {
return null;
}
- return _currentSession!.getApprovedChains();
+ return _currentSession!.getApprovedChains(namespace: namespace);
}
@override
- List? getApprovedMethods() {
+ List? getApprovedMethods({String? namespace}) {
if (_currentSession == null) {
return null;
}
- return _currentSession!.getApprovedMethods();
+ return _currentSession!.getApprovedMethods(namespace: namespace);
}
@override
- List? getApprovedEvents() {
+ List? getApprovedEvents({String? namespace}) {
if (_currentSession == null) {
return null;
}
- return _currentSession!.getApprovedEvents();
+ return _currentSession!.getApprovedEvents(namespace: namespace);
}
Future _setLocalEthChain(String chainId, {bool? logEvent}) async {
_currentSelectedChainId = chainId;
- final caip2Chain = '${CoreConstants.namespace}:$_currentSelectedChainId';
- _currentSelectedChainId = chainId;
+ final caip2Chain = ReownAppKitModalNetworks.getCaip2Chain(chainId);
+ _appKit.core.logger.d('[$runtimeType] _setLocalEthChain $caip2Chain');
_notify();
try {
if (isConnected) {
await _storage.set(
StorageConstants.selectedChainId,
- {'chainId': _currentSelectedChainId!},
+ {'chainId': _currentSelectedChainId ?? '1'},
);
}
- } catch (e, s) {
- _appKit.core.logger.d(
- '[$runtimeType] _setLocalEthChain error: $e',
- stackTrace: s,
- );
+ } catch (e) {
+ _appKit.core.logger.e('[$runtimeType] _setLocalEthChain error: $e');
}
if (_isConnected && logEvent == true) {
- analyticsService.instance.sendEvent(SwitchNetworkEvent(
+ _analyticsService.sendEvent(SwitchNetworkEvent(
network: _currentSelectedChainId!,
));
}
@@ -621,12 +686,12 @@ class ReownAppKitModal with ChangeNotifier implements IReownAppKitModal {
return;
}
- analyticsService.instance.sendEvent(ModalOpenEvent(
+ _analyticsService.sendEvent(ModalOpenEvent(
connected: _isConnected,
));
// Reset the explorer
- explorerService.instance.search(query: null);
+ _explorerService.search(query: null);
widgetStack.instance.clear();
final isBottomSheet = PlatformUtils.isBottomSheet();
@@ -720,14 +785,14 @@ class ReownAppKitModal with ChangeNotifier implements IReownAppKitModal {
name: walletName,
platform: inBrowser ? AnalyticsPlatform.web : AnalyticsPlatform.mobile,
);
- analyticsService.instance.sendEvent(event);
+ _analyticsService.sendEvent(event);
}
@override
Future connectSelectedWallet({bool inBrowser = false}) async {
_checkInitialized();
- final walletRedirect = explorerService.instance.getWalletRedirect(
+ final walletRedirect = _explorerService.getWalletRedirect(
selectedWallet,
);
@@ -744,15 +809,20 @@ class ReownAppKitModal with ChangeNotifier implements IReownAppKitModal {
}
try {
if (_selectedWallet!.isCoinbase) {
- await coinbaseService.instance.getAccount();
- await explorerService.instance.storeConnectedWallet(_selectedWallet);
+ await _coinbaseService.getAccount();
+ await _explorerService.storeConnectedWallet(_selectedWallet);
} else {
await buildConnectionUri();
- await uriService.instance.openRedirect(
- walletRedirect,
- wcURI: wcUri!,
- pType: pType,
- );
+ final linkMode = walletRedirect.linkMode ?? '';
+ if (linkMode.isNotEmpty && _wcUri.startsWith(linkMode)) {
+ await ReownCoreUtils.openURL(_wcUri);
+ } else {
+ await _uriService.openRedirect(
+ walletRedirect,
+ wcURI: _wcUri,
+ pType: pType,
+ );
+ }
}
} on LaunchUrlException catch (e) {
if (e is CanNotLaunchUrl) {
@@ -774,19 +844,19 @@ class ReownAppKitModal with ChangeNotifier implements IReownAppKitModal {
} else {
if (_isUserRejectedError(e)) {
onModalError.broadcast(UserRejectedConnection());
- analyticsService.instance.sendEvent(ConnectErrorEvent(
+ _analyticsService.sendEvent(ConnectErrorEvent(
message: 'User declined connection',
));
} else {
onModalError.broadcast(ErrorOpeningWallet());
- analyticsService.instance.sendEvent(ConnectErrorEvent(
+ _analyticsService.sendEvent(ConnectErrorEvent(
message: e.message,
));
}
}
} else if (_isUserRejectedError(e)) {
onModalError.broadcast(UserRejectedConnection());
- analyticsService.instance.sendEvent(ConnectErrorEvent(
+ _analyticsService.sendEvent(ConnectErrorEvent(
message: 'User declined connection',
));
} else {
@@ -802,27 +872,31 @@ class ReownAppKitModal with ChangeNotifier implements IReownAppKitModal {
@override
Future buildConnectionUri() async {
if (!_isConnected) {
+ /// TODO Qs: How do I handle SIWE if non-EVM chains are included?
+ /// TODO Qs: How do I handle switch to Solana from EVM chain?
try {
- if (siweService.instance!.enabled) {
- final walletRedirect = explorerService.instance.getWalletRedirect(
+ if (_siweService.enabled) {
+ final walletRedirect = _explorerService.getWalletRedirect(
selectedWallet,
);
- final nonce = await siweService.instance!.getNonce();
- final p1 = await siweService.instance!.config!.getMessageParams();
- final methods = p1.methods ?? MethodsConstants.allMethods;
+ final nonce = await _siweService.getNonce();
+ final p1 = await _siweService.config!.getMessageParams();
+ final methods =
+ p1.methods ?? NetworkUtils.defaultNetworkMethods['eip155'];
//
- final supportedNetworks = ReownAppKitModalNetworks.getNetworks(
- CoreConstants.namespace,
- );
- final chains = supportedNetworks
- .map((e) => '${CoreConstants.namespace}:${e.chainId}')
- .toList();
+ final networks = ReownAppKitModalNetworks.getAllSupportedNetworks();
+ final chains = networks.map((chain) {
+ return ReownAppKitModalNetworks.getCaip2Chain(chain.chainId);
+ }).toList();
final p2 = {'nonce': nonce, 'chains': chains, 'methods': methods};
final authParams = SessionAuthRequestParams.fromJson({
...p1.toJson(),
...p2,
});
// One-Click Auth
+ _appKit.core.logger.d(
+ '[$runtimeType] authenticate ${jsonEncode(authParams.toJson())}, ${walletRedirect?.linkMode}',
+ );
final authResponse = await _appKit.authenticate(
params: authParams,
walletUniversalLink: walletRedirect?.linkMode,
@@ -840,11 +914,8 @@ class ReownAppKitModal with ChangeNotifier implements IReownAppKitModal {
_notify();
_awaitConnectionCallback(connectResponse);
}
- } catch (e, s) {
- _appKit.core.logger.d(
- '[$runtimeType] buildConnectionUri error: $e',
- stackTrace: s,
- );
+ } catch (e) {
+ _appKit.core.logger.e('[$runtimeType] buildConnectionUri error: $e');
}
}
}
@@ -889,7 +960,7 @@ class ReownAppKitModal with ChangeNotifier implements IReownAppKitModal {
Future _connectionErrorHandler(dynamic e) async {
if (_isUserRejectedError(e)) {
onModalError.broadcast(UserRejectedConnection());
- analyticsService.instance.sendEvent(ConnectErrorEvent(
+ _analyticsService.sendEvent(ConnectErrorEvent(
message: 'User declined connection',
));
} else {
@@ -902,13 +973,13 @@ class ReownAppKitModal with ChangeNotifier implements IReownAppKitModal {
return;
}
onModalError.broadcast(ModalError('Error connecting to wallet'));
- analyticsService.instance.sendEvent(ConnectErrorEvent(
+ _analyticsService.sendEvent(ConnectErrorEvent(
message: message,
));
}
if (e is ReownSignError || e is ReownCoreError) {
onModalError.broadcast(ModalError(e.message));
- analyticsService.instance.sendEvent(ConnectErrorEvent(
+ _analyticsService.sendEvent(ConnectErrorEvent(
message: e.message,
));
}
@@ -920,7 +991,7 @@ class ReownAppKitModal with ChangeNotifier implements IReownAppKitModal {
void launchConnectedWallet() async {
_checkInitialized();
- final walletInfo = explorerService.instance.getConnectedWallet();
+ final walletInfo = _explorerService.getConnectedWallet();
if (walletInfo == null) {
// if walletInfo is null could mean that either
// 1. There's no wallet connected (shouldn't happen)
@@ -950,7 +1021,7 @@ class ReownAppKitModal with ChangeNotifier implements IReownAppKitModal {
return;
}
- final walletRedirect = explorerService.instance.getWalletRedirect(
+ final walletRedirect = _explorerService.getWalletRedirect(
walletInfo,
);
@@ -960,7 +1031,7 @@ class ReownAppKitModal with ChangeNotifier implements IReownAppKitModal {
try {
final link = metadataRedirect?.native ?? metadataRedirect?.universal;
- uriService.instance.openRedirect(
+ _uriService.openRedirect(
walletRedirect.copyWith(mobile: link),
pType: PlatformUtils.getPlatformType(),
);
@@ -985,17 +1056,20 @@ class ReownAppKitModal with ChangeNotifier implements IReownAppKitModal {
if (_currentSession?.sessionService.isCoinbase == true) {
try {
- await coinbaseService.instance.resetSession();
- } catch (_) {
+ await _coinbaseService.resetSession();
+ } catch (e) {
+ _appKit.core.logger.d('[$runtimeType] disconnect coinbase $e');
_status = ReownAppKitModalStatus.initialized;
_notify();
return;
}
}
if (_currentSession?.sessionService.isMagic == true) {
- await Future.delayed(Duration(milliseconds: 300));
- final disconnected = await _magicService.disconnect();
- if (!disconnected) {
+ try {
+ await Future.delayed(Duration(milliseconds: 300));
+ await _magicService.disconnect();
+ } catch (e) {
+ _appKit.core.logger.d('[$runtimeType] disconnect magic $e');
_status = ReownAppKitModalStatus.initialized;
_notify();
return;
@@ -1016,19 +1090,19 @@ class ReownAppKitModal with ChangeNotifier implements IReownAppKitModal {
);
}
try {
- if (siweService.instance!.signOutOnDisconnect) {
- await siweService.instance!.signOut();
+ if (_siweService.signOutOnDisconnect) {
+ await _siweService.signOut();
}
} catch (_) {}
- analyticsService.instance.sendEvent(DisconnectSuccessEvent());
+ _analyticsService.sendEvent(DisconnectSuccessEvent());
if (!(_currentSession?.sessionService.isWC == true)) {
// if sessionService.isWC then _cleanSession() is being called on sessionDelete event
return await _cleanSession();
}
return;
} catch (e) {
- analyticsService.instance.sendEvent(DisconnectErrorEvent());
+ _analyticsService.sendEvent(DisconnectErrorEvent());
_status = ReownAppKitModalStatus.initialized;
_notify();
}
@@ -1057,15 +1131,15 @@ class ReownAppKitModal with ChangeNotifier implements IReownAppKitModal {
if (_disconnectOnClose) {
_disconnectOnClose = false;
if (currentKey == KeyConstants.approveSiwePageKey) {
- analyticsService.instance.sendEvent(ClickCancelSiwe(
+ _analyticsService.sendEvent(ClickCancelSiwe(
network: _currentSelectedChainId ?? '',
));
}
await disconnect();
selectWallet(null);
}
- toastService.instance.clear();
- analyticsService.instance.sendEvent(ModalCloseEvent(
+ _toastService.clear();
+ _analyticsService.sendEvent(ModalCloseEvent(
connected: _isConnected,
));
}
@@ -1079,7 +1153,10 @@ class ReownAppKitModal with ChangeNotifier implements IReownAppKitModal {
void launchBlockExplorer() async {
if ((selectedChain?.explorerUrl ?? '').isNotEmpty) {
final blockExplorer = selectedChain!.explorerUrl;
- final address = _currentSession?.address ?? '';
+ final namespace = ReownAppKitModalNetworks.getNamespaceForChainId(
+ selectedChain!.chainId,
+ );
+ final address = _currentSession?.getAddress(namespace) ?? '';
final explorerUrl = '$blockExplorer/address/$address';
await ReownCoreUtils.openURL(explorerUrl);
}
@@ -1101,7 +1178,7 @@ class ReownAppKitModal with ChangeNotifier implements IReownAppKitModal {
final isValidChainId = NamespaceUtils.isValidChainId(chainId);
if (!isValidChainId) {
if (selectedChain!.chainId == chainId) {
- reqChainId = '${CoreConstants.namespace}:$chainId';
+ reqChainId = ReownAppKitModalNetworks.getCaip2Chain(chainId);
} else {
throw Errors.getSdkError(
Errors.UNSUPPORTED_CHAINS,
@@ -1110,8 +1187,9 @@ class ReownAppKitModal with ChangeNotifier implements IReownAppKitModal {
}
}
//
- _appKit.core.logger
- .t('[$runtimeType] requestWriteContract, chainId: $reqChainId');
+ _appKit.core.logger.i(
+ '[$runtimeType] requestReadContract, chainId: $reqChainId',
+ );
final networkInfo = ReownAppKitModalNetworks.getNetworkById(
reqChainId.split(':').first,
@@ -1153,7 +1231,7 @@ class ReownAppKitModal with ChangeNotifier implements IReownAppKitModal {
final isValidChainId = NamespaceUtils.isValidChainId(chainId);
if (!isValidChainId) {
if (selectedChain!.chainId == chainId) {
- reqChainId = '${CoreConstants.namespace}:$chainId';
+ reqChainId = ReownAppKitModalNetworks.getCaip2Chain(chainId);
} else {
throw Errors.getSdkError(
Errors.UNSUPPORTED_CHAINS,
@@ -1162,8 +1240,9 @@ class ReownAppKitModal with ChangeNotifier implements IReownAppKitModal {
}
}
//
- _appKit.core.logger
- .t('[$runtimeType] requestWriteContract, chainId: $reqChainId');
+ _appKit.core.logger.i(
+ '[$runtimeType] requestWriteContract, chainId: $reqChainId',
+ );
try {
return await _appKit.requestWriteContract(
@@ -1194,7 +1273,7 @@ class ReownAppKitModal with ChangeNotifier implements IReownAppKitModal {
final isValidChainId = NamespaceUtils.isValidChainId(chainId);
if (!isValidChainId) {
if (selectedChain!.chainId == chainId) {
- reqChainId = '${CoreConstants.namespace}:$chainId';
+ reqChainId = ReownAppKitModalNetworks.getCaip2Chain(chainId);
} else {
throw Errors.getSdkError(
Errors.UNSUPPORTED_CHAINS,
@@ -1203,7 +1282,7 @@ class ReownAppKitModal with ChangeNotifier implements IReownAppKitModal {
}
}
//
- _appKit.core.logger.t(
+ _appKit.core.logger.d(
'[$runtimeType] request, chainId: $reqChainId, '
'${jsonEncode(request.toJson())}',
);
@@ -1215,7 +1294,7 @@ class ReownAppKitModal with ChangeNotifier implements IReownAppKitModal {
);
}
if (_currentSession!.sessionService.isCoinbase) {
- return await await coinbaseService.instance.request(
+ return await await _coinbaseService.request(
chainId: switchToChainId ?? reqChainId,
request: request,
);
@@ -1248,10 +1327,20 @@ class ReownAppKitModal with ChangeNotifier implements IReownAppKitModal {
@override
Future dispose() async {
if (_status == ReownAppKitModalStatus.initialized) {
- await disconnect();
- await expirePreviousInactivePairings();
_unregisterListeners();
+ await expirePreviousInactivePairings();
+ await disconnect();
+ await _appKit.core.relayClient.disconnect();
+ _relayConnected = false;
+ _isConnected = false;
+ _currentSelectedChainId = null;
+ _requiredNamespaces = {};
+ _optionalNamespaces = {};
+ _lastChainEmitted = null;
+ _supportsOneClickAuth = false;
_status = ReownAppKitModalStatus.idle;
+ await Future.delayed(Duration(milliseconds: 500));
+ _notify();
}
super.dispose();
}
@@ -1286,8 +1375,8 @@ class ReownAppKitModal with ChangeNotifier implements IReownAppKitModal {
bool get _initializeCoinbaseSDK {
final cbId = CoinbaseService.defaultWalletData.listing.id;
- final included = (explorerService.instance.includedWalletIds ?? {});
- final excluded = (explorerService.instance.excludedWalletIds ?? {});
+ final included = (_explorerService.includedWalletIds ?? {});
+ final excluded = (_explorerService.excludedWalletIds ?? {});
if (included.isNotEmpty) {
return included.contains(cbId);
@@ -1316,13 +1405,9 @@ class ReownAppKitModal with ChangeNotifier implements IReownAppKitModal {
// Set the required namespaces to everything in our chain presets
_requiredNamespaces = {};
}
-
- final wrongNamespace = _requiredNamespaces.keys.firstWhereOrNull(
- (k) => k != CoreConstants.namespace,
+ _appKit.core.logger.d(
+ '[$runtimeType] required namespaces ${jsonEncode(_requiredNamespaces)}',
);
- if (wrongNamespace != null) {
- throw ReownAppKitModalException('Only eip155 blockains are supported');
- }
}
void _setOptionalNamespaces(Map? optionalNSpaces) {
@@ -1340,25 +1425,22 @@ class ReownAppKitModal with ChangeNotifier implements IReownAppKitModal {
);
} else {
// Set the optional namespaces to everything in our chain presets
- final namespaces = ReownAppKitModalNetworks.supported.keys;
+ final namespaces = ReownAppKitModalNetworks.getAllSupportedNamespaces();
for (var ns in namespaces) {
- final chains = ReownAppKitModalNetworks.supported[ns] ?? [];
+ final networks = ReownAppKitModalNetworks.getAllSupportedNetworks(
+ namespace: ns,
+ );
_optionalNamespaces[ns] = RequiredNamespace(
- chains: chains.map((e) => '$ns:${e.chainId}').toList(),
- methods: MethodsConstants.allMethods.toSet().toList(),
- events: EventsConstants.allEvents.toSet().toList(),
+ chains: networks.map((e) => '$ns:${e.chainId}').toList(),
+ methods: NetworkUtils.defaultNetworkMethods[ns] ?? [],
+ events: NetworkUtils.defaultNetworkEvents[ns] ?? [],
);
}
}
- final wrongNamespace = _optionalNamespaces.keys.firstWhereOrNull(
- (k) => k != CoreConstants.namespace,
+ _appKit.core.logger.d(
+ '[$runtimeType] optional namespaces ${jsonEncode(_optionalNamespaces)}',
);
- if (wrongNamespace != null) {
- throw ReownAppKitModalException(
- 'Only ${CoreConstants.namespace} networks are supported',
- );
- }
}
/// Loads account balance and avatar.
@@ -1366,62 +1448,74 @@ class ReownAppKitModal with ChangeNotifier implements IReownAppKitModal {
@override
Future loadAccountData() async {
// If there is no selected chain or session, stop. No account to load in.
- if (_currentSelectedChainId == null ||
- _currentSession == null ||
- _currentSession?.address == null) {
+ if (_currentSelectedChainId == null || _currentSession == null) {
return;
}
// Get the chain balance.
+ final namespace = ReownAppKitModalNetworks.getNamespaceForChainId(
+ _currentSelectedChainId!,
+ );
+
try {
- _chainBalance = await blockchainService.instance.rpcRequest(
- chainId: '${CoreConstants.namespace}:$_currentSelectedChainId',
- request: SessionRequestParams(
- method: 'eth_getBalance',
- params: [_currentSession!.address!, 'latest'],
- ),
+ _chainBalance = await _blockchainService.getBalance(
+ address: _currentSession!.getAddress(namespace)!,
+ namespace: namespace,
+ chainId: _currentSelectedChainId!,
);
final tokenName = selectedChain?.currency ?? '';
- balanceNotifier.value =
- '${CoreUtils.formatChainBalance(_chainBalance)} $tokenName';
- } catch (e, s) {
- _appKit.core.logger.d(
- '[$runtimeType] loadAccountData error: $e',
- stackTrace: s,
- );
+ final formattedBalance = CoreUtils.formatChainBalance(_chainBalance);
+ balanceNotifier.value = '$formattedBalance $tokenName';
+ } catch (_) {
+ // Calling getBalanceFallback defined by user
+ _chainBalance = await _getBalance?.call();
+ final tokenName = selectedChain?.currency ?? '';
+ final formattedBalance = CoreUtils.formatChainBalance(_chainBalance);
+ balanceNotifier.value = '$formattedBalance $tokenName';
}
- // Get the avatar, each chainId is just a number in string form.
- try {
- final blockchainId = await blockchainService.instance.getIdentity(
- _currentSession!.address!,
- );
- _avatarUrl = blockchainId.avatar;
- } catch (e, s) {
- _appKit.core.logger.d(
- '[$runtimeType] loadAccountData error: $e',
- stackTrace: s,
- );
+ if (namespace == NetworkUtils.eip155) {
+ // Get the avatar, each chainId is just a number in string form.
+ try {
+ final blockchainId = await _blockchainService.getIdentity(
+ _currentSession!.getAddress(namespace)!,
+ );
+ _avatarUrl = blockchainId.avatar;
+ } catch (_) {}
}
_notify();
}
@override
Future requestSwitchToChain(
- ReownAppKitModalNetworkInfo newChain) async {
+ ReownAppKitModalNetworkInfo newChain,
+ ) async {
+ final namespace = ReownAppKitModalNetworks.getNamespaceForChainId(
+ newChain.chainId,
+ );
+ if (namespace != NetworkUtils.eip155) {
+ // If chain is not EVM then there's no need to request a switch since it doesn't exist such method for non-EVM chains
+ // Therefor at this point the selected non-EVM chain is either already approved, invalidating the need of a switch call, or not approved, failing with the following error.
+ throw ReownAppKitModalException('Chain namespace is not supported');
+ }
if (_currentSession?.sessionService.isMagic == true) {
await selectChain(newChain);
return;
}
- final currentChain = '${CoreConstants.namespace}:$_currentSelectedChainId';
- final newChainId = '${CoreConstants.namespace}:${newChain.chainId}';
- _appKit.core.logger
- .i('[$runtimeType] requesting switch to chain $newChainId');
+ final currentCaip2Chain = ReownAppKitModalNetworks.getCaip2Chain(
+ _currentSelectedChainId!,
+ );
+ final newCaip2Chain = ReownAppKitModalNetworks.getCaip2Chain(
+ newChain.chainId,
+ );
+ _appKit.core.logger.i(
+ '[$runtimeType] requesting switch to chain $newCaip2Chain',
+ );
try {
await request(
topic: _currentSession?.topic ?? '',
- chainId: currentChain,
- switchToChainId: newChainId,
+ chainId: currentCaip2Chain,
+ switchToChainId: newCaip2Chain,
request: SessionRequestParams(
method: MethodsConstants.walletSwitchEthChain,
params: [
@@ -1442,9 +1536,20 @@ class ReownAppKitModal with ChangeNotifier implements IReownAppKitModal {
try {
// Otherwise it meas chain has to be added.
return await requestAddChain(newChain);
+ } on JsonRpcError catch (e) {
+ _appKit.core.logger.e(
+ '[$runtimeType] Switch to chain error: ${e.toJson()}',
+ );
+ rethrow;
+ } on ReownAppKitModalException catch (e) {
+ _appKit.core.logger.e(
+ '[$runtimeType] Switch to chain error: ${e.message}',
+ stackTrace: e.stackTrace,
+ );
+ rethrow;
} catch (e, s) {
- _appKit.core.logger.d(
- '[$runtimeType] requestSwitchToChain error: $e',
+ _appKit.core.logger.e(
+ '[$runtimeType] Switch to chain error: ${e.toString()}',
stackTrace: s,
);
rethrow;
@@ -1456,14 +1561,18 @@ class ReownAppKitModal with ChangeNotifier implements IReownAppKitModal {
@override
Future requestAddChain(ReownAppKitModalNetworkInfo newChain) async {
final topic = _currentSession?.topic ?? '';
- final chainId = '${CoreConstants.namespace}:$_currentSelectedChainId';
- final newChainId = '${CoreConstants.namespace}:${newChain.chainId}';
- _appKit.core.logger.i('[$runtimeType] requesting add chain $newChainId');
+ final currentCaip2Chain = ReownAppKitModalNetworks.getCaip2Chain(
+ _currentSelectedChainId!,
+ );
+ final newCaip2Chain = ReownAppKitModalNetworks.getCaip2Chain(
+ newChain.chainId,
+ );
+ _appKit.core.logger.i('[$runtimeType] requesting add chain $newCaip2Chain');
try {
await request(
topic: topic,
- chainId: chainId,
- switchToChainId: newChainId,
+ chainId: currentCaip2Chain,
+ switchToChainId: newCaip2Chain,
request: SessionRequestParams(
method: MethodsConstants.walletAddEthChain,
params: [newChain.toJson()],
@@ -1472,13 +1581,12 @@ class ReownAppKitModal with ChangeNotifier implements IReownAppKitModal {
_currentSelectedChainId = newChain.chainId;
await _setSesionAndChainData(_currentSession!);
return;
+ } on JsonRpcError {
+ await _setLocalEthChain(_currentSelectedChainId!);
+ rethrow;
} catch (e, s) {
- _appKit.core.logger.d(
- '[$runtimeType] requestAddChain error: $e',
- stackTrace: s,
- );
await _setLocalEthChain(_currentSelectedChainId!);
- throw JsonRpcError(code: 5002, message: 'User rejected methods.');
+ throw ReownAppKitModalException(e.toString(), s);
}
}
@@ -1510,18 +1618,24 @@ class ReownAppKitModal with ChangeNotifier implements IReownAppKitModal {
}
}
+ Future _deleteStorage() async {
+ await _storage.delete(StorageConstants.selectedChainId);
+ await _storage.delete(StorageConstants.modalSession);
+ }
+
Future _cleanSession({SessionDelete? args, bool event = true}) async {
try {
final storedWalletId = _storage.get(StorageConstants.recentWalletId);
final walletId = storedWalletId?['walletId'];
- await _storage.deleteAll();
- await explorerService.instance.storeRecentWalletId(walletId);
- } catch (_) {
- await _storage.deleteAll();
+ await _deleteStorage();
+ await _explorerService.storeRecentWalletId(walletId);
+ } catch (e, s) {
+ _appKit.core.logger.e('[$runtimeType] _cleanSession $e', stackTrace: s);
+ await _deleteStorage();
}
if (event) {
onModalDisconnect.broadcast(ModalDisconnect(
- topic: args?.topic,
+ topic: args?.topic ?? _currentSession?.topic,
id: args?.id,
));
}
@@ -1534,6 +1648,35 @@ class ReownAppKitModal with ChangeNotifier implements IReownAppKitModal {
_notify();
}
+ void _onModalError(ModalError? event) {
+ _toastService.show(ToastMessage(
+ type: ToastType.error,
+ text: event?.message ?? 'An error occurred.',
+ ));
+ }
+
+ void _onNetworkChainRequireSIWE(ModalNetworkChange? args) async {
+ if (_siweService.config?.enabled != true) return;
+ try {
+ if (_siweService.signOutOnNetworkChange) {
+ await _siweService.signOut();
+ _disconnectOnClose = true;
+ widgetStack.instance.push(ApproveSIWEPage(
+ onSiweFinish: _oneSIWEFinish,
+ ));
+ }
+ } catch (e, s) {
+ _appKit.core.logger.e(
+ '[$runtimeType] _onNetworkChainRequireSIWE error: $e',
+ stackTrace: s,
+ );
+ }
+ }
+
+ void _loadAccountData(ModalConnect? event) {
+ loadAccountData();
+ }
+
void _checkInitialized() {
if (_status != ReownAppKitModalStatus.initialized &&
_status != ReownAppKitModalStatus.initializing) {
@@ -1544,6 +1687,7 @@ class ReownAppKitModal with ChangeNotifier implements IReownAppKitModal {
}
void _registerListeners() {
+ onModalError.subscribe(_onModalError);
// Magic
_magicService.onMagicConnect.subscribe(_onMagicConnectEvent);
_magicService.onMagicLoginSuccess.subscribe(_onMagicLoginEvent);
@@ -1552,13 +1696,9 @@ class ReownAppKitModal with ChangeNotifier implements IReownAppKitModal {
_magicService.onMagicRpcRequest.subscribe(_onMagicRequest);
//
// Coinbase
- coinbaseService.instance.onCoinbaseConnect.subscribe(
- _onCoinbaseConnectEvent,
- );
- coinbaseService.instance.onCoinbaseError.subscribe(
- _onCoinbaseErrorEvent,
- );
- coinbaseService.instance.onCoinbaseSessionUpdate.subscribe(
+ _coinbaseService.onCoinbaseConnect.subscribe(_onCoinbaseConnectEvent);
+ _coinbaseService.onCoinbaseError.subscribe(_onCoinbaseErrorEvent);
+ _coinbaseService.onCoinbaseSessionUpdate.subscribe(
_onCoinbaseSessionUpdateEvent,
);
//
@@ -1580,24 +1720,9 @@ class ReownAppKitModal with ChangeNotifier implements IReownAppKitModal {
);
}
- void _onNetworkChainRequireSIWE(ModalNetworkChange? args) async {
- try {
- if (siweService.instance!.signOutOnNetworkChange) {
- await siweService.instance!.signOut();
- _disconnectOnClose = true;
- widgetStack.instance.push(ApproveSIWEPage(
- onSiweFinish: _oneSIWEFinish,
- ));
- }
- } catch (e, s) {
- _appKit.core.logger.d(
- '[$runtimeType] _onNetworkChainRequireSIWE error: $e',
- stackTrace: s,
- );
- }
- }
-
void _unregisterListeners() {
+ onModalError.unsubscribe(_onModalError);
+
// Magic
_magicService.onMagicLoginSuccess.unsubscribe(_onMagicLoginEvent);
_magicService.onMagicError.unsubscribe(_onMagicErrorEvent);
@@ -1605,13 +1730,9 @@ class ReownAppKitModal with ChangeNotifier implements IReownAppKitModal {
_magicService.onMagicRpcRequest.unsubscribe(_onMagicRequest);
//
// Coinbase
- coinbaseService.instance.onCoinbaseConnect.unsubscribe(
- _onCoinbaseConnectEvent,
- );
- coinbaseService.instance.onCoinbaseError.unsubscribe(
- _onCoinbaseErrorEvent,
- );
- coinbaseService.instance.onCoinbaseSessionUpdate.unsubscribe(
+ _coinbaseService.onCoinbaseConnect.unsubscribe(_onCoinbaseConnectEvent);
+ _coinbaseService.onCoinbaseError.unsubscribe(_onCoinbaseErrorEvent);
+ _coinbaseService.onCoinbaseSessionUpdate.unsubscribe(
_onCoinbaseSessionUpdateEvent,
);
//
@@ -1635,7 +1756,6 @@ class ReownAppKitModal with ChangeNotifier implements IReownAppKitModal {
String? _getStoredChainId(String? defaultValue) {
if (_storage.has(StorageConstants.selectedChainId)) {
final storedChain = _storage.get(StorageConstants.selectedChainId);
- debugPrint('storedChain $storedChain');
return storedChain?['chainId'] as String? ?? defaultValue;
}
return defaultValue;
@@ -1646,14 +1766,17 @@ extension _EmailConnectorExtension on ReownAppKitModal {
// Login event should be treated like Connect event for regular wallets
Future _onMagicLoginEvent(MagicLoginEvent? args) async {
if (args!.data != null) {
- final newChainId = _getStoredChainId('${args.data!.chainId}')!;
+ _appKit.core.logger.d(
+ '[$runtimeType] _onMagicLoginEvent ${args.data?.toJson()}',
+ );
+ final newChainId = _getStoredChainId(args.data!.chainId)!;
_currentSelectedChainId = newChainId;
//
final email = args.data?.email ?? _currentSession?.toRawJson()['email'];
final userName =
args.data?.userName ?? _currentSession?.toRawJson()['userName'];
final magicData = args.data?.copytWith(
- chainId: int.tryParse(newChainId),
+ chainId: newChainId,
email: email,
userName: userName,
);
@@ -1666,7 +1789,7 @@ extension _EmailConnectorExtension on ReownAppKitModal {
await _storage.delete(StorageConstants.connectedWalletData);
}
//
- if (siweService.instance!.enabled) {
+ if (_siweService.enabled) {
if (!_isOpen) {
await _checkSIWEStatus();
onModalUpdate.broadcast(ModalConnect(_currentSession!));
@@ -1688,14 +1811,18 @@ extension _EmailConnectorExtension on ReownAppKitModal {
Future _onMagicSessionUpdateEvent(MagicSessionEvent? args) async {
if (args != null) {
+ _appKit.core.logger.d(
+ '[$runtimeType] _onMagicSessionUpdateEvent ${args.toJson()}',
+ );
try {
final currentUsername = _currentSession?.userName;
final currentEmail = _currentSession?.email;
final newEmail = args.email ?? currentEmail ?? currentUsername;
final newUsername = args.userName ?? currentUsername;
final newProvider = args.provider ?? _currentSession?.socialProvider;
- final newAddress = args.address ?? _currentSession!.address!;
final newChainId = args.chainId?.toString() ?? _currentSession!.chainId;
+ final ns = ReownAppKitModalNetworks.getNamespaceForChainId(newChainId);
+ final newAddress = args.address ?? _currentSession!.getAddress(ns)!;
_currentSelectedChainId = newChainId;
//
final magicData = MagicData(
@@ -1703,7 +1830,7 @@ extension _EmailConnectorExtension on ReownAppKitModal {
address: newAddress,
userName: newUsername,
provider: newProvider,
- chainId: int.parse(newChainId),
+ chainId: newChainId,
);
final session = (_currentSession != null)
? _currentSession!.copyWith(
@@ -1715,7 +1842,7 @@ extension _EmailConnectorExtension on ReownAppKitModal {
await _setSesionAndChainData(session);
onModalUpdate.broadcast(ModalConnect(session));
} catch (e, s) {
- _appKit.core.logger.d(
+ _appKit.core.logger.e(
'[$runtimeType] _onMagicUpdateEvent error: $e',
stackTrace: s,
);
@@ -1753,6 +1880,7 @@ extension _EmailConnectorExtension on ReownAppKitModal {
extension _CoinbaseConnectorExtension on ReownAppKitModal {
void _onCoinbaseConnectEvent(CoinbaseConnectEvent? args) async {
+ _appKit.core.logger.d('[$runtimeType] _onCoinbaseConnectEvent: $args');
if (args?.data != null) {
final newChainId = _getStoredChainId('${args!.data!.chainId}')!;
_currentSelectedChainId = newChainId;
@@ -1761,7 +1889,7 @@ extension _CoinbaseConnectorExtension on ReownAppKitModal {
await _setSesionAndChainData(session);
onModalConnect.broadcast(ModalConnect(session));
//
- if (siweService.instance!.enabled) {
+ if (_siweService.enabled) {
_disconnectOnClose = true;
widgetStack.instance.push(ApproveSIWEPage(
onSiweFinish: _oneSIWEFinish,
@@ -1775,32 +1903,32 @@ extension _CoinbaseConnectorExtension on ReownAppKitModal {
}
void _onCoinbaseSessionUpdateEvent(CoinbaseSessionEvent? args) async {
+ _appKit.core.logger.d(
+ '[$runtimeType] _onCoinbaseSessionUpdateEvent: $args',
+ );
if (args != null) {
try {
- final address = args.address ?? _currentSession!.address!;
final chainId = args.chainId ?? _currentSession!.chainId;
+ final ns = ReownAppKitModalNetworks.getNamespaceForChainId(chainId);
+ final address = args.address ?? _currentSession!.getAddress(ns)!;
+ final chainInfo = ReownAppKitModalNetworks.getNetworkById(ns, chainId);
_currentSelectedChainId = chainId;
- //
- final chain = ReownAppKitModalNetworks.getNetworkById(
- CoreConstants.namespace,
- chainId,
- );
final session = _currentSession!.copyWith(
coinbaseData: CoinbaseData(
address: address,
- chainName: chain?.name ?? '',
+ chainName: chainInfo?.name ?? '',
chainId: int.parse(chainId),
- peer: coinbaseService.instance.metadata,
+ peer: _coinbaseService.metadata,
self: ConnectionMetadata(
metadata: _appKit.metadata,
- publicKey: await coinbaseService.instance.ownPublicKey,
+ publicKey: await _coinbaseService.ownPublicKey,
),
),
);
await _setSesionAndChainData(session);
onModalUpdate.broadcast(ModalConnect(session));
} catch (e, s) {
- _appKit.core.logger.d(
+ _appKit.core.logger.e(
'[$runtimeType] _onCoinbaseSessionUpdateEvent error: $e',
stackTrace: s,
);
@@ -1809,6 +1937,7 @@ extension _CoinbaseConnectorExtension on ReownAppKitModal {
}
void _onCoinbaseErrorEvent(CoinbaseErrorEvent? args) async {
+ _appKit.core.logger.d('[$runtimeType] _onCoinbaseErrorEvent: $args');
final errorMessage = args?.error ?? 'Something went wrong';
if (!errorMessage.toLowerCase().contains('user denied')) {
onModalError.broadcast(ModalError(errorMessage));
@@ -1818,6 +1947,10 @@ extension _CoinbaseConnectorExtension on ReownAppKitModal {
extension _AppKitModalExtension on ReownAppKitModal {
void _onSessionAuthResponse(SessionAuthResponse? args) async {
+ final debugString = jsonEncode(args?.toJson());
+ _appKit.core.logger.d(
+ '[$runtimeType] _onSessionAuthResponse: $debugString',
+ );
if (args?.session != null) {
// IF 1-CA SUPPORTED WE SHOULD CALL SIWECONGIF METHODS HERE
final session = await _settleSession(args!.session!);
@@ -1830,19 +1963,21 @@ extension _AppKitModalExtension on ReownAppKitModal {
cacaoPayload: CacaoRequestPayload.fromCacaoPayload(cacao.p),
);
final clientId = await _appKit.core.crypto.getClientId();
- await siweService.instance!.verifyMessage(
+ await _siweService.verifyMessage(
message: message,
signature: cacao.s.s,
clientId: clientId,
);
} catch (e, s) {
- _appKit.core.logger
- .e('[$runtimeType] onSessionAuthResponse $e', stackTrace: s);
+ _appKit.core.logger.e(
+ '[$runtimeType] onSessionAuthResponse $e',
+ stackTrace: s,
+ );
await disconnect();
return;
}
//
- final siweSession = await siweService.instance!.getSession();
+ final siweSession = await _siweService.getSession();
final newSession = session.copyWith(siweSession: siweSession);
//
await _storeSession(newSession);
@@ -1855,14 +1990,17 @@ extension _AppKitModalExtension on ReownAppKitModal {
}
void _onSessionConnect(SessionConnect? args) async {
- final siweEnabled = siweService.instance!.enabled;
- if (_supportsOneClickAuth && siweEnabled) return;
+ final debugString = jsonEncode(args?.session.toJson());
+ _appKit.core.logger.d('[$runtimeType] _onSessionConnect: $debugString');
+ if (_supportsOneClickAuth && _siweService.enabled) {
+ return;
+ }
if (args != null) {
// IF SIWE CALLBACK (1-CA NOT SUPPORTED) SIWECONGIF METHODS ARE CALLED ON ApproveSIWEPage
final session = await _settleSession(args.session);
onModalConnect.broadcast(ModalConnect(session));
//
- if (siweService.instance!.enabled) {
+ if (_siweService.enabled) {
_disconnectOnClose = true;
widgetStack.instance.push(ApproveSIWEPage(
onSiweFinish: _oneSIWEFinish,
@@ -1876,29 +2014,27 @@ extension _AppKitModalExtension on ReownAppKitModal {
}
// HAS TO BE CALLED JUST ONCE ON CONNECTION
- Future _settleSession(
- SessionData sessionData,
- ) async {
+ Future _settleSession(SessionData mSession) async {
if (_currentSelectedChainId == null) {
final chains = NamespaceUtils.getChainIdsFromNamespaces(
- namespaces: sessionData.namespaces,
- )..sort((a, b) => a.compareTo(b));
+ namespaces: mSession.namespaces,
+ );
final chainId = chains.first.split(':').last.toString();
_currentSelectedChainId = chainId;
}
- final session = ReownAppKitModalSession(sessionData: sessionData);
+ final session = ReownAppKitModalSession(sessionData: mSession);
await _setSesionAndChainData(session);
if (_selectedWallet == null) {
- analyticsService.instance.sendEvent(ConnectSuccessEvent(
+ _analyticsService.sendEvent(ConnectSuccessEvent(
name: 'WalletConnect',
method: AnalyticsPlatform.qrcode,
));
await _storage.delete(StorageConstants.recentWalletId);
await _storage.delete(StorageConstants.connectedWalletData);
} else {
- explorerService.instance.storeConnectedWallet(_selectedWallet);
+ _explorerService.storeConnectedWallet(_selectedWallet);
final walletName = _selectedWallet!.listing.name;
- analyticsService.instance.sendEvent(ConnectSuccessEvent(
+ _analyticsService.sendEvent(ConnectSuccessEvent(
name: walletName,
method: AnalyticsPlatform.mobile,
));
@@ -1907,6 +2043,9 @@ extension _AppKitModalExtension on ReownAppKitModal {
}
void _oneSIWEFinish(ReownAppKitModalSession updatedSession) async {
+ _appKit.core.logger.d(
+ '[$runtimeType] _oneSIWEFinish ${updatedSession.toJson()}',
+ );
await _storeSession(updatedSession);
try {
await _storage.set(
@@ -1914,39 +2053,41 @@ extension _AppKitModalExtension on ReownAppKitModal {
{'chainId': _currentSelectedChainId!},
);
} catch (e, s) {
- _appKit.core.logger.d(
+ _appKit.core.logger.e(
'[$runtimeType] _oneSIWEFinish error: $e',
stackTrace: s,
);
}
onModalUpdate.broadcast(ModalConnect(updatedSession));
closeModal();
- analyticsService.instance.sendEvent(SiweAuthSuccess(
+ _analyticsService.sendEvent(SiweAuthSuccess(
network: _currentSelectedChainId!,
));
}
void _onSessionEvent(SessionEvent? args) async {
+ _appKit.core.logger.d('[$runtimeType] _onSessionEvent $args');
onSessionEventEvent.broadcast(args);
if (args?.name == EventsConstants.chainChanged) {
_currentSelectedChainId = args?.data?.toString();
- } else if (args?.name == EventsConstants.accountsChanged) {
- try {
- // TODO implement account change
- if (siweService.instance!.signOutOnAccountChange) {
- await siweService.instance!.signOut();
+ }
+ if (args?.name == EventsConstants.accountsChanged) {
+ if (_siweService.enabled && _siweService.signOutOnAccountChange) {
+ try {
+ await _siweService.signOut();
+ } catch (e, s) {
+ _appKit.core.logger.e(
+ '[$runtimeType] _onSessionEvent error: $e',
+ stackTrace: s,
+ );
}
- } catch (e, s) {
- _appKit.core.logger.d(
- '[$runtimeType] _onSessionEvent error: $e',
- stackTrace: s,
- );
}
}
_notify();
}
void _onSessionUpdate(SessionUpdate? args) async {
+ _appKit.core.logger.d('[$runtimeType] _onSessionUpdate $args');
if (args != null) {
final wcSessions = _appKit.sessions.getAll();
if (wcSessions.isEmpty) return;
diff --git a/packages/reown_appkit/lib/modal/constants/string_constants.dart b/packages/reown_appkit/lib/modal/constants/string_constants.dart
index aee69eb..e29b447 100644
--- a/packages/reown_appkit/lib/modal/constants/string_constants.dart
+++ b/packages/reown_appkit/lib/modal/constants/string_constants.dart
@@ -1,14 +1,15 @@
// ignore_for_file: public_member_api_docs
import 'package:reown_appkit/reown_appkit.dart';
+import 'package:reown_core/version.dart' as reown_core;
import 'package:reown_sign/version.dart' as reown_sign;
class CoreConstants {
// Request Headers
static const X_SDK_TYPE = 'appkit';
- static const X_SDK_VERSION = packageVersion;
- static const X_CORE_SDK_VERSION = 'flutter_${reown_sign.packageVersion}';
- static const String namespace = 'eip155';
+ static const X_SDK_VERSION = 'flutter-$packageVersion';
+ static const X_CORE_SDK_VERSION = 'core-${reown_core.packageVersion}';
+ static const X_SIGN_SDK_VERSION = 'sign-${reown_sign.packageVersion}';
}
class UIConstants {
@@ -32,13 +33,12 @@ class UIConstants {
class StorageConstants {
// Storage
- static const String recentWalletId =
- '${CoreConstants.X_SDK_TYPE}_recentWallet';
- static const String connectedWalletData =
- '${CoreConstants.X_SDK_TYPE}_walletData';
- static const String selectedChainId =
- '${CoreConstants.X_SDK_TYPE}_selectedChainId';
- static const String modalSession = '${CoreConstants.X_SDK_TYPE}_session';
+ static const prefix = '${CoreConstants.X_SDK_TYPE}:$packageVersion//';
+
+ static const String recentWalletId = '${prefix}recentWallet';
+ static const String connectedWalletData = '${prefix}walletData';
+ static const String selectedChainId = '${prefix}selectedChainId';
+ static const String modalSession = '${prefix}session';
}
class UrlConstants {
diff --git a/packages/reown_appkit/lib/modal/i_appkit_modal_impl.dart b/packages/reown_appkit/lib/modal/i_appkit_modal_impl.dart
index 63e1602..d1db8e7 100644
--- a/packages/reown_appkit/lib/modal/i_appkit_modal_impl.dart
+++ b/packages/reown_appkit/lib/modal/i_appkit_modal_impl.dart
@@ -104,13 +104,13 @@ abstract class IReownAppKitModal with ChangeNotifier {
List? getAvailableChains();
/// List of approved chains by connected wallet
- List? getApprovedChains();
+ List? getApprovedChains({String? namespace});
/// List of approved methods by connected wallet
- List? getApprovedMethods();
+ List? getApprovedMethods({String? namespace});
/// List of approved events by connected wallet
- List? getApprovedEvents();
+ List? getApprovedEvents({String? namespace});
/// Loads/Refresh account balance and identity
Future loadAccountData();
diff --git a/packages/reown_appkit/lib/modal/models/public/appkit_modal_session.dart b/packages/reown_appkit/lib/modal/models/public/appkit_modal_session.dart
index 1cf2336..3a6e496 100644
--- a/packages/reown_appkit/lib/modal/models/public/appkit_modal_session.dart
+++ b/packages/reown_appkit/lib/modal/models/public/appkit_modal_session.dart
@@ -1,6 +1,6 @@
import 'package:get_it/get_it.dart';
-import 'package:reown_appkit/modal/constants/string_constants.dart';
import 'package:reown_appkit/modal/services/coinbase_service/coinbase_service.dart';
+import 'package:reown_appkit/modal/services/coinbase_service/i_coinbase_service.dart';
import 'package:reown_appkit/modal/services/coinbase_service/models/coinbase_data.dart';
import 'package:reown_appkit/modal/services/magic_service/i_magic_service.dart';
import 'package:reown_appkit/modal/services/magic_service/models/magic_data.dart';
@@ -97,78 +97,125 @@ class ReownAppKitModalSession {
return true;
}
- final nsMethods = getApprovedMethods() ?? [];
+ final nsMethods = getApprovedMethods(namespace: NetworkUtils.eip155) ?? [];
final supportsAddChain = nsMethods.contains(
MethodsConstants.walletAddEthChain,
);
return supportsAddChain;
}
- /// Get the approved methods by the connected peer
- List? getApprovedMethods() {
+ List? getApprovedMethods({String? namespace}) {
+ final methodsList = [];
+
if (sessionService.noSession) {
return null;
}
if (sessionService.isCoinbase) {
- return CoinbaseService.supportedMethods;
+ return GetIt.I().supportedMethods;
}
if (sessionService.isMagic) {
- return GetIt.I().supportedMethods;
+ final ns = namespace ?? NetworkUtils.eip155;
+ return GetIt.I().supportedMethods[ns];
}
final sessionNamespaces = _sessionData!.namespaces;
- final namespace = sessionNamespaces[CoreConstants.namespace];
- final methodsList = namespace?.methods.toSet().toList();
- return methodsList ?? [];
+ if ((namespace ?? '').isEmpty) {
+ for (var namespace in sessionNamespaces.keys) {
+ final events = sessionNamespaces[namespace]?.methods ?? [];
+ methodsList.addAll(events);
+ }
+
+ return methodsList;
+ }
+
+ return sessionNamespaces[namespace]?.methods ?? [];
}
- /// Get the approved events by the connected peer
- List? getApprovedEvents() {
+ List? getApprovedEvents({String? namespace}) {
+ final eventsList = [];
+
if (sessionService.noSession) {
return null;
}
if (sessionService.isCoinbase) {
- return [];
+ return eventsList;
}
if (sessionService.isMagic) {
- return [];
+ return eventsList;
}
final sessionNamespaces = _sessionData!.namespaces;
- final namespace = sessionNamespaces[CoreConstants.namespace];
- final eventsList = namespace?.events.toSet().toList();
- return eventsList ?? [];
+ if ((namespace ?? '').isEmpty) {
+ for (var namespace in sessionNamespaces.keys) {
+ final events = sessionNamespaces[namespace]?.events ?? [];
+ eventsList.addAll(events);
+ }
+
+ return eventsList;
+ }
+
+ return sessionNamespaces[namespace]?.events ?? [];
}
- /// Get the approved chains by the connected peer
- List? getApprovedChains() {
+ List? getApprovedChains({String? namespace}) {
if (sessionService.noSession) {
return null;
}
- // We can not know which chains are approved from Coinbase or Magic
- if (!sessionService.isWC) {
- return [chainId];
+ // Coinbase only support EIP155 but since we can not know which chains are actually approved...
+ // Magic only support EIP155 and Solana but since we can not know which chains are actually approved...
+
+ final allEIP155 = ReownAppKitModalNetworks.getAllSupportedNetworks(
+ namespace: NetworkUtils.eip155,
+ ).map((e) => '${NetworkUtils.eip155}:${e.chainId}').toList();
+
+ if (sessionService.isCoinbase) {
+ return [...allEIP155];
+ }
+
+ final allSolana = ReownAppKitModalNetworks.getAllSupportedNetworks(
+ namespace: NetworkUtils.solana,
+ ).map((e) => '${NetworkUtils.solana}:${e.chainId}').toList();
+
+ if (sessionService.isMagic) {
+ return [...allEIP155, ...allSolana];
}
- final accounts = getAccounts() ?? [];
- final approvedChains = NamespaceUtils.getChainsFromAccounts(accounts);
- return approvedChains;
+ final accounts = getAccounts(namespace: namespace) ?? [];
+ return NamespaceUtils.getChainsFromAccounts(accounts);
}
- /// Get the approved accounts by the connected peer
- List? getAccounts() {
+ List? getAccounts({String? namespace}) {
+ final accountList = [];
+
if (sessionService.noSession) {
return null;
}
+
if (sessionService.isCoinbase) {
- return ['${CoreConstants.namespace}:$chainId:$address'];
+ final ns = NetworkUtils.eip155;
+ return ReownAppKitModalNetworks.getAllSupportedNetworks(namespace: ns)
+ .map((e) => '$ns:${e.chainId}:${getAddress(ns)}')
+ .toList();
}
+
if (sessionService.isMagic) {
- return ['${CoreConstants.namespace}:$chainId:$address'];
+ final ns = namespace ?? NetworkUtils.eip155;
+ return ReownAppKitModalNetworks.getAllSupportedNetworks(namespace: ns)
+ .map((e) => '$ns:${e.chainId}:${getAddress(ns)}')
+ .toList();
}
final sessionNamespaces = _sessionData!.namespaces;
- return sessionNamespaces[CoreConstants.namespace]?.accounts ?? [];
+ if ((namespace ?? '').isEmpty) {
+ for (var namespace in sessionNamespaces.keys) {
+ final accounts = sessionNamespaces[namespace]?.accounts ?? [];
+ accountList.addAll(accounts);
+ }
+
+ return accountList;
+ }
+
+ return sessionNamespaces[namespace]?.accounts ?? [];
}
Redirect? getSessionRedirect() {
@@ -182,6 +229,10 @@ class ReownAppKitModalSession {
// toJson() would convert ReownAppKitModalSession to a SessionData kind of map
// no matter if Coinbase Wallet or Email Wallet is connected
Map toJson() {
+ if (_sessionData != null) {
+ return _sessionData!.toJson();
+ }
+
final sessionData = SessionData(
topic: topic ?? '',
pairingTopic: pairingTopic ?? '',
@@ -257,7 +308,7 @@ extension ReownAppKitModalSessionExtension on ReownAppKitModalSession {
AppKitSocialOption? get socialProvider => _magicData?.provider;
//
- String? get address {
+ String? getAddress(String namespace) {
if (sessionService.noSession) {
return null;
}
@@ -267,8 +318,8 @@ extension ReownAppKitModalSessionExtension on ReownAppKitModalSession {
if (sessionService.isMagic) {
return _magicData!.address;
}
- final namespace = namespaces?[CoreConstants.namespace];
- final accounts = namespace?.accounts ?? [];
+ final ns = namespaces?[namespace];
+ final accounts = ns?.accounts ?? [];
if (accounts.isNotEmpty) {
return NamespaceUtils.getAccount(accounts.first);
}
@@ -313,25 +364,40 @@ extension ReownAppKitModalSessionExtension on ReownAppKitModalSession {
Map? _namespaces() {
if (sessionService.isCoinbase) {
+ // Coinbase only supports eip155 chains
+ final eip155 = NetworkUtils.eip155;
+ final allEIP155 = ReownAppKitModalNetworks.getAllSupportedNetworks(
+ namespace: eip155,
+ ).map((e) => '$eip155:${e.chainId}').toList();
return {
- CoreConstants.namespace: Namespace(
- chains: ['${CoreConstants.namespace}:$chainId'],
- accounts: ['${CoreConstants.namespace}:$chainId:$address'],
- methods: [...CoinbaseService.supportedMethods],
+ eip155: Namespace(
+ chains: [...allEIP155],
+ accounts: [...getAccounts(namespace: eip155)!],
+ methods: [...GetIt.I().supportedMethods],
+ // Coinbase does not have events as it doesn't use WC protocol
events: [],
),
};
}
+
if (sessionService.isMagic) {
+ final ns = ReownAppKitModalNetworks.getNamespaceForChainId(
+ _magicData!.chainId,
+ );
+ final allChains = ReownAppKitModalNetworks.getAllSupportedNetworks(
+ namespace: ns,
+ ).map((e) => '$ns:${e.chainId}').toList();
return {
- CoreConstants.namespace: Namespace(
- chains: ['${CoreConstants.namespace}:$chainId'],
- accounts: ['${CoreConstants.namespace}:$chainId:$address'],
- methods: [...GetIt.I().supportedMethods],
+ ns: Namespace(
+ chains: [...allChains],
+ accounts: [...getAccounts(namespace: ns)!],
+ methods: [...NetworkUtils.defaultNetworkMethods[ns]!],
+ // Magic does not have events as it doesn't use WC protocol
events: [],
),
};
}
+
return namespaces;
}
diff --git a/packages/reown_appkit/lib/modal/pages/account_page.dart b/packages/reown_appkit/lib/modal/pages/account_page.dart
index 0247507..b1cf3e7 100644
--- a/packages/reown_appkit/lib/modal/pages/account_page.dart
+++ b/packages/reown_appkit/lib/modal/pages/account_page.dart
@@ -1,14 +1,16 @@
+import 'package:cached_network_image/cached_network_image.dart';
import 'package:collection/collection.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
+import 'package:get_it/get_it.dart';
import 'package:reown_appkit/modal/constants/key_constants.dart';
import 'package:reown_appkit/modal/constants/style_constants.dart';
import 'package:reown_appkit/modal/pages/edit_email_page.dart';
import 'package:reown_appkit/modal/pages/upgrade_wallet_page.dart';
import 'package:reown_appkit/modal/services/analytics_service/models/analytics_event.dart';
-import 'package:reown_appkit/modal/services/explorer_service/explorer_service_singleton.dart';
import 'package:reown_appkit/modal/i_appkit_modal_impl.dart';
+import 'package:reown_appkit/modal/services/explorer_service/i_explorer_service.dart';
import 'package:reown_appkit/modal/utils/asset_util.dart';
import 'package:reown_appkit/modal/widgets/circular_loader.dart';
import 'package:reown_appkit/modal/widgets/miscellaneous/content_loading.dart';
@@ -127,8 +129,12 @@ class _DefaultAccountView extends StatelessWidget {
),
Visibility(
visible: isEmailLogin,
- child: _EmailLoginButton(),
+ child: _EmailAndSocialLoginButton(),
),
+ // Visibility(
+ // visible: !isEmailLogin,
+ // child: _ConnectedWalletButton(),
+ // ),
const SizedBox.square(dimension: kPadding8),
_SelectNetworkButton(),
const SizedBox.square(dimension: kPadding8),
@@ -198,7 +204,7 @@ class _UpgradeWalletButton extends StatelessWidget {
}
}
-class _EmailLoginButton extends StatelessWidget {
+class _EmailAndSocialLoginButton extends StatelessWidget {
@override
Widget build(BuildContext context) {
final service = ModalProvider.of(context).instance;
@@ -208,9 +214,8 @@ class _EmailLoginButton extends StatelessWidget {
final provider = AppKitSocialOption.values.firstWhereOrNull(
(e) => e.name == service.session!.peer?.metadata.name,
);
- final title = service.session!.email.isNotEmpty
- ? service.session!.email
- : service.session!.userName;
+ final title =
+ provider != null ? service.session!.userName : service.session!.email;
return Column(
children: [
const SizedBox.square(dimension: kPadding8),
@@ -252,6 +257,61 @@ class _EmailLoginButton extends StatelessWidget {
}
}
+// ignore: unused_element
+class _ConnectedWalletButton extends StatelessWidget {
+ @override
+ Widget build(BuildContext context) {
+ final service = ModalProvider.of(context).instance;
+ final themeData = ReownAppKitModalTheme.getDataOf(context);
+ final themeColors = ReownAppKitModalTheme.colorsOf(context);
+ final radiuses = ReownAppKitModalTheme.radiusesOf(context);
+ String iconImage = '';
+ if ((service.session!.peer?.metadata.icons ?? []).isNotEmpty) {
+ iconImage = service.session!.peer?.metadata.icons.first ?? '';
+ }
+ final walletInfo = GetIt.I().getConnectedWallet();
+ return Column(
+ children: [
+ const SizedBox.square(dimension: kPadding8),
+ AccountListItem(
+ iconWidget: Padding(
+ padding: const EdgeInsets.symmetric(horizontal: 4.0),
+ child: iconImage.isEmpty
+ ? RoundedIcon(
+ assetPath: 'lib/modal/assets/icons/wallet.svg',
+ assetColor: themeColors.inverse100,
+ borderRadius: radiuses.isSquare() ? 0.0 : null,
+ )
+ : ClipRRect(
+ borderRadius: radiuses.isSquare()
+ ? BorderRadius.zero
+ : BorderRadius.circular(34),
+ child: CachedNetworkImage(
+ imageUrl: iconImage,
+ height: 34,
+ width: 34,
+ errorWidget: (context, url, error) {
+ return RoundedIcon(
+ assetPath: 'lib/modal/assets/icons/wallet.svg',
+ assetColor: themeColors.inverse100,
+ borderRadius: radiuses.isSquare() ? 0.0 : null,
+ );
+ },
+ ),
+ ),
+ ),
+ title: service.session!.peer?.metadata.name ?? 'Connected Wallet',
+ titleStyle: themeData.textStyles.paragraph500.copyWith(
+ color: themeColors.foreground100,
+ ),
+ onTap:
+ walletInfo != null ? () => service.launchConnectedWallet() : null,
+ ),
+ ],
+ );
+ }
+}
+
class _SelectNetworkButton extends StatelessWidget {
@override
Widget build(BuildContext context) {
@@ -260,7 +320,7 @@ class _SelectNetworkButton extends StatelessWidget {
final themeColors = ReownAppKitModalTheme.colorsOf(context);
final chainId = service.selectedChain?.chainId ?? '';
final imageId = ReownAppKitModalNetworks.getNetworkIconId(chainId);
- final tokenImage = explorerService.instance.getAssetImageUrl(imageId);
+ final tokenImage = GetIt.I().getAssetImageUrl(imageId);
final radiuses = ReownAppKitModalTheme.radiusesOf(context);
return AccountListItem(
iconWidget: Padding(
diff --git a/packages/reown_appkit/lib/modal/pages/approve_siwe.dart b/packages/reown_appkit/lib/modal/pages/approve_siwe.dart
index 8ad66ba..e9ac032 100644
--- a/packages/reown_appkit/lib/modal/pages/approve_siwe.dart
+++ b/packages/reown_appkit/lib/modal/pages/approve_siwe.dart
@@ -3,16 +3,16 @@ import 'dart:async';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
+import 'package:get_it/get_it.dart';
import 'package:reown_appkit/modal/constants/key_constants.dart';
-import 'package:reown_appkit/modal/constants/string_constants.dart';
-import 'package:reown_appkit/modal/services/analytics_service/analytics_service_singleton.dart';
+import 'package:reown_appkit/modal/services/analytics_service/i_analytics_service.dart';
import 'package:reown_appkit/modal/services/analytics_service/models/analytics_event.dart';
-import 'package:reown_appkit/modal/services/siwe_service/siwe_service_singleton.dart';
import 'package:reown_appkit/modal/i_appkit_modal_impl.dart';
import 'package:reown_appkit/modal/constants/style_constants.dart';
+import 'package:reown_appkit/modal/services/siwe_service/i_siwe_service.dart';
+import 'package:reown_appkit/modal/services/toast_service/i_toast_service.dart';
import 'package:reown_appkit/modal/services/toast_service/models/toast_message.dart';
-import 'package:reown_appkit/modal/services/toast_service/toast_service_singleton.dart';
import 'package:reown_appkit/modal/widgets/avatars/account_avatar.dart';
import 'package:reown_appkit/modal/widgets/buttons/primary_button.dart';
import 'package:reown_appkit/modal/widgets/buttons/secondary_button.dart';
@@ -34,6 +34,9 @@ class ApproveSIWEPage extends StatefulWidget {
}
class _ApproveSIWEPageState extends State {
+ ISiweService get _siweService => GetIt.I();
+ IAnalyticsService get _analyticsService => GetIt.I();
+
IReownAppKitModal? _appKitModal;
double _position = 0.0;
static const _duration = Duration(milliseconds: 1500);
@@ -68,32 +71,33 @@ class _ApproveSIWEPageState extends State {
void _signIn() async {
setState(() => _waitingSign = true);
try {
- final address = _appKitModal!.session!.address!;
String chainId = _appKitModal!.selectedChain?.chainId ?? '1';
- analyticsService.instance.sendEvent(ClickSignSiweMessage(
- network: chainId,
- ));
- chainId = '${CoreConstants.namespace}:$chainId';
+ final namespace = ReownAppKitModalNetworks.getNamespaceForChainId(
+ chainId,
+ );
+ final address = _appKitModal!.session!.getAddress(namespace)!;
+ _analyticsService.sendEvent(ClickSignSiweMessage(network: chainId));
+ chainId = ReownAppKitModalNetworks.getCaip2Chain(chainId);
//
- final message = await siweService.instance!.createMessage(
+ final message = await _siweService.createMessage(
chainId: chainId,
address: address,
);
//
_appKitModal!.launchConnectedWallet();
- final signature = await siweService.instance!.signMessageRequest(
+ final signature = await _siweService.signMessageRequest(
message,
session: _appKitModal!.session!,
);
//
final clientId = await _appKitModal!.appKit!.core.crypto.getClientId();
- await siweService.instance!.verifyMessage(
+ await _siweService.verifyMessage(
message: message,
signature: signature,
clientId: clientId,
);
//
- final siweSession = await siweService.instance!.getSession();
+ final siweSession = await _siweService.getSession();
final newSession =
_appKitModal!.session!.copyWith(siweSession: siweSession);
//
@@ -111,8 +115,8 @@ class _ApproveSIWEPageState extends State {
void _handleError(String? error) {
debugPrint('[$runtimeType] _handleError $error');
String chainId = _appKitModal!.selectedChain?.chainId ?? '1';
- analyticsService.instance.sendEvent(SiweAuthError(network: chainId));
- toastService.instance.show(ToastMessage(
+ _analyticsService.sendEvent(SiweAuthError(network: chainId));
+ GetIt.I().show(ToastMessage(
type: ToastType.error,
text: error ?? 'Something went wrong.',
));
diff --git a/packages/reown_appkit/lib/modal/pages/confirm_email_page.dart b/packages/reown_appkit/lib/modal/pages/confirm_email_page.dart
index e9de578..79b27c7 100644
--- a/packages/reown_appkit/lib/modal/pages/confirm_email_page.dart
+++ b/packages/reown_appkit/lib/modal/pages/confirm_email_page.dart
@@ -5,9 +5,9 @@ import 'package:reown_appkit/modal/services/magic_service/i_magic_service.dart';
import 'package:reown_appkit/modal/services/magic_service/models/email_login_step.dart';
import 'package:reown_appkit/modal/services/magic_service/models/magic_events.dart';
import 'package:reown_appkit/modal/constants/style_constants.dart';
+import 'package:reown_appkit/modal/services/toast_service/i_toast_service.dart';
import 'package:reown_appkit/modal/theme/public/appkit_modal_theme.dart';
import 'package:reown_appkit/modal/services/toast_service/models/toast_message.dart';
-import 'package:reown_appkit/modal/services/toast_service/toast_service_singleton.dart';
import 'package:reown_appkit/modal/widgets/icons/rounded_icon.dart';
import 'package:reown_appkit/modal/widgets/miscellaneous/content_loading.dart';
import 'package:reown_appkit/modal/widgets/miscellaneous/verify_otp_view.dart';
@@ -38,10 +38,6 @@ class _ConfirmEmailPageState extends State {
}
void _onMagicErrorEvent(MagicErrorEvent? event) {
- toastService.instance.show(ToastMessage(
- type: ToastType.error,
- text: event?.error ?? 'Something went wrong.',
- ));
if (event is ConnectEmailErrorEvent) {
_goBack();
} else {
@@ -108,7 +104,7 @@ class __VerifyDeviceViewState extends State<_VerifyDeviceView> {
void _resendEmail() async {
final diff = DateTime.now().difference(_resendEnabledAt).inSeconds;
if (diff < 0) {
- toastService.instance.show(ToastMessage(
+ GetIt.I().show(ToastMessage(
type: ToastType.error,
text: 'Try again after ${diff.abs()} seconds',
));
@@ -116,7 +112,7 @@ class __VerifyDeviceViewState extends State<_VerifyDeviceView> {
final email = _magicService.email.value;
await _magicService.connectEmail(value: email);
_resendEnabledAt = DateTime.now().add(Duration(seconds: 30));
- toastService.instance.show(ToastMessage(
+ GetIt.I().show(ToastMessage(
type: ToastType.success,
text: 'Link email resent',
));
diff --git a/packages/reown_appkit/lib/modal/pages/connect_wallet_page.dart b/packages/reown_appkit/lib/modal/pages/connect_wallet_page.dart
index eb5a6bf..526a510 100644
--- a/packages/reown_appkit/lib/modal/pages/connect_wallet_page.dart
+++ b/packages/reown_appkit/lib/modal/pages/connect_wallet_page.dart
@@ -2,14 +2,15 @@ import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
+import 'package:get_it/get_it.dart';
import 'package:reown_appkit/modal/constants/key_constants.dart';
-import 'package:reown_appkit/modal/services/explorer_service/explorer_service_singleton.dart';
-import 'package:reown_appkit/modal/services/siwe_service/siwe_service_singleton.dart';
+import 'package:reown_appkit/modal/services/explorer_service/i_explorer_service.dart';
import 'package:reown_appkit/modal/i_appkit_modal_impl.dart';
import 'package:reown_appkit/modal/constants/style_constants.dart';
+import 'package:reown_appkit/modal/services/siwe_service/i_siwe_service.dart';
+import 'package:reown_appkit/modal/services/toast_service/i_toast_service.dart';
import 'package:reown_appkit/modal/services/toast_service/models/toast_message.dart';
-import 'package:reown_appkit/modal/services/toast_service/toast_service_singleton.dart';
import 'package:reown_appkit/modal/widgets/icons/rounded_icon.dart';
import 'package:reown_appkit/modal/widgets/miscellaneous/content_loading.dart';
import 'package:reown_appkit/modal/widgets/miscellaneous/segmented_control.dart';
@@ -32,6 +33,9 @@ class ConnectWalletPage extends StatefulWidget {
class _ConnectWalletPageState extends State
with WidgetsBindingObserver {
+ IExplorerService get _explorerService => GetIt.I();
+ ISiweService get _siweService => GetIt.I();
+
IReownAppKitModal? _service;
SegmentOption _selectedSegment = SegmentOption.mobile;
ModalError? errorEvent;
@@ -56,7 +60,7 @@ class _ConnectWalletPageState extends State
if (state == AppLifecycleState.resumed) {
final isOpen = _service?.isOpen ?? false;
final isConnected = _service?.isConnected ?? false;
- if (isOpen && isConnected && !siweService.instance!.enabled) {
+ if (isOpen && isConnected && !_siweService.enabled) {
Future.delayed(Duration(seconds: 1), () {
if (!mounted) return;
_service?.closeModal();
@@ -88,7 +92,7 @@ class _ConnectWalletPageState extends State
kNavbarHeight -
(kPadding16 * 2);
//
- final walletRedirect = explorerService.instance.getWalletRedirect(
+ final walletRedirect = _explorerService.getWalletRedirect(
_service!.selectedWallet,
);
final webOnlyWallet = walletRedirect?.webOnly == true;
@@ -97,7 +101,7 @@ class _ConnectWalletPageState extends State
final selectedWallet = _service!.selectedWallet;
final walletName = selectedWallet?.listing.name ?? 'Wallet';
final imageId = selectedWallet?.listing.imageId ?? '';
- final imageUrl = explorerService.instance.getWalletImageUrl(imageId);
+ final imageUrl = _explorerService.getWalletImageUrl(imageId);
//
return ModalNavbar(
title: walletName,
@@ -297,9 +301,10 @@ class _ConnectWalletPageState extends State
Future _copyToClipboard(BuildContext context) async {
final service = ModalProvider.of(context).instance;
await Clipboard.setData(ClipboardData(text: service.wcUri!));
- toastService.instance.show(
- ToastMessage(type: ToastType.success, text: 'Link copied'),
- );
+ GetIt.I().show(ToastMessage(
+ type: ToastType.success,
+ text: 'Link copied',
+ ));
}
}
diff --git a/packages/reown_appkit/lib/modal/pages/connet_network_page.dart b/packages/reown_appkit/lib/modal/pages/connet_network_page.dart
index aaad1bc..e85bcc2 100644
--- a/packages/reown_appkit/lib/modal/pages/connet_network_page.dart
+++ b/packages/reown_appkit/lib/modal/pages/connet_network_page.dart
@@ -1,13 +1,14 @@
import 'dart:async';
import 'package:flutter/material.dart';
+import 'package:get_it/get_it.dart';
import 'package:reown_appkit/modal/constants/key_constants.dart';
-import 'package:reown_appkit/modal/constants/string_constants.dart';
-import 'package:reown_appkit/modal/services/explorer_service/explorer_service_singleton.dart';
-import 'package:reown_appkit/modal/services/siwe_service/siwe_service_singleton.dart';
+import 'package:reown_appkit/modal/services/explorer_service/i_explorer_service.dart';
+import 'package:reown_appkit/modal/services/magic_service/i_magic_service.dart';
import 'package:reown_appkit/modal/i_appkit_modal_impl.dart';
import 'package:reown_appkit/modal/constants/style_constants.dart';
+import 'package:reown_appkit/modal/services/siwe_service/i_siwe_service.dart';
import 'package:reown_appkit/modal/widgets/icons/rounded_icon.dart';
import 'package:reown_appkit/modal/widgets/miscellaneous/content_loading.dart';
import 'package:reown_appkit/modal/widgets/widget_stack/widget_stack_singleton.dart';
@@ -19,18 +20,21 @@ import 'package:reown_appkit/modal/widgets/navigation/navbar.dart';
import 'package:reown_appkit/reown_appkit.dart';
class ConnectNetworkPage extends StatefulWidget {
- final ReownAppKitModalNetworkInfo chainInfo;
const ConnectNetworkPage({
required this.chainInfo,
+ this.isMagic = false,
}) : super(key: KeyConstants.connecNetworkPageKey);
+ final ReownAppKitModalNetworkInfo chainInfo;
+ final bool isMagic;
+
@override
State createState() => _ConnectNetworkPageState();
}
class _ConnectNetworkPageState extends State
with WidgetsBindingObserver {
- IReownAppKitModal? _service;
+ IReownAppKitModal? _appKitModal;
ModalError? errorEvent;
@override
@@ -38,41 +42,61 @@ class _ConnectNetworkPageState extends State
super.initState();
WidgetsBinding.instance.addObserver(this);
WidgetsBinding.instance.addPostFrameCallback((_) {
- _service = ModalProvider.of(context).instance;
- _service?.onModalError.subscribe(_errorListener);
+ _appKitModal = ModalProvider.of(context).instance;
+ _appKitModal?.onModalError.subscribe(_errorListener);
setState(() {});
Future.delayed(const Duration(milliseconds: 300), () => _connect());
});
}
+ IMagicService get _magicService => GetIt.I();
+ IExplorerService get _explorerService => GetIt.I();
+ ISiweService get _siweService => GetIt.I();
+
void _connect() async {
errorEvent = null;
- _service!.launchConnectedWallet();
- try {
- await _service!.requestSwitchToChain(widget.chainInfo);
- final chainId = widget.chainInfo.chainId;
- final chainInfo = ReownAppKitModalNetworks.getNetworkById(
- CoreConstants.namespace,
- chainId,
+ if (widget.isMagic) {
+ final newCaip2Chain = ReownAppKitModalNetworks.getCaip2Chain(
+ widget.chainInfo.chainId,
);
- if (chainInfo != null) {
- Future.delayed(const Duration(milliseconds: 300), () {
- if (!siweService.instance!.enabled) {
- widgetStack.instance.pop();
- }
- });
+ await _magicService.switchNetwork(chainId: newCaip2Chain);
+ } else {
+ try {
+ _appKitModal!.launchConnectedWallet();
+ await _appKitModal!.requestSwitchToChain(widget.chainInfo);
+ final chainId = widget.chainInfo.chainId;
+ final namespace = ReownAppKitModalNetworks.getNamespaceForChainId(
+ chainId,
+ );
+ final chainInfo = ReownAppKitModalNetworks.getNetworkById(
+ namespace,
+ chainId,
+ );
+ if (chainInfo != null) {
+ Future.delayed(const Duration(milliseconds: 300), () {
+ if (!_siweService.enabled) {
+ widgetStack.instance.pop();
+ }
+ });
+ }
+ } on JsonRpcError catch (e) {
+ setState(
+ () => errorEvent = ModalError(e.message ?? 'An error occurred'),
+ );
+ } on ReownAppKitModalException catch (e) {
+ setState(() => errorEvent = ModalError(e.message));
+ } catch (e) {
+ setState(() => errorEvent = ModalError('An error occurred'));
}
- } catch (e) {
- setState(() {});
}
}
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
if (state == AppLifecycleState.resumed) {
- if (_service?.session?.sessionService.isCoinbase == true) {
- if (_service?.selectedChain?.chainId == widget.chainInfo.chainId) {
- if (!siweService.instance!.enabled) {
+ if (_appKitModal?.session?.sessionService.isCoinbase == true) {
+ if (_appKitModal?.selectedChain?.chainId == widget.chainInfo.chainId) {
+ if (!_siweService.enabled) {
widgetStack.instance.pop();
}
}
@@ -84,14 +108,14 @@ class _ConnectNetworkPageState extends State
@override
void dispose() {
- _service?.onModalError.unsubscribe(_errorListener);
+ _appKitModal?.onModalError.unsubscribe(_errorListener);
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
@override
Widget build(BuildContext context) {
- if (_service == null) {
+ if (_appKitModal == null) {
return ContentLoading();
}
final themeData = ReownAppKitModalTheme.getDataOf(context);
@@ -105,7 +129,7 @@ class _ConnectNetworkPageState extends State
//
final chainId = widget.chainInfo.chainId;
final imageId = ReownAppKitModalNetworks.getNetworkIconId(chainId);
- final imageUrl = explorerService.instance.getAssetImageUrl(imageId);
+ final imageUrl = _explorerService.getAssetImageUrl(imageId);
//
return ModalNavbar(
title: widget.chainInfo.name,
@@ -138,14 +162,16 @@ class _ConnectNetworkPageState extends State
const SizedBox.square(dimension: 20.0),
errorEvent != null
? Text(
- 'Switch declined',
+ errorEvent?.message ?? 'Switch declined',
textAlign: TextAlign.center,
style: themeData.textStyles.paragraph500.copyWith(
color: themeColors.error100,
),
)
: Text(
- 'Continue in ${_service?.session?.peer?.metadata.name ?? 'wallet'}',
+ widget.isMagic
+ ? 'Switching to ${widget.chainInfo.name}'
+ : 'Continue in ${_appKitModal?.session?.peer?.metadata.name ?? 'wallet'}',
textAlign: TextAlign.center,
style: themeData.textStyles.paragraph500.copyWith(
color: themeColors.foreground100,
@@ -154,14 +180,16 @@ class _ConnectNetworkPageState extends State
const SizedBox.square(dimension: 8.0),
errorEvent != null
? Text(
- 'Switch can be declined by the user or if a previous request is still active',
+ 'Switch can be declined by the user or if the wallet doesn\'t support the selected chain.',
textAlign: TextAlign.center,
style: themeData.textStyles.small500.copyWith(
color: themeColors.foreground200,
),
)
: Text(
- 'Accept switch request in your wallet',
+ widget.isMagic
+ ? 'Wait until it\'s completed'
+ : 'Accept switch request in your wallet',
textAlign: TextAlign.center,
style: themeData.textStyles.small500.copyWith(
color: themeColors.foreground200,
diff --git a/packages/reown_appkit/lib/modal/pages/edit_email_page.dart b/packages/reown_appkit/lib/modal/pages/edit_email_page.dart
index 8d54bea..4204001 100644
--- a/packages/reown_appkit/lib/modal/pages/edit_email_page.dart
+++ b/packages/reown_appkit/lib/modal/pages/edit_email_page.dart
@@ -7,8 +7,6 @@ import 'package:reown_appkit/modal/services/magic_service/models/email_login_ste
import 'package:reown_appkit/modal/services/magic_service/models/magic_events.dart';
import 'package:reown_appkit/modal/constants/style_constants.dart';
import 'package:reown_appkit/modal/utils/core_utils.dart';
-import 'package:reown_appkit/modal/services/toast_service/models/toast_message.dart';
-import 'package:reown_appkit/modal/services/toast_service/toast_service_singleton.dart';
import 'package:reown_appkit/modal/widgets/buttons/primary_button.dart';
import 'package:reown_appkit/modal/widgets/buttons/secondary_button.dart';
import 'package:reown_appkit/modal/widgets/miscellaneous/content_loading.dart';
@@ -48,10 +46,6 @@ class _EditEmailPageState extends State {
}
void _onMagicErrorEvent(MagicErrorEvent? event) {
- toastService.instance.show(ToastMessage(
- type: ToastType.error,
- text: event?.error ?? 'An error occurred.',
- ));
setState(() {});
}
diff --git a/packages/reown_appkit/lib/modal/pages/farcaster_qrcode_page.dart b/packages/reown_appkit/lib/modal/pages/farcaster_qrcode_page.dart
index 1e20b52..b59dde5 100644
--- a/packages/reown_appkit/lib/modal/pages/farcaster_qrcode_page.dart
+++ b/packages/reown_appkit/lib/modal/pages/farcaster_qrcode_page.dart
@@ -5,14 +5,10 @@ import 'package:reown_appkit/modal/widgets/widget_stack/widget_stack_singleton.d
import 'package:reown_appkit/reown_appkit.dart';
import 'package:reown_appkit/modal/constants/key_constants.dart';
-import 'package:reown_appkit/modal/i_appkit_modal_impl.dart';
import 'package:reown_appkit/modal/constants/style_constants.dart';
import 'package:reown_appkit/modal/widgets/qr_code_view.dart';
import 'package:reown_appkit/modal/widgets/miscellaneous/responsive_container.dart';
-import 'package:reown_appkit/modal/widgets/modal_provider.dart';
import 'package:reown_appkit/modal/widgets/navigation/navbar.dart';
-import 'package:reown_appkit/modal/services/toast_service/models/toast_message.dart';
-import 'package:reown_appkit/modal/services/toast_service/toast_service_singleton.dart';
import 'package:shimmer/shimmer.dart';
class FarcasterQRCodePage extends StatefulWidget {
@@ -28,15 +24,12 @@ class FarcasterQRCodePage extends StatefulWidget {
}
class _FarcasterQRCodePageState extends State {
- IReownAppKitModal? _service;
Widget? _qrQodeWidget;
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) async {
- _service = ModalProvider.of(context).instance;
- _service?.onModalError.subscribe(_onError);
_qrQodeWidget = QRCodeView(
uri: widget.farcasterUri,
logoPath: 'lib/modal/assets/png/farcaster.png',
@@ -54,22 +47,6 @@ class _FarcasterQRCodePageState extends State {
});
}
- void _onError(ModalError? args) {
- final event = args ?? ModalError('An error occurred');
- toastService.instance.show(
- ToastMessage(
- type: ToastType.error,
- text: event.message,
- ),
- );
- }
-
- @override
- void dispose() async {
- _service?.onModalError.unsubscribe(_onError);
- super.dispose();
- }
-
@override
Widget build(BuildContext context) {
final themeData = ReownAppKitModalTheme.getDataOf(context);
diff --git a/packages/reown_appkit/lib/modal/pages/public/appkit_modal_all_wallets_page.dart b/packages/reown_appkit/lib/modal/pages/public/appkit_modal_all_wallets_page.dart
index 0c953f9..832fd61 100644
--- a/packages/reown_appkit/lib/modal/pages/public/appkit_modal_all_wallets_page.dart
+++ b/packages/reown_appkit/lib/modal/pages/public/appkit_modal_all_wallets_page.dart
@@ -1,11 +1,12 @@
import 'dart:math';
import 'package:flutter/material.dart';
+import 'package:get_it/get_it.dart';
import 'package:reown_appkit/modal/constants/key_constants.dart';
import 'package:reown_appkit/modal/pages/connect_wallet_page.dart';
-import 'package:reown_appkit/modal/services/explorer_service/explorer_service_singleton.dart';
import 'package:reown_appkit/modal/constants/style_constants.dart';
+import 'package:reown_appkit/modal/services/explorer_service/i_explorer_service.dart';
import 'package:reown_appkit/modal/widgets/widget_stack/widget_stack_singleton.dart';
import 'package:reown_appkit/modal/widgets/miscellaneous/responsive_container.dart';
import 'package:reown_appkit/modal/widgets/modal_provider.dart';
@@ -25,6 +26,7 @@ class ReownAppKitModalAllWalletsPage extends StatefulWidget {
class _AppKitModalAllWalletsPageState
extends State