2

So I am building a service that will be creating high amount of transactions on different substrate base chains.

The infrastructure I have in mind is having microservices that will generate transactions depending on the chain and different outcomes. Then the constructed transaction parameters are sent to another microservice that selects the key and signs the transaction. The signed transaction is saved into the database and a cron job picks it up and sends it to the node. While another worker is checking and updating the transaction status in the database.

Why I have this is mind is so that I can have a secure way of signing the transaction. Then since a node can be unresponsive or dynamically chosen based on the chain we are transmitting to I have a separate worker that just makes sure the transactions are transmitted to the network in the correct sequence. And finally a service that monitors transactions and their statuses.

Now almost all examples I found do all this 3 things at the same time using signAndSend method and waiting for response.

I found this: https://wiki.polkadot.network/docs/build-transaction-construction for creating each step individually.

But from researching further I found out that transactionHash is not unique like with EVM chains to monitor the transaction through that.

Now my main questions are:

  • Is the infrastructure I have in mind appropriate= It works very well for EVM based chains but is there is a different/better way to do things for substrate based transactions?
  • How to uniquely identify and monitor transactions? And can you get the unique key before actually sending the transaction to the chain?

1 Answer 1

5

How to uniquely identify and monitor transactions? And can you get the unique key before actually sending the transaction to the chain?

You are right transactionHash is not unique, read the section Unique Identifiers for Extrinsics from the Polkadot wiki:

Many infrastructure providers on existing blockchains, e.g. Ethereum, consider a transaction's hash as a unique identifier. In Substrate-based chains like Polkadot, a transaction's hash only serves as a fingerprint of the information within a transaction, and there are times when two transactions with the same hash are both valid.

The correct way to uniquely identify an extrinsic on a Substrate-based chain is to use the block ID (height or hash) and the extrinsic's index.

See this past question and the answer in StackExchange about Why could we find the same transaction hash in 3 different blocks? where it explains it in more detail.

Is the infrastructure I have in mind appropriate= It works very well for EVM based chains but is there is a different/better way to do things for substrate based transactions?

It makes sense to me too. However you need some extra code to see in which block your transaction has been included and construct this unique identifier for your transaction.

First with a subscription to know the hash of the block and after querying the information from the block and its extrinsics.

A code example would be:

const unsub = await api.tx.balances
    .transfer(BOB, 100000000000)
    .signAndSend(alice, async (result) => {
        const extrinsicHash = result.txHash.toHuman();
        console.log(`Extrinsic Hash is ${extrinsicHash}`);

        if (result.status.isInBlock) {
            console.log(`Transaction included at blockHash ${result.status.asInBlock}`);
        } else if (result.status.isFinalized) {
            console.log(`Transaction finalized at blockHash ${result.status.asFinalized}`);
            const hashOfTheBlock = result.status.asFinalized;
            const signedBlock = await api.rpc.chain.getBlock(hashOfTheBlock);
            
            signedBlock.block.extrinsics.forEach(async (ex, index) => {
                const blockNumber = signedBlock.block.header.number;
                if (extrinsicHash === ex.hash.toHex()) {
                    
                    const extrinsic = (`${blockNumber}-${index}`);
                    console.log(extrinsic);
                }
            });
        unsub();
        }
    });

As mentioned that the transaction hash is not unique, does that mean that transaction hash does not include nonce? Is there a way to retrieve a transaction via address and nonce?

The nonce is included in the transaction hash, and most of the times it will make that the hash of the transaction an account is making is different.

However, this is not enough to ensure is unique.

An example can be a reaped account. See this example from the Polkadot docs: enter image description here

An account A makes the first transaction and is reaped because its funds goes below the existential deposit, when an account is reaped all the information of this account is deleted included the nonce.

When it receives funds again if the account A creates the same extrinsic again (it will have the same nonce as before) therefore the hash will be the same.

9
  • So I have to wait for result after sending the transaction since otherwise I actually cannot uniquely identify the transaction? What if the chain is super congested? This can take X amount of time? And for sending multiple transactions one after the other this can be really slow always waiting for the transaction to get included into a block? Jan 26, 2023 at 8:19
  • If you want another option to not wait for the transaction, you need another process to find it "later on". You can query the last blocks and check in the list of extrinsics of the block to find your extrinsic and generate the transaction identifier
    – Alex Bean
    Jan 26, 2023 at 8:33
  • or have another service that is listening the events like in this answer substrate.stackexchange.com/questions/6075/…
    – Alex Bean
    Jan 26, 2023 at 8:38
  • 1
    If you can batch the transactions that is perfect for your use case, because you can get the block where all of them are included just waiting once and construct the transaction identifier for each one
    – Alex Bean
    Jan 26, 2023 at 10:51
  • 1
    I have update my answer @Josh
    – Alex Bean
    Feb 13, 2023 at 10:17

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.