From b7fc12da0ad2a622747d5bf46089cdf154d29756 Mon Sep 17 00:00:00 2001 From: Alfreedom <00tango.bromine@icloud.com> Date: Mon, 20 Jan 2025 12:35:26 +0100 Subject: [PATCH] Solana missing methods --- packages/reown_appkit/CHANGELOG.md | 2 +- .../example/base/lib/pages/connect_page.dart | 129 +++++++-------- .../base/lib/utils/crypto/helpers.dart | 151 ++++++++++++------ .../phantom_service/phantom_service.dart | 8 + packages/reown_appkit/lib/version.dart | 2 +- packages/reown_appkit/pubspec.yaml | 8 +- 6 files changed, 183 insertions(+), 117 deletions(-) diff --git a/packages/reown_appkit/CHANGELOG.md b/packages/reown_appkit/CHANGELOG.md index 129067d..1851df0 100644 --- a/packages/reown_appkit/CHANGELOG.md +++ b/packages/reown_appkit/CHANGELOG.md @@ -1,4 +1,4 @@ -## 1.4.0-beta01 +## 1.4.0-beta02 - Phantom Wallet support 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 a77d45e..6dca90e 100644 --- a/packages/reown_appkit/example/base/lib/pages/connect_page.dart +++ b/packages/reown_appkit/example/base/lib/pages/connect_page.dart @@ -129,7 +129,9 @@ class ConnectPageState extends State { ], ), const SizedBox.square(dimension: 8.0), - ...(_buildRequestButtons()), + _RequestButtons( + appKitModal: widget.appKitModal, + ), ], ), ), @@ -187,68 +189,6 @@ class ConnectPageState extends State { ); } - List _buildRequestButtons() { - 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!.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: FutureBuilder( - future: getParams( - method, - address, - chainInfo!, - ), - builder: (_, snapshot) { - final enabled = snapshot.data != null; - return ElevatedButton( - style: ButtonStyle( - elevation: WidgetStateProperty.all(0.0), - backgroundColor: WidgetStateProperty.all( - enabled - ? ReownAppKitModalTheme.colorsOf(context).accent080 - : ReownAppKitModalTheme.colorsOf(context) - .accenGlass010, - ), - foregroundColor: WidgetStateProperty.all( - enabled - ? Colors.white - : ReownAppKitModalTheme.colorsOf(context) - .foreground200, - ), - ), - 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() ?? - []; - } - void _onSessionConnect(SessionConnect? event) async { if (event == null) return; @@ -287,6 +227,69 @@ class ConnectPageState extends State { } } +class _RequestButtons extends StatefulWidget { + final ReownAppKitModal appKitModal; + const _RequestButtons({required this.appKitModal}); + + @override + State<_RequestButtons> createState() => __RequestButtonsState(); +} + +class __RequestButtonsState extends State<_RequestButtons> { + @override + Widget build(BuildContext context) { + final topic = widget.appKitModal.session!.topic ?? ''; + final chainId = widget.appKitModal.selectedChain!.chainId; + final namespace = ReownAppKitModalNetworks.getNamespaceForChainId(chainId); + final methods = widget.appKitModal.getApprovedMethods(namespace: namespace); + final address = widget.appKitModal.session!.getAddress(namespace)!; + final chainInfo = ReownAppKitModalNetworks.getNetworkById( + namespace, + chainId, + ); + return Column( + children: (methods ?? []).map((method) { + return Container( + height: 40.0, + width: double.infinity, + margin: const EdgeInsets.symmetric( + vertical: StyleConstants.linear8, + ), + child: ElevatedButton( + style: ButtonStyle( + elevation: WidgetStateProperty.all(0.0), + backgroundColor: WidgetStateProperty.all( + ReownAppKitModalTheme.colorsOf(context).accent080), + foregroundColor: WidgetStateProperty.all(Colors.white), + ), + onPressed: () async { + final params = await getParams(method, address, chainInfo!); + if (params?.params != null) { + widget.appKitModal.launchConnectedWallet(); + final future = widget.appKitModal.request( + topic: topic, + chainId: chainId, + request: params!, + ); + MethodDialog.show(context, method, future); + } else { + toastification.show( + type: ToastificationType.error, + title: const Text('Method not implemented'), + context: context, + autoCloseDuration: Duration(seconds: 2), + alignment: Alignment.bottomCenter, + ); + } + }, + child: Text(method), + ), + ); + }).toList(), + ); + } +} + class _FooterWidget extends StatefulWidget { const _FooterWidget({required this.appKitModal}); final ReownAppKitModal appKitModal; 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 14e4bd0..49e49b2 100644 --- a/packages/reown_appkit/example/base/lib/utils/crypto/helpers.dart +++ b/packages/reown_appkit/example/base/lib/utils/crypto/helpers.dart @@ -7,6 +7,7 @@ import 'package:reown_appkit_dapp/utils/crypto/tron.dart'; import 'package:reown_appkit_dapp/utils/test_data.dart'; import 'package:solana_web3/solana_web3.dart' as solana; +import 'package:solana_web3/programs.dart' as programs; List getChainMethods(String namespace) { switch (namespace) { @@ -101,60 +102,40 @@ Future getParams( }, ); case 'solana_signTransaction': - // Create a connection to the devnet cluster. - final cluster = solana.Cluster.https( - Uri.parse(chainData.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), - // ), - ], - ); + case 'solana_signAndSendTransaction': + final transactionV0 = await _contructSolanaTX(address, chainData); const config = solana.TransactionSerializableConfig( verifySignatures: false, ); - final bytes = transactionv0.serialize(config).asUint8List(); + 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(), + 'pubkey': address, + 'feePayer': address, + ...transactionV0.message.toJson(), + }, + ); + case 'solana_signAllTransactions': + final transactionV0_1 = await _contructSolanaTX(address, chainData); + final transactionV0_2 = await _contructSolanaTX_2(address, chainData); + + const config = solana.TransactionSerializableConfig( + verifySignatures: false, + ); + final bytes_1 = transactionV0_1.serialize(config).asUint8List(); + final encodedV0Trx_1 = base64.encode(bytes_1); + final bytes_2 = transactionV0_2.serialize(config).asUint8List(); + final encodedV0Trx_2 = base64.encode(bytes_2); + + return SessionRequestParams( + method: method, + params: { + 'transactions': [encodedV0Trx_1, encodedV0Trx_2], }, ); case 'tron_signMessage': @@ -179,6 +160,86 @@ Future getParams( }, ); default: - return null; + return SessionRequestParams( + method: method, + params: null, + ); } } + +Future _contructSolanaTX( + String address, + ReownAppKitModalNetworkInfo chainData, +) async { + // Create a connection to the devnet cluster. + final cluster = solana.Cluster.https( + Uri.parse(chainData.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' + } + ] + }), + ], + ); + + return transactionv0; +} + +Future _contructSolanaTX_2( + String address, + ReownAppKitModalNetworkInfo chainData, +) async { + // Create a connection to the devnet cluster. + final cluster = solana.Cluster.https( + Uri.parse(chainData.rpcUrl).authority, + ); + // final cluster = solana.Cluster.devnet; + final connection = solana.Connection(cluster); + + // Fetch the latest blockhash. + final blockhash = await connection.getLatestBlockhash(); + + // Define transfer amount in lamports (1 SOL = 1,000,000,000 lamports) + // Amount to send in lamports (0.001 SOL) + final lamports = BigInt.from(1000000); + + // Create the transfer instruction + final transferInstruction = programs.SystemProgram.transfer( + fromPubkey: solana.Pubkey.fromBase58(address), + toPubkey: solana.Pubkey.fromBase58(address), + lamports: lamports, + ); + + final transactionv0 = solana.Transaction.v0( + payer: solana.Pubkey.fromBase58(address), + recentBlockhash: blockhash.blockhash, + instructions: [ + transferInstruction, + ], + ); + + return transactionv0; +} diff --git a/packages/reown_appkit/lib/modal/services/phantom_service/phantom_service.dart b/packages/reown_appkit/lib/modal/services/phantom_service/phantom_service.dart index 462989f..b4fdcab 100644 --- a/packages/reown_appkit/lib/modal/services/phantom_service/phantom_service.dart +++ b/packages/reown_appkit/lib/modal/services/phantom_service/phantom_service.dart @@ -180,6 +180,14 @@ class PhantomService implements IPhantomService { requestUri = _phantomHelper.buildSignTransactionUri( transaction: request.params['transaction'], ); + case 'solana_signAllTransactions': + requestUri = _phantomHelper.buildUriSignAllTransactions( + transactions: request.params['transactions'], + ); + case 'solana_signAndSendTransaction': + requestUri = _phantomHelper.buildSignAndSendTransactionUri( + transaction: request.params['transaction'], + ); default: throw ThirdPartyWalletException('${request.method} unimplemented'); } diff --git a/packages/reown_appkit/lib/version.dart b/packages/reown_appkit/lib/version.dart index da9e06f..cb39b2d 100644 --- a/packages/reown_appkit/lib/version.dart +++ b/packages/reown_appkit/lib/version.dart @@ -1,2 +1,2 @@ // Generated code. Do not modify. -const packageVersion = '1.4.0-beta01'; +const packageVersion = '1.4.0-beta02'; diff --git a/packages/reown_appkit/pubspec.yaml b/packages/reown_appkit/pubspec.yaml index dd576be..d0926c2 100644 --- a/packages/reown_appkit/pubspec.yaml +++ b/packages/reown_appkit/pubspec.yaml @@ -1,6 +1,6 @@ name: reown_appkit description: "Reown is the onchain UX platform that provides toolkits built on top of the WalletConnect Network" -version: 1.4.0-beta01 +version: 1.4.0-beta02 homepage: https://github.com/reown-com/reown_flutter repository: https://github.com/reown-com/reown_flutter/tree/master/packages/reown_appkit documentation: https://docs.reown.com/appkit/flutter/core/installation @@ -34,17 +34,11 @@ dependencies: # reown_sign: # path: ../reown_sign/ shimmer: ^3.0.0 - # solana: ^0.31.0+1 - # solana_web3: ^0.1.3 uuid: ^4.5.1 webview_flutter: ^4.10.0 webview_flutter_android: ^4.2.0 webview_flutter_wkwebview: ^3.16.3 -# dependency_overrides: -# # because of solana_web3 on reown_appkit -# web_socket_channel: ^3.0.1 - dev_dependencies: build_runner: ^2.4.13 build_version: ^2.1.1