13

I wonder if there is an equivalent to bitcoind's getrawtransaction, i.e., a command to dump a raw transaction in hex format, given its hash id.

I am working preferably in geth.

6 Answers 6

10

There is eth.getRawTransaction(<txhash>) now.

Edit: Please check that you're using an up-to-date version of geth. It's part of the current release (v.1.8.6) and was introduced some time ago. You can also see it in the source code: https://github.com/ethereum/go-ethereum/blob/ca64a122d33008c155c35a9d0e78cfbcafb1820a/internal/web3ext/web3ext.go (look for getRawTransaction)
https://github.com/ethereum/go-ethereum/blob/ec8ee611caefb5c5ad5d796178e94c1919260df4/internal/ethapi/api.go (look for GetRawTransactionByHash)

input: transaction hash
output: bytes of the corresponding transaction

4
  • Can you please improve & expand this answer by providing links to documentation and the call/response?
    – tayvano
    Commented Jun 12, 2017 at 22:19
  • Is this real? It seems that this call does not exist
    – blues
    Commented Jan 10, 2018 at 11:40
  • 1
    There isn't eth.getRawTransaction(). What are you talking about?
    – rustyx
    Commented Apr 24, 2018 at 15:11
  • 1
    I am probing a Geth client version 1.8.15 and this method does not seem to exist. This call returns 405 Method Not Allowed: curl -i -X POST --data '{"jsonrpc":"2.0","method":"eth_getRawTransaction","params":["0x14f00d6f024a1d19d1d93948627020c5b75fc6b2a9fabb256dd2320953834d96"],"id":1}' <client_url> The same happens if the method is eth_getRawTransactionByHash. Commented Oct 14, 2018 at 12:42
6

There is an "undocumented" method eth_getRawTransactionByHash from JSON-RPC

curl -H "Content-Type: application/json" -X POST --data \
'{"jsonrpc":"2.0","method":"eth_getRawTransactionByHash","params":["<TX_HASH>"],"id":1}' http://localhost:8545

<TX_HASH> - transaction id

2
  • If I call this, I get 405 Method Not Allowed. This method does not seem to exist on version 1.8.15. Commented Oct 14, 2018 at 12:46
  • But it does work in Geth v1.9.11 Commented Jan 28, 2020 at 17:14
3

Have a look at getTransactionByHash() of the JSON-RPC API.

eth_getTransactionByHash

Returns the information about a transaction requested by transaction hash.

Parameters

DATA, 32 Bytes - hash of a transaction
params: [
   "0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238"
]
Returns

Object - A transaction object, or null when no transaction was found:

hash: DATA, 32 Bytes - hash of the transaction.
nonce: QUANTITY - the number of transactions made by the sender prior to this one.
blockHash: DATA, 32 Bytes - hash of the block where this transaction was in. null when its pending.
blockNumber: QUANTITY - block number where this transaction was in. null when its pending.
transactionIndex: QUANTITY - integer of the transactions index position in the block. null when its pending.
from: DATA, 20 Bytes - address of the sender.
to: DATA, 20 Bytes - address of the receiver. null when its a contract creation transaction.
value: QUANTITY - value transferred in Wei.
gasPrice: QUANTITY - gas price provided by the sender in Wei.
gas: QUANTITY - gas provided by the sender.
input: DATA - the data send along with the transact
2
  • 4
    That returns a json description, not the raw transaction
    – oriol
    Commented Jul 26, 2016 at 16:06
  • It is possible to construct the raw transaction from the data returned from the getTransactionByHash() RPC call. Commented Oct 14, 2018 at 12:39
2

You can also find the raw transaction hex on etherscan.io by going to a transaction, picking Tools & Utilities and choosing Get Raw TxHash. See for example:

https://etherscan.io/getRawTx?tx=0x248b16e4cb8a624ab4bb3125a3a2cf6bd6d21200b773e3d9c1f0738b1b09dd22

If you want to do this programatically with geth, I present a solution for that here: Can I get the raw transaction using Nethereum?

2

You can do it this way in Python:

import web3
from eth_account._utils.legacy_transactions import (
    encode_transaction,
    serializable_unsigned_transaction_from_dict,
)

w3 = web3.Web3(web3.HTTPProvider("https://eth-mainnet.alchemyapi.io/v2/XXXXXXXXXXXXXXXXXXXXXXXXXXX"))
hash = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
tx = w3.eth.getTransaction(hash)

def recover_raw_transaction(tx):
    """Recover raw transaction for replay.

    Inspired by: https://github.com/ethereum/eth-account/blob/1d26f44f6075d6f283aeaeff879f4508c9a228dc/eth_account/_utils/signing.py#L28-L42
    """
    transaction = {
        "chainId": tx["chainId"],
        "nonce": int(tx["nonce"], 16),
        "maxPriorityFeePerGas": int(tx["maxPriorityFeePerGas"], 16),
        "maxFeePerGas": int(tx["maxFeePerGas"], 16),
        "gas": int(tx["gas"], 16),
        "to": Web3.toChecksumAddress(tx["to"].lower()),
        "value": int(tx["value"], 16),
        "accessList": tx["accessList"],
    }
    if "data" in tx:
        transaction["data"] = tx["data"]
    if "input" in tx:
        transaction["data"] = tx["input"]
    
    v = int(tx["v"], 16)
    r = int(tx["r"], 16)
    s = int(tx["s"], 16)
    unsigned_transaction = serializable_unsigned_transaction_from_dict(transaction)
    return "0x" + encode_transaction(unsigned_transaction, vrs=(v, r, s)).hex()

raw_tx = recover_raw_transaction(tx)

If some basic fields like access_list are missing when you retried the tx by hash, add them manually.

0

The node I'm consuming doesn't support eth_getTransactionByHash So similarly to Nikolay answer, this is how I did it using ethers.js v5 (and TypeScript) instead of web3.py

import { Transaction } from "@ethersproject/transactions";

/**
 * Serializes a transaction object into a raw transaction string.
 * This function takes a Transaction object, ensures it is fully signed,
 * constructs the unsigned transaction object, and then serializes it with the signature.
 * It also verifies the serialization process by comparing the computed transaction hash
 * with the original transaction hash.
 *
 * @param {Transaction} transaction - The transaction object from Ethers.js.
 * @returns {string} The serialized raw transaction.
 */
const transactionToRawTransaction = (
  transaction: TransactionResponse,
): string => {
  const type0Fields = { gasPrice: transaction.gasPrice };
  const type1Fields = { ...type0Fields, accessList: transaction.accessList };
  const type2Fields = {
    accessList: transaction.accessList,
    maxFeePerGas: transaction.maxFeePerGas,
    maxPriorityFeePerGas: transaction.maxPriorityFeePerGas,
  };
  const typeFileds = [type0Fields, type1Fields, type2Fields];
  const extraFields = typeFileds[transaction.type ?? 0];
  const unsignedTx = {
    chainId: transaction.chainId,
    data: transaction.data,
    gasLimit: transaction.gasLimit,
    nonce: transaction.nonce,
    to: transaction.to,
    type: transaction.type,
    value: transaction.value,
    ...extraFields,
  };
  assert.ok(transaction.r);
  const signature = {
    r: transaction.r,
    s: transaction.s,
    v: transaction.v,
  };
  const serialized = ethers.utils.serializeTransaction(unsignedTx, signature);
  // double check things went well
  assert.strictEqual(ethers.utils.keccak256(serialized), transaction.hash);
  return serialized;
};

/**
 * Fetches a transaction from the blockchain using its hash and serializes it into a raw transaction string.
 * This function retrieves the transaction details using the provided hash, ensuring the transaction exists,
 * and then utilizes `transactionToRawTransaction` to serialize the transaction.
 * This is useful if we want to replay a raw transaction in local or in the tests.
 *
 * @param {Provider} provider - The Ethers.js provider instance to interact with the blockchain.
 * @param {string} hash - The hash of the transaction to fetch and serialize.
 * @returns {Promise<string>} A promise that resolves to the serialized raw transaction string.
 */
const transactionHashToRawTransaction = async (
  provider: Provider,
  hash: string,
): Promise<string> => {
  const transaction = await provider.getTransaction(hash);
  const serialized = transactionToRawTransaction(transaction);
  return serialized;
};

It's much easier with Ethers v6 is much easier since the ethers.Transaction object has a serialized attribute.

import { TransactionResponseParams } from "ethers";

const transactionToRawTransaction = (
  transaction: TransactionResponseParams,
): string => {
  const serialized = Transaction.from(transaction).serialized;
  // double check things went well
  assert.strictEqual(keccak256(serialized), transaction.hash);
  return serialized;
};

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.