Help with understanding 'Retrying Transactions' Docs

Hi frens. Looking for guidance and help with understanding how to digest the Retrying Transactions guide in the Solana main docs/cookbook.

Guides:

My code:

// 2. Get lastest blockdata. Have to fetch it here to use for my Helius priority fee estimation. Using Solona docs/cookbook strat:

const blockhashResponse = await connection.getLatestBlockhashAndContext();
const lastValidBlockHeight = blockhashResponse.context.slot + 150;

console.log("Blockhash response: ", blockhashResponse);
console.log("lastValidBlockHeight: ", lastValidBlockHeight);
console.log("Current blockheight: ", await connection.getBlockHeight());

This logs:

Blockhash response: {
context: { apiVersion: ‘1.17.20’, slot: 255390070 },
value: {
blockhash: ‘Fe2uRgLUNpFGTJELp8gkXXVWM8PJ3khVEC3AnhPrppQw’,
lastValidBlockHeight: 235877486
}
}
lastValidBlockHeight + 150: 255390220
Current blockheight: 235877187

Then for my actual retrying logic:

// 5. send our v0 transaction to the cluster using solana's cookbook retry logic

let sx;
let txConfirmed = false;
let blockheight = await connection.getBlockHeight();
  while (blockheight < lastValidBlockHeight && !txConfirmed) {
    try {
      const txStatus = sx
        ? (await connection.getSignatureStatus(sx)).value?.confirmationStatus
        : undefined;
      if (txStatus === "confirmed") {
        console.log("Woohoo, tx confirmed!");
        txConfirmed = true;
        break;
      }
      if (!txConfirmed) {
        console.log("sending v0 tx");
        sx = await connection.sendTransaction(transaction, {
          skipPreflight: true,
          preflightCommitment: "confirmed",
          maxRetries: 0,
        });
        await wait(1);
        blockheight = await connection.getBlockHeight();
        console.log("Current block height: ", blockheight);
      }
    } catch (e: any) {
      console.error("Error sending v0 tx: ", e.message);
      if (e.message.includes("has already been processed")) {
        console.log("tx already processed");
        break;
      }
      if (e.message.includes("0x1771")) {
        throw new Error("TransactionError: 0x1771");
      }
    }
  }
return sx;

So I guess im struggling with understanding why the guides are using the slot in the context returned from the getLatestBlockhashAndContext call. This number (255390070) was much higher than the current blockheight ( 235877187), so the check for while (blockheight < lastValidBlockHeight) will always return true?

Would appreciate any help/guidance.

cheers

gm @thearch1tect !

It’s important to start with the distinction between slots and block height on Solana:

  • A slot is a period in which a new block may be produced (set to 400ms but can be higher in practice). Not all slots will have a block
  • The block height represents the number of blocks in the chain. Unlike slots, this number only increases when a new block is added

The confusion seems to stem from expecting these two numbers to correlate directly, which isn’t always the case. Since lastValidBlockHeight is derived from slot numbers, while (blockheight < lastValidBlockHeight && !txConfirmed) might always return true because lastValidBlockHeight (based on slots) should be higher than the current block height.

I’d recommend altering this logic and, maybe, querying the current slot and checking that against your lastValidBlockHeight variable. This adjustment would ensure you’re working with the correct frame of reference to continually retry the transaction until it’s either confirmed or the blockhash expires.

0xIchigo