Transaction Recent Blockhash Required - Phantom Wallet Solana - solana

Uncaught (in promise) WalletSignTransactionError: Transaction recentBlockhash required
at PhantomWalletAdapter.signTransaction (adapter.ts:215:1)
at async WalletProvider.tsx:247:1
at async mintNFT (luckoo.tsx:100:1)
I got this when im trying to send transaction using solana wallet, what should i do?

You need to provide a recentBlockhash in your transaction in order for it to be signed. Most likely, you need to fetch a blockhash and add it before signing the transaction using getLatestBlockhash, ie:
let blockhash = (await connection.getLatestBlockhash('finalized')).blockhash;
transaction.recentBlockhash = blockhash;
Previously, you would use the similar deprecated function getRecentBlockhash:
let blockhash = await connection.getRecentBlockhash('finalized').blockhash;
transaction.recentBlockhash = blockhash;
Your better bet is to directly use sendTransaction, which does all of that work for you. As you can see in the source code, sendTransaction is filling in the recent blockhash if it isn't already present: https://github.com/solana-labs/wallet-adapter/blob/a5b1ebd70ae9753d188fec60e95e252402f3f371/packages/core/base/src/signer.ts#L13
More info about blockhashes: https://docs.solana.com/developing/programming-model/transactions#recent-blockhash
More info about fetching blockhashes: https://docs.solana.com/developing/clients/jsonrpc-api#getlatestblockhash
More info about using sendTransaction: https://github.com/solana-labs/wallet-adapter#usage

Use this
let blockhash = (await connection.getLatestBlockhash("finalized")).blockhash;
console.log("recentBlockhash: ", blockhash);

Related

How can I confirm if a transaction has happened on Solana using the transaction hash (signature)

The confirmTransaction method is being deprecated. Instead there's a sendandconfirmtransaction method but that is not available on the connection object, so I can't use for transactions that are to be signed using phantom.
I have a transaction hash(signature) after the transaction so I'm trying to confirm if a transaction was done on the backend using the transaction hash, how is this possible?
/** #deprecated Instead, call `confirmTransaction` using a `TransactionConfirmationConfig` */
Method is not deprecated try this:
const tx = await connection.requestAirdrop(publicKey, 1e9);
const latestBlockHash = await connection.getLatestBlockhash();
await connection.confirmTransaction({
blockhash: latestBlockHash.blockhash,
lastValidBlockHeight: latestBlockHash.lastValidBlockHeight,
signature: tx,
});

solana web3 API: how to obtain data created with splToken.createTransferInstruction()

Would appreciate guidance on how to obtain the data back in the variables, which was entered into splToken.createTransferInstruction(), step-by-step, from the buffer variable in the code snippet below:
var transaction = new web3.Transaction();
transaction.add(
splToken.createTransferInstruction(
fromTokenAccount,
toTokenAccount,
senderPublicKey,
amount,
[],
splToken.TOKEN_PROGRAM_ID,
)
);
// Setting the variables for the transaction
transaction.feePayer = provider.publicKey;
let blockhashObj = await connection.getRecentBlockhash();
transaction.recentBlockhash = await blockhashObj.blockhash;
// Transaction constructor initialized successfully
if(transaction) { console.log('Txn created successfully'); }
// Request creator to sign the transaction (allow the transaction)
let signed = await provider.signTransaction(transaction);
let buffer = signed.serialize();
Using web3.Transaction.from(buffer) I obtained a Transaction object - see image from the browser's console:
I need to do something with instructions[0].data, I suppose to break it into byte lengths that will allow me to repopulate from the signed transaction:
fromTokenAccount,
toTokenAccount,
senderPublicKey,
amount,
[], // would this be a variable or zero-byte?
splToken.TOKEN_PROGRAM_ID,
from the splToken.createTransferInstruction() above.
Much appreciated!
From the TransactionInstruction, you can use decodeTransferInstruction to get back the initial parameters. In your case, you can call:
let tx = web3.Transaction.from(buffer);
let decodedIx = decodeTransferInstruction(tx.instructions[0]);
console.log(decodedIx.keys.source);
console.log(decodedIx.keys.destination);
console.log(decodedIx.keys.owner);
console.log(decodedIx.data.amount);
Full source code available at: https://github.com/solana-labs/solana-program-library/blob/24baf875e9e19c26d694d28c557d33848c3a9180/token/js/src/instructions/transfer.ts#L87

How to use await on getAll method for IndexDB?

I am trying to get the data stored in my ObjectStore and I want this synchronously. So instead of using onsuccess I want to use await / async.
I have implemented this below code but somehow its not returning me the data.
async function viewNotes() {
const tx = db.transaction("personal_notes","readonly")
const pNotes = tx.objectStore("personal_notes")
const items = await db.transaction("personal_notes").objectStore("personal_notes").getAllKeys()
console.log("And the Items are ", items.result)
let NotesHere = await pNotes.getAll().onsuccess
console.log("Ans this are the logs", NotesHere)
}
Neither I am getting the data through items.result nor from NotesHere.
When I view from debug mode, items's readyState is still in pending even after using await.
What am I missing ?
The IndexedDB API does not natively support async/await. You need to either manually wrap the event handlers in promises, or (much better solution) use a library like https://github.com/jakearchibald/idb that does it for you.

How to get the result of a payable transaction using near-api-js?

When calling a contract method with attached deposits, you are redirected to the NEAR wallet for approving the transaction. How can the contract frontend app get the result of the transaction after returning from the wallet?
I've faced the same problem. For this moment near-api set transaction info in the browser url. So you get the transaction hash from url after returning from the wallet. Then using transaction hash get info about it using near-api-js:
const { providers } = require("near-api-js");
//network config (replace testnet with mainnet or betanet)
const provider = new providers.JsonRpcProvider(
"https://archival-rpc.testnet.near.org"
);
const TX_HASH = "9av2U6cova7LZPA9NPij6CTUrpBbgPG6LKVkyhcCqtk3";
// account ID associated with the transaction
const ACCOUNT_ID = "sender.testnet";
getState(TX_HASH, ACCOUNT_ID);
async function getState(txHash, accountId) {
const result = await provider.txStatus(txHash, accountId);
console.log("Result: ", result);
}
Documentation: https://docs.near.org/docs/api/naj-cookbook#get-transaction-status
There are 2 options:
Use provider.txStatus like Tom Links said. But the cons : we only know transaction success or fail but not the response from smart contract.
Seperate deposit api and actions api -> User must deposit before call actions api, so we can read the response.

FirebaseInstanceId.Instance.Token is depricated and returns null in Xamarin.Android using Xamarin.Firebase.Messaging

I'm working on a Xamarin.Android project using Xamarin.Firebase.Messaging v71.1740 nuget plugin,
I'm trying to get the FCM Token that was already generated in the FirebaseMessagingService extended class method,
public override void OnNewToken(string p0)
{
base.OnNewToken(p0);
// use token
}
using,
var token = FirebaseInstanceId.Instance.Token;
But this returns null and it listed as obsolete too.
UPDATE
GetInstanceId<InstanceIdResult>() is also deprecated in favour of FirebaseMessaging.getToken() for FCM Token and FirebaseInstallations.getId() for Instance Identifier,
So, FirebaseMessaging.getToken() is the recommended way now to get the FCM Token,
This is how you can consume it easily,
var token = await FirebaseMessaging.Instance.GetToken();
and FirebaseInstallations.getId() is the recommended way now to get the Instance Identifier,
This is how you can consume it easily,
var id = await FirebaseInstallations.Instance.GetId();
here, var is of the Type Java.Lang.Object. Do, token.ToString() to get the string value.
ORIGINAL
FirebaseInstanceId.Instance.Token is deprecated in favour of GetInstanceId<InstanceIdResult>(),
So, GetInstanceId<InstanceIdResult>() is the recommended way,
This is how you can consume it,
var instanceIdResult = await FirebaseInstanceId.Instance.GetInstanceId().AsAsync<IInstanceIdResult>();
var token = instanceIdResult.Token;
Oh look, FirebaseInstanceId.Instance is deprecated too.
Looks like the more newer way is:
var token = await FirebaseMessaging.Instance.GetToken();
If you are getting null on FirebaseInstanceId.Instance, when calling
var instanceIdResult = await FirebaseInstanceId.Instance.GetInstanceId().AsAsync<IInstanceIdResult>();
I have to update
Xamarin.Firebase.Messaging to version 71.1740.1
And add this to yourproject.android.csproj
<PropertyGroup>
<AndroidManifestMerger>manifestmerger.jar</AndroidManifestMerger>
</PropertyGroup>
(more info)
This works for me (not sure if both are mandatory)

Resources