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.

Tesa
  • 2,269
  • 20
  • 40
oriol
  • 133
  • 1
  • 1
  • 6

6 Answers6

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

Pold
  • 293
  • 2
  • 9
  • Can you please improve & expand this answer by providing links to documentation and the call/response? – tayvano Jun 12 '17 at 22:19
  • Is this real? It seems that this call does not exist – blues Jan 10 '18 at 11:40
  • 1
    There isn't eth.getRawTransaction(). What are you talking about? – rustyx Apr 24 '18 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.

    – Thorkil Værge Oct 14 '18 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

mishabunte
  • 61
  • 1
  • 1
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
Richard Horrocks
  • 37,835
  • 13
  • 87
  • 144
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
&quot;&quot;&quot;
transaction = {
    &quot;chainId&quot;: tx[&quot;chainId&quot;],
    &quot;nonce&quot;: int(tx[&quot;nonce&quot;], 16),
    &quot;maxPriorityFeePerGas&quot;: int(tx[&quot;maxPriorityFeePerGas&quot;], 16),
    &quot;maxFeePerGas&quot;: int(tx[&quot;maxFeePerGas&quot;], 16),
    &quot;gas&quot;: int(tx[&quot;gas&quot;], 16),
    &quot;to&quot;: Web3.toChecksumAddress(tx[&quot;to&quot;].lower()),
    &quot;value&quot;: int(tx[&quot;value&quot;], 16),
    &quot;accessList&quot;: tx[&quot;accessList&quot;],
}
if &quot;data&quot; in tx:
    transaction[&quot;data&quot;] = tx[&quot;data&quot;]
if &quot;input&quot; in tx:
    transaction[&quot;data&quot;] = tx[&quot;input&quot;]

v = int(tx[&quot;v&quot;], 16)
r = int(tx[&quot;r&quot;], 16)
s = int(tx[&quot;s&quot;], 16)
unsigned_transaction = serializable_unsigned_transaction_from_dict(transaction)
return &quot;0x&quot; + 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.

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?

Thorkil Værge
  • 4,220
  • 2
  • 16
  • 38
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; };

Andre Miras
  • 107
  • 4