3

when I run getBlock function as followed const signedBlock = await api.derived.chain.getBlock(blockhash) I can fetch data from this blockhash: 0x5a17cf943d384aacdfcd834702fa1904f34b4164c2bc6d5601f8ab2fdeb15240 but it doesn't work the same for this blockhash: 0x32b4113148f6086a76f5d01cca690cd7712517dbd64ed862f05d4cebe790a81f. What is the difference between these two? Parameters are the same, methods, modules, calls are the same. Here is my code:

const { ApiPromise, WsProvider } = require('@polkadot/api')
const BigNumber = require('bignumber.js')

const wsProvider = new WsProvider('ws://WEBSOCKET');



 function convertToDot(amount) {

  if (amount === undefined || amount === null || amount === "" || amount === 0) 
  {
    return 0;
  }
  else {
    let divisionby = 10000000000;
    var bn = new BigNumber(amount);
    return Number( bn.div(divisionby) );
  }

}

const declaredTransferTypes = {
  balances: ["transfer", "transferKeepAlive"],
  utility: ["batch"]
}

const getTransactionsFromBlockHash = async (blockhash) => {
 
try{
  api = await ApiPromise.create({ provider: wsProvider });
  const signedBlock = await api.derive.chain.getBlock(blockhash)
  console.log(signedBlock)
  let signedBlockExts = signedBlock.block.extrinsics
  if (signedBlockExts.length <= 0) return []
  let successTxArray = []
  const signedExts = signedBlock.extrinsics
  const extrinsicTransfers = signedBlock.block.extrinsics.filter(y => (((y.method.toHuman().method === "transfer") || (y.method.toHuman().method === "transferKeepAlive")) && (y.method.toHuman().section === "balances")))
  if (extrinsicTransfers.length > 0) {
    extrinsicTransfers.forEach(item => {
      const onlySuccessTransfer = signedExts.filter(y => (y.extrinsic.args.length === 2) && (item.args[0].toHuman().Id === y.extrinsic.args[0].toHuman().Id) && (!y.dispatchError))
      if (onlySuccessTransfer.length > 0) {
       console.log("success transfer object", { tx: item.hash.toHuman(), from: item.signer.toHuman().Id, to: item.args[0].toHuman().Id, amount: convertToDot(`${item.args[1]}`) })
        successTxArray.push({ tx: item.hash.toHuman(), from: item.signer.toHuman().Id, to: item.args[0].toHuman().Id, amount: convertToDot(`${item.args[1]}`) })
      }
    })
  }
   console.log("success transfer  number", successTxArray.length, "success tx here", successTxArray)

  const extrinsicUtility = signedBlockExts.filter(y => (((Object.values(declaredTransferTypes.utility).filter(a => a === y.method.toHuman().method))) && (y.method.toHuman().section === "utility")))
  if (extrinsicUtility.length === 0) return (successTxArray.length > 0 ? successTxArray : [])
  extrinsicUtility.forEach(item => {
    const onlySuccessUtility = signedExts.filter(y => (y.extrinsic._raw.toHuman().signature.signer.Id.indexOf(item._raw.signature.signer.toHuman().Id) > -1) && (!y.dispatchError)).map(a => (a.extrinsic._raw.toHuman().method.args[0]))
    // console.log("onlySuccessUtility", onlySuccessUtility)
    if ((onlySuccessUtility.length > 0) && (item.args[0].length > 0)) {
      item.args[0].filter(y => (Object.values(declaredTransferTypes.balances).filter(a => a === y.method)) && (y.section === "balances")).map(a => (a.args)).forEach(y => {
        // console.log("Success Utility Transactions:", { tx: item.hash.toHuman(), from: item.signer.toHuman().Id, to: y[0].toHuman().Id, amount: convertToDot(`${y[1]}`) })
        successTxArray.push({ tx: item.hash.toHuman(), from: item.signer.toHuman().Id, to: y[0].toHuman().Id, amount: convertToDot(`${y[1]}`) })
      })
    }
  })
  
  console.log("Extrinsics success tx number", successTxArray.length, "success tx", successTxArray)
  return successTxArray

} catch(err){
console.log("Couldn't decode the block. Blockhash:", blockhash)

return []
}
}

getTransactionsFromBlockHash("0x32b4113148f6086a76f5d01cca690cd7712517dbd64ed862f05d4cebe790a81f")

This is the error I'm receiving when I can't fetch data:

2022-08-02 17:59:31 RPC-CORE: getRuntimeVersion(at?: BlockHash): RuntimeVersion:: -32603: Unknown error occurred: Client, Application, UnknownBlock, State already discarded for BlockId::Hash, 0xd72e0b2d776d84dd5d274be22ba0fc1ab971ac8a8f7f0fdb3dc54c331ecec608

1 Answer 1

6

Polkadot nodes are configured to prune old blocks to save disk space.
The default configuration is set to 256 past blocks (wiki link).
If you try to query the state of an older block, you will see the error that you experienced:

State already discarded for BlockId::Hash ...

One solution is to configure the node in --archive mode, which will keep all blocks but requires much more disk space.
Another way is to use an indexer, which is an external application that ingests block data and makes it query-able.
This has the additional advantage that its normally faster since the Polkadot node itself is not build for massive RPC requests into past blocks.

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.