When I build a Phantom wallet integration (using these docs) on a page, it doesn't include the backend in the transaction at all.

How does the backend hear about that transaction? The back of house is not signing and sending the transaction, the front is.

So the frontend would have to send signatures to.. my backend?

How could I trust the users packet? What if it fails to deliver? What if the user spams my server with false signatures to validate?

  • Didn't realise how quiet this Stack was. For the moment I am settling for using QuickNode, a service which offer webhooks to listen to a wallet's funds changes in real-time quicknode.com/guides/solana-development/getting-started/…
    – 1owk3y
    Sep 9, 2023 at 8:19
  • Okay turns out I can't do that. While it does enable me to get real-time notifications about wallet fund changes it doesn't contain information about the sender. It just notifies you that the balance is different. Back to square zero.
    – 1owk3y
    Sep 9, 2023 at 13:17
  • 1
    The back-end is the blockchain itself. If you need a service to respond to changes in the blockchain you would ideally query the blockchain regularly. You are correct that relying on webhooks or the UI sending the event is risky, but they can offer great UX, however you should always query the blockchain for events separately to cover cases where the first two methods fail.
    – Serban
    Sep 10, 2023 at 8:03
  • @Serban "the back-end is the blockchain itself" would be true if my app was fully on-chain. It is not. A webhook is good for notifications only, since they generally only notify about balance changes and not their origins/instructions. And yes, having the front notify the back is way too risky, it needs to be the other way around. In the end I opted for having the back-end periodically check for new transactions which is not instant, but using a webhook to invoke that check would make it so, and does not take any front-end user input at all
    – 1owk3y
    Sep 10, 2023 at 8:22

3 Answers 3


Alchemy have webhooks to get real time notifications. You can setup a custom webhook and capture the transaction data. https://docs.alchemy.com/reference/notify-api-quickstart

  • Alchemy has no webhook to listen to a wallet fund changes (in Solana). I understand what you are saying but if I had a transaction to query, I would listen to it's events - that isn't the problem. The problem is that I get a signature hash AFTER user sends the payment. What if my server never recieves a transaction hash?
    – 1owk3y
    Sep 9, 2023 at 13:16

How about the Webhooks that helius.dev provides? Here's a blogpost about building a simple wallet tracker: https://www.helius.dev/blog/build-a-wallet-tracker-on-solana. Your backend could be notified when the wallet receives the funds.

When creating the webhook, you can also select the "raw" webhook type which would give you complete freedom in parsing the transaction data and you'll get the signature.


You can get the Transactions and it's to/from hashes, and lamports exchanged yourself (without third-party providers) easily via getSignaturesForAddress (via @solana/web3.js)

You can query the public hash of a wallet for it's signatures, and here's what I wasn't understanding:

Signatures convert to transactions via getParsedTransactions(signatureList)

Each Transaction contains instructions which is an array containing items which include the source hash, destination hash, and the number of lamports which changed hands.

const getTransactions = async(address, numTx) => {
    const pubKey = new solanaWeb3.PublicKey(address);
    let transactionList = await solanaConnection.getSignaturesForAddress(pubKey, {limit:numTx});

    let signatureList = transactionList.map(transaction=>transaction.signature);
    let transactionDetails = await solanaConnection.getParsedTransactions(signatureList, {maxSupportedTransactionVersion:0});

    transactionList.forEach((transaction, i) => {
        const date = new Date(transaction.blockTime*1000);
        const transactionInstructions = transactionDetails[i].transaction.message.instructions;
        console.log(`Transaction No: ${i+1}`);
        console.log(`Signature: ${transaction.signature}`);
        console.log(`Time: ${date}`);
        console.log(`Status: ${transaction.confirmationStatus}`);
        transactionInstructions.forEach((instruction, n)=>{
            console.log(`---Instructions ${n+1}: ${instruction.programId.toString()}`);


Now we have a source of truth to reconcile against. A guarunteed way of knowing which transactions landed.

This solution does not enable the 'real time notification' aspect of collecting the transactions... but now that we actually have a way to get this data we can just use a webhook listener (see other answers) as the cataylist to invoke the re-checking process (using this answer)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.