Skip to content

Commit

Permalink
Merge pull request #87 from reown-com/chores/solana_missing_methods
Browse files Browse the repository at this point in the history
[AppKit] Solana missing methods
  • Loading branch information
quetool authored Jan 20, 2025
2 parents 7117c7e + b7fc12d commit dfed91d
Show file tree
Hide file tree
Showing 6 changed files with 183 additions and 117 deletions.
2 changes: 1 addition & 1 deletion packages/reown_appkit/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## 1.4.0-beta01
## 1.4.0-beta02

- Phantom Wallet support

Expand Down
129 changes: 66 additions & 63 deletions packages/reown_appkit/example/base/lib/pages/connect_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,9 @@ class ConnectPageState extends State<ConnectPage> {
],
),
const SizedBox.square(dimension: 8.0),
...(_buildRequestButtons()),
_RequestButtons(
appKitModal: widget.appKitModal,
),
],
),
),
Expand Down Expand Up @@ -187,68 +189,6 @@ class ConnectPageState extends State<ConnectPage> {
);
}

List<Widget> _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<SessionRequestParams?>(
future: getParams(
method,
address,
chainInfo!,
),
builder: (_, snapshot) {
final enabled = snapshot.data != null;
return ElevatedButton(
style: ButtonStyle(
elevation: WidgetStateProperty.all(0.0),
backgroundColor: WidgetStateProperty.all<Color>(
enabled
? ReownAppKitModalTheme.colorsOf(context).accent080
: ReownAppKitModalTheme.colorsOf(context)
.accenGlass010,
),
foregroundColor: WidgetStateProperty.all<Color>(
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;

Expand Down Expand Up @@ -287,6 +227,69 @@ class ConnectPageState extends State<ConnectPage> {
}
}

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<Color>(
ReownAppKitModalTheme.colorsOf(context).accent080),
foregroundColor: WidgetStateProperty.all<Color>(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;
Expand Down
151 changes: 106 additions & 45 deletions packages/reown_appkit/example/base/lib/utils/crypto/helpers.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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<String> getChainMethods(String namespace) {
switch (namespace) {
Expand Down Expand Up @@ -101,60 +102,40 @@ Future<SessionRequestParams?> 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':
Expand All @@ -179,6 +160,86 @@ Future<SessionRequestParams?> getParams(
},
);
default:
return null;
return SessionRequestParams(
method: method,
params: null,
);
}
}

Future<solana.Transaction> _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<solana.Transaction> _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;
}
Original file line number Diff line number Diff line change
Expand Up @@ -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');
}
Expand Down
2 changes: 1 addition & 1 deletion packages/reown_appkit/lib/version.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 1 addition & 7 deletions packages/reown_appkit/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit dfed91d

Please sign in to comment.