Closed kevin-nemo74 closed 1 year ago
Hi @kevin-nemo74,
You need to add blockhash information to the transaction and serialize it with transaction.serialize().
Here's the updated section with comments trailing the added lines:
...
print('creating transaction');
final connection = web3.Connection(Cluster.devnet); // Connect to same cluster as adapter.
final blockhash = await connection.getLatestBlockhash(); // Get latest blockhash.
final transaction = web3.Transaction( // Add blockhash info to tx.
recentBlockhash: blockhash.blockhash,
lastValidBlockHeight: blockhash.lastValidBlockHeight,
feePayer: snd, // Your wallet address.
);
transaction.add(
SystemProgram.transfer(
fromPublicKey: snd,
toPublicKey: rcv,
lamports: web3.solToLamports(1),
),
);
final arr = [];
arr.add(transaction);
const config = web3.SerializeConfig(requireAllSignatures: false); // Allow wallet to sign tx.
final tt = transaction.serialize(config).getString(web3.BufferEncoding.base64); // Serialize tx to base-64.
print('creating transaction string $tt');
...
Let me know if you need anything else.
Thanks! Merigo
The snd
address also needs updating in the example.
final receivinadd = "WTuHGrE2eia5JAa3KTY2k1DkUsHua2SJDdGWadPksKE";
final sendingadd = "DuR26WphWX3o3S3kVBhNsv7gYpGXBfRwS5CXfFuZGAb1";
final rcv = web3.PublicKey.fromString(receivinadd);
final snd = web3.PublicKey.fromString(sendingadd); // Your wallet app address.
Thanks you so much for replying
i made the changes am currently testing it and am getting a failed transaction from solflare wallet and the reason is "Transaction signature verification failure" also the snd address is the same as my wallet public key (address) i had to type it manually because when i access it from the adapter it gives a totally random address i have no idea why here s the updated code that give me the verification failure `` final receivinadd = "WTuHGrE2eia5JAa3KTY2k1DkUsHua2SJDdGWadPksKE"; final sendingadd = "DuR26WphWX3o3S3kVBhNsv7gYpGXBfRwS5CXfFuZGAb1"; final rcv = web3.PublicKey.fromString(receivinadd); final snd = web3.PublicKey.fromString(receivinadd);
print('creating transaction');
final connection = web3.Connection(
Cluster.devnet); // Connect to same cluster as adapter.
final blockhash = await connection
.getLatestBlockhash(); // Get latest blockhash.
final transaction = web3.Transaction(
// Add blockhash info to tx.
recentBlockhash: blockhash.blockhash,
lastValidBlockHeight: blockhash.lastValidBlockHeight,
feePayer: snd, // Your wallet address.
);
transaction.add(
SystemProgram.transfer(
fromPublicKey: snd,
toPublicKey: rcv,
lamports: web3.solToLamports(1),
),
);
final arr = [];
arr.add(transaction);
const config = web3.SerializeConfig(
requireAllSignatures: false); // Allow wallet to sign tx.
final tt = transaction.serialize(config).getString(
web3.BufferEncoding.base64); // Serialize tx to base-64.
print('creating transaction string $tt');
await adapter.signAndSendTransactions(transactions: [tt]);
print('tried sending transaction');
``
Thanks again
Also before the failure message it shows that it failed to simulate transaction
Thanks!
@merigo-labs can you check the code to see if am doin anything wrong ! am using this package and the documentations dont offer anything useful Thanks
Hi @kevin-nemo74,
The mobile adapter returns the address in base-64 format (as defined by the specification).
Make sure Solflare is connected to Devnet (Settings > General > Network).
Here's a complete example:
import 'package:flutter/material.dart';
import 'package:solana_wallet_adapter/solana_wallet_adapter.dart';
import 'package:solana_web3/solana_web3.dart' as web3;
import 'package:solana_web3/programs/system.dart';
void main() {
runApp(const MaterialApp(
home: AuthorizeButton(),
));
}
/// 1. Get the cluster.
final Cluster cluster = Cluster.devnet;
/// 2. Create instance of [SolanaWalletAdapter] for [cluster].
final adapter = SolanaWalletAdapter(
const AppIdentity(),
cluster: cluster,
);
/// 3. Create a connection to [cluster].
final connection = web3.Connection(
cluster,
);
class AuthorizeButton extends StatefulWidget {
const AuthorizeButton({super.key});
@override
State createState() => _AuthorizeButtonState();
}
class _AuthorizeButtonState extends State {
Object? out;
Future<void> _authorize() async {
try {
final result = await adapter.authorize();
out = result.toJson();
} catch (error) {
out = error;
} finally {
setState(() {});
}
}
Future<void> _signAndSendTransaction() async {
try {
final connectedAccount = adapter.connectedAccount?.address;
if (connectedAccount == null) throw Exception('Connect wallet before sending tx.');
// Mobile wallet displays the address as base-58.
final rcv = web3.PublicKey.fromBase58("WTuHGrE2eia5JAa3KTY2k1DkUsHua2SJDdGWadPksKE");
// Mobile wallet adapter specification returns address as base-64
final snd = web3.PublicKey.fromBase64(connectedAccount);
// final snd = web3.PublicKey.fromBase58("DuR26WphWX3o3S3kVBhNsv7gYpGXBfRwS5CXfFuZGAb1");
print('creating transaction');
// Get latest blockhash info.
final blockhash = await connection.getLatestBlockhash(); // Get latest blockhash.
// Create transfer tx.
final transaction = web3.Transaction(
feePayer: snd, // The account that will sign the tx (and pay any fees).
recentBlockhash: blockhash.blockhash,
lastValidBlockHeight: blockhash.lastValidBlockHeight,
instructions: [
SystemProgram.transfer(
fromPublicKey: snd,
toPublicKey: rcv,
lamports: web3.solToLamports(1),
),
],
);
// Serialize tx.
const config = web3.SerializeConfig(requireAllSignatures: false);
final tt = transaction.serialize(config).getString(web3.BufferEncoding.base64);
print('creating transaction string $tt');
// Sign and send tx.
final result = await adapter.signAndSendTransactions(transactions: [tt]);
setState(() => out = result.toJson());
// Wait for confirmation.
await connection.confirmTransaction(base64ToBase58(result.signatures.first!));
print('transaction success ${result.signatures.first}');
} catch (error) {
print('error sending tx $error');
}
}
@override
Widget build(final BuildContext context) {
return Scaffold(
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
TextButton(
onPressed: adapter.isAuthorized ? null : _authorize,
child: const Text('Authorize'),
),
TextButton(
onPressed: adapter.isAuthorized ? _signAndSendTransaction : null,
child: const Text('Send'),
),
if (out != null) Text(out.toString()),
],
),
);
}
}
Will look to provide better docs very soon!
Thanks Merigo
@merigo-labs Thank you so much ! it worked
I tried running the exact same code and got the following error when I tried to transact using Solflare
W/FlutterJNI(31006): Tried to send a platform message response, but FlutterJNI was detached from native C++. Could not send. Response ID: 90
W/FlutterJNI(31006): Tried to send a platform message response, but FlutterJNI was detached from native C++. Could not send. Response ID: 91
W/FlutterJNI(31006): Tried to send a platform message response, but FlutterJNI was detached from native C++. Could not send. Response ID: 93
W/FlutterJNI(31006): Tried to send a platform message response, but FlutterJNI was detached from native C++. Could not send. Response ID: 94
E/flutter (31006): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: MissingPluginException(No implementation found for method callAsyncJavaScript on channel com.pichillilorenzo/flutter_inappwebview_122212122589139161956711721439613127213153)
E/flutter (31006): #0 MethodChannel._invokeMethod (package:flutter/src/services/platform_channel.dart:294)
E/flutter (31006): <asynchronous suspension>
E/flutter (31006): #1 InAppWebViewController.callAsyncJavaScript (package:flutter_inappwebview/src/in_app_webview/in_app_webview_controller.dart:2300)
E/flutter (31006): <asynchronous suspension>
E/flutter (31006): #2 StakingService.getStakeAccounts (package:solflare/blockchain/solana/sdk/action/staking/staking_service.dart:22)
E/flutter (31006): <asynchronous suspension>
E/flutter (31006): #3 StakingFragmentCubit._getStakingAccounts (package:solflare/staking/fragment/bloc/staking_fragment_cubit.dart:62)
E/flutter (31006): <asynchronous suspension>
E/flutter (31006): #4 StakingFragmentCubit.onReload (package:solflare/staking/fragment/bloc/staking_fragment_cubit.dart:56)
E/flutter (31006): <asynchronous suspension>
E/flutter (31006):
E/flutter (31006): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: MissingPluginException(No implementation found for method callAsyncJavaScript on channel com.pichillilorenzo/flutter_inappwebview_122212122589139161956711721439613127213153)
E/flutter (31006): #0 MethodChannel._invokeMethod (package:flutter/src/services/platform_channel.dart:294)
E/flutter (31006): <asynchronous suspension>
E/flutter (31006): #1 InAppWebViewController.callAsyncJavaScript (package:flutter_inappwebview/src/in_app_webview/in_app_webview_controller.dart:2300)
E/flutter (31006): <asynchronous suspension>
E/flutter (31006): #2 SolanaSimulation.getSimulatedBalanceChanges (package:solflare/blockchain/solana/sdk/action/simulation/solana_simulation.dart:22)
E/flutter (31006): <asynchronous suspension>
E/flutter (31006): #3 Future.wait.<anonymous closure> (dart:async/future.dart:522)
E/flutter (31006): <asynchronous suspension>
E/flutter (31006): #4 ConfirmTransactionCubit._loadSimulationInitially (package:solflare/transaction/bloc/confirm_transaction/confirm_transaction_cubit.dart:150)
E/flutter (31006): <asynchronous suspension>
E/flutter (31006):
E/flutter (31006): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: MissingPluginException(No implementation found for method callAsyncJavaScript on channel com.pichillilorenzo/flutter_inappwebview_122212122589139161956711721439613127213153)
E/flutter (31006): #0 MethodChannel._invokeMethod (package:flutter/src/services/platform_channel.dart:294)
E/flutter (31006): <asynchronous suspension>
E/flutter (31006): #1 InAppWebViewController.callAsyncJavaScript (package:flutter_inappwebview/src/in_app_webview/in_app_webview_controller.dart:2300)
E/flutter (31006): <asynchronous suspension>
E/flutter (31006): #2 NameService.getTwitterHandleForPublicKey (package:solflare/blockchain/solana/sdk/action/name_service/name_service.dart:28)
E/flutter (31006): <asynchronous suspension>
E/flutter (31006): #3 PortfolioCubit._getTwitterHandle (package:solflare/portfolio/fragment/bloc/portfolio_cubit.dart:227)
E/flutter (31006): <asynchronous suspension>
E/flutter (31006): #4 Future.wait.<anonymous closure> (dart:async/future.dart:522)
E/flutter (31006): <asynchronous suspension>
E/flutter (31006): #5 PortfolioCubit._getPortfolioData (package:solflare/portfolio/fragment/bloc/portfolio_cubit.dart:143)
E/flutter (31006): <asynchronous suspension>
E/flutter (31006): #6 PortfolioCubit.setTokenAccountCubit.<anonymous closure> (package:solflare/portfolio/fragment/bloc/portfolio_cubit.dart:130)
E/flutter (31006): <asynchronous suspension>
E/flutter (31006):
E/flutter (31006): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: MissingPluginException(No implementation found for method callAsyncJavaScript on channel com.pichillilorenzo/flutter_inappwebview_240182255151794369312015193167229232190250)
E/flutter (31006): #0 MethodChannel._invokeMethod (package:flutter/src/services/platform_channel.dart:294)
E/flutter (31006): <asynchronous suspension>
E/flutter (31006): #1 InAppWebViewController.callAsyncJavaScript (package:flutter_inappwebview/src/in_app_webview/in_app_webview_controller.dart:2300)
E/flutter (31006): <asynchronous suspension>
E/flutter (31006): #2 ActivityService.initialize (package:solflare/blockchain/solana/sdk/action/activity/activity_service.dart:32)
E/flutter (31006): <asynchronous suspension>
E/flutter (31006): #3 TokenAccountCubit._onRefresh (package:solflare/shared/bloc/token_account/token_account_cubit.dart:95)
E/flutter (31006): <asynchronous suspension>
E/flutter (31006):
i tried sending sol from one wallet to another by creating a transaction using solana_web3 package and changing it to String before passing it to the signAndSendTransactions method i get request contains an invalid payloads entry error
import 'dart:convert'; import 'dart:typed_data';
import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter/material.dart'; import 'package:solana_wallet_adapter/solana_wallet_adapter.dart'; import 'package:solana_web3/solana_web3.dart'; import 'package:solana_web3/solana_web3.dart' as web3; import 'package:solana_web3/programs/system.dart';
import '../dashboard/widgets/appBar.dart';
// 1. Create instance of [SolanaWalletAdapter]. final adapter = SolanaWalletAdapter( const AppIdentity(), // NOTE: CONNECT THE WALLET APPLICATION // TO THE SAME NETWORK. cluster: Cluster.devnet, );
class AuthorizeButton extends StatefulWidget { const AuthorizeButton({super.key}); @override State createState() => _AuthorizeButtonState();
}
class _AuthorizeButtonState extends State {
Object? out;
@override
Widget build(BuildContext context) {
return Scaffold(
bottomNavigationBar: GNavBar(
selectedIndex: 1,
),
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
TextButton(
onPressed: () {
// 2. Authorize application with wallet.
} }
here s my code if anyone can help !