dev
dart 204 lines 6.3 KB
Raw
1 import 'package:cake_wallet/di.dart';
2 import 'package:cake_wallet/generated/i18n.dart';
3 import 'package:cake_wallet/src/screens/wallet_connect/services/bottom_sheet_service.dart';
4 import 'package:cake_wallet/src/screens/wallet_connect/models/wc_connection_model.dart';
5 import 'package:cake_wallet/src/screens/wallet_connect/services/walletkit_service.dart';
6 import 'package:cake_wallet/src/screens/wallet_connect/widgets/wc_message_card.dart';
7 import 'package:cake_wallet/src/screens/wallet_connect/widgets/wc_signing_request_sheet.dart';
8 import 'package:cake_wallet/store/app_store.dart';
9 import 'package:cake_wallet/themes/core/custom_theme_colors.dart';
10 import 'package:flutter/material.dart';
11 import 'package:reown_walletkit/reown_walletkit.dart';
12
13 class MethodsUtils {
14 static ReownWalletKit get walletKit => getIt.get<WalletKitService>().walletKit;
15 static final bottomSheetService = getIt.get<BottomSheetService>();
16
17 static bool isSessionOwnedByWallet(SessionData? session, String walletPublicKey) {
18 if (session == null || walletPublicKey.isEmpty) {
19 return false;
20 }
21
22 final accounts = session.namespaces.values.expand((namespace) => namespace.accounts);
23
24 return accounts.any((account) => isSameAccount(account.split(":").last, walletPublicKey));
25 }
26
27 static bool isSameAccount(String a, String b) {
28 if (a.startsWith("0x") && b.startsWith("0x")) {
29 return a.toLowerCase() == b.toLowerCase();
30 }
31
32 return a == b;
33 }
34
35 static const _transactionMethods = {
36 'eth_sendTransaction',
37 'eth_signTransaction',
38 'solana_signTransaction',
39 'solana_signAllTransactions',
40 'solana_signAndSendTransaction',
41 };
42
43 static Future<bool> requestApproval(
44 String text, {
45 String? title,
46 String? method,
47 String? chainId,
48 String? address,
49 String? topic,
50 required String transportType,
51 List<WCConnectionModel> extraModels = const [],
52 VerifyContext? verifyContext,
53 }) async {
54 final appStore = getIt.get<AppStore>();
55 SessionData? session;
56 if (topic != null) {
57 session = walletKit.sessions.get(topic);
58 } else {
59 final pending = walletKit.pendingRequests.getAll();
60 session = pending.isNotEmpty ? walletKit.sessions.get(pending.last.topic) : null;
61 }
62 final dAppMetadata = session?.peer.metadata;
63
64 final isTransaction = method != null && _transactionMethods.contains(method);
65 final resolvedTitle = title ??
66 (isTransaction ? S.current.wc_approve_request_title : S.current.wc_signing_request_title);
67 final swipeLabel = isTransaction ? S.current.wc_swipe_to_approve : S.current.wc_swipe_to_sign;
68
69 final extraRows = <WCMessageRow>[];
70 if (method != null && method.isNotEmpty) {
71 extraRows.add(WCMessageRow(label: S.current.method, value: method));
72 }
73 if (chainId != null && chainId.isNotEmpty) {
74 extraRows.add(WCMessageRow(label: S.current.chain_id, value: chainId));
75 }
76 if (transportType.isNotEmpty) {
77 extraRows.add(WCMessageRow(
78 label: S.current.transport_type,
79 value: transportType.toUpperCase(),
80 ));
81 }
82 for (final model in extraModels) {
83 if (model.title == null) continue;
84 final value = model.elements?.join(', ') ?? model.text ?? '';
85 extraRows.add(WCMessageRow(label: model.title!, value: value));
86 }
87
88 final WCBottomSheetResult result = (await bottomSheetService.queueBottomSheet(
89 widget: WCSigningRequestSheet(
90 title: resolvedTitle,
91 swipeLabel: swipeLabel,
92 dappName: dAppMetadata?.name ?? '',
93 dappIconUrl:
94 (dAppMetadata?.icons.isNotEmpty ?? false) ? dAppMetadata!.icons.first : null,
95 dappSubtitle: method ?? dAppMetadata?.url ?? '',
96 message: text,
97 walletName: appStore.wallet?.name ?? '',
98 address: address ?? '',
99 verifyContext: verifyContext,
100 extraRows: extraRows,
101 ),
102 ) as WCBottomSheetResult?) ??
103 WCBottomSheetResult.reject;
104
105 return result != WCBottomSheetResult.reject;
106 }
107
108 static void handleRedirect(
109 String topic,
110 Redirect? redirect, [
111 String? error,
112 bool success = false,
113 ]) {
114 debugPrint('handleRedirect topic: $topic, redirect: $redirect, error: $error');
115 openApp(
116 topic,
117 redirect,
118 onFail: (e) => goBackModal(
119 title: success ? S.current.success : S.current.error,
120 message: error,
121 success: success,
122 ),
123 );
124 }
125
126 static void openApp(
127 String topic,
128 Redirect? redirect, {
129 int delay = 100,
130 Function(ReownSignError? error)? onFail,
131 }) async {
132 await Future.delayed(Duration(milliseconds: delay));
133 try {
134 await walletKit.redirectToDapp(
135 topic: topic,
136 redirect: redirect,
137 );
138 } on ReownSignError catch (e) {
139 onFail?.call(e);
140 }
141 }
142
143 static void goBackModal({
144 String? title,
145 String? message,
146 bool success = true,
147 }) async {
148 await bottomSheetService.queueBottomSheet(
149 closeAfter: success ? 3 : 0,
150 widget: GoBackModalWidget(
151 isSuccess: success,
152 title: title,
153 message: message,
154 ),
155 );
156 }
157 }
158
159 class GoBackModalWidget extends StatelessWidget {
160 const GoBackModalWidget({
161 required this.isSuccess,
162 this.message,
163 this.title,
164 super.key,
165 });
166
167 final bool isSuccess;
168 final String? title;
169 final String? message;
170
171 @override
172 Widget build(BuildContext context) {
173 return Container(
174 color: Theme.of(context).colorScheme.surface,
175 height: 280.0,
176 width: double.infinity,
177 padding: const EdgeInsets.all(20.0),
178 child: Column(
179 children: [
180 Icon(
181 isSuccess ? Icons.check_circle_sharp : Icons.error_outline_sharp,
182 color: isSuccess
183 ? CustomThemeColors.syncGreen
184 : Theme.of(context).colorScheme.errorContainer,
185 size: 80.0,
186 ),
187 Text(
188 title ?? S.current.connected,
189 style: Theme.of(context).textTheme.titleLarge?.copyWith(
190 fontSize: 18.0,
191 fontWeight: FontWeight.w600,
192 ),
193 ),
194 Text(
195 message ?? S.current.youCanGoBackToYourDapp,
196 style: Theme.of(context).textTheme.bodyMedium?.copyWith(
197 fontSize: 16.0,
198 ),
199 ),
200 ],
201 ),
202 );
203 }
204 }