-
Notifications
You must be signed in to change notification settings - Fork 88
Transactions
The Eth::
module supports all known transaction types. It will default to EIP-1559 transactions on the Ethereum network.
To create a transaction, create the payload first. To use a different network, just provide a chain_id
. Note the Eth::Unit::
submodule for convenience.
payload = {
chain_id: Eth::Chain::GOERLI,
nonce: 5,
priority_fee: 3 * Eth::Unit::GWEI,
max_gas_fee: 69 * Eth::Unit::GWEI,
gas_limit: 230_420,
to: "0xCaA29806044A08E533963b2e573C1230A2cd9a2d",
value: 0.069423 * Eth::Unit::ETHER,
}
# => {:chain_id=>5, :nonce=>5, :priority_fee=>0.3e10, :max_gas_fee=>0.69e11, :gas_limit=>230420, :to=>"0xCaA29806044A08E533963b2e573C1230A2cd9a2d", :value=>0.69423e17}
Create a new transaction with the payload. Note, because we specified priority_fee
and max_gas_fee
, it automatically creates an Eth::Tx::Eip1559
object indicating we want to create a type-2 transaction (EIP-1559).
tx = Eth::Tx.new payload
# => #<Eth::Tx::Eip1559:0x0000557e35fc5a68 @access_list=[], @amount=69423000000000000, @chain_id=5, @destination="CaA29806044A08E533963b2e573C1230A2cd9a2d", @gas_limit=230420, @max_fee_per_gas=69000000000, @max_priority_fee_per_gas=3000000000, @payload="", @sender="", @signature_r=0, @signature_s=0, @signature_y_parity=nil, @signer_nonce=5, @type=2>
Transactions can be signed by simply passing a keypair to the sign
method.
signer_key = Eth::Key.new priv: "30137644b564785d01420f8043f043d74dcca64008e57c59f8ce713a0005a54b"
# => #<Eth::Key:0x0000557e36243178 @private_key=#<Secp256k1::PrivateKey:0x0000557e36242d40 @data="0\x13vD\xB5dx]\x01B\x0F\x80C\xF0C\xD7M\xCC\xA6@\b\xE5|Y\xF8\xCEq:\x00\x05\xA5K">, @public_key=#<Secp256k1::PublicKey:0x0000557e36242cf0>>
tx.sign signer_key
# => "cba302c0ebf8d0205a78ae97f560419b407e32e2426f416abc95a9bfc9dac09c"
This returns the transaction hash. To get the signed, raw transaction use hex
.
tx.hex
# => "02f873050584b2d05e00851010b872008303841494caa29806044a08e533963b2e573c1230a2cd9a2d87f6a3d9c63df00080c080a03aa187d10b138d3e0155729adb961cd89e10f988ba2d19d6869770b9e5a23d10a04d40864600136ae214916043c7d63b849c98db757e95c86983a036982816e1af"
That's it. It can be broadcasted through whatever client one desires.
To create a legacy transaction (type 0), just replace the priority_fee
and max_gas_fee
options in the payload by gas_price
. You'll receive an Eth::Tx::Legacy
object that can be signed in the same way.
legacy_payload = {
chain_id: Eth::Chain::ROPSTEN,
nonce: 137,
gas_price: 42 * Eth::Unit::GWEI,
gas_limit: Eth::Tx::DEFAULT_GAS_LIMIT,
to: "0xCaA29806044A08E533963b2e573C1230A2cd9a2d",
value: 1 * Eth::Unit::ETHER,
}
#=> {:chain_id=>3, :nonce=>137, :gas_price=>0.42e11, :gas_limit=>21000, :to=>"0xCaA29806044A08E533963b2e573C1230A2cd9a2d", :value=>0.1e19}
legacy_tx = Eth::Tx.new legacy_payload
=> #<Eth::Tx::Legacy:0x0000558e5508e9c0
@amount=1000000000000000000, @chain_id=3, @destination="CaA29806044A08E533963b2e573C1230A2cd9a2d", @gas_limit=21000, @gas_price=42000000000, @payload="", @sender="", @signature_r=0, @signature_s=0, @signature_v=3, @signer_nonce=137, @type=0>
Type-1 transactions (EIP-2930) are also supported, by simply providing an access_list
.
access_list = [["de0b295669a9fd93d5f28d9ec85e40f4cb697bae", ["0000000000000000000000000000000000000000000000000000000000000003", "0000000000000000000000000000000000000000000000000000000000000007"]], ["bb9bc244d798123fde783fcc1c72d3bb8c189413", []]]
# => [["de0b295669a9fd93d5f28d9ec85e40f4cb697bae", ["0000000000000000000000000000000000000000000000000000000000000003", "0000000000000000000000000000000000000000000000000000000000000007"]], ["bb9bc244d798123fde783fcc1c72d3bb8c189413", []]]
intrinsic_gas = Eth::Tx.estimate_intrinsic_gas "", access_list
# => 29600
type1_payload = {
chain_id: Eth::Chain::PRIVATE_GETH,
nonce: 0,
gas_price: 1 * Eth::Unit::GWEI,
gas_limit: intrinsic_gas,
to: "0xCaA29806044A08E533963b2e573C1230A2cd9a2d",
access_list: access_list
}
# => {:chain_id=>1337, :nonce=>0, :gas_price=>0.1e10, :gas_limit=>29600, :to=>"0xCaA29806044A08E533963b2e573C1230A2cd9a2d", :access_list=> [["de0b295669a9fd93d5f28d9ec85e40f4cb697bae", ["0000000000000000000000000000000000000000000000000000000000000003", "0000000000000000000000000000000000000000000000000000000000000007"]], ["bb9bc244d798123fde783fcc1c72d3bb8c189413", []]]}
type1_tx = Eth::Tx.new type1_payload
# => #<Eth::Tx::Eip2930:0x0000558e54fc5f48 @access_list=[["\xDE\v)Vi\xA9\xFD\x93\xD5\xF2\x8D\x9E\xC8^@\xF4\xCBi{\xAE", ["\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03", "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\a"]], ["\xBB\x9B\xC2D\xD7\x98\x12?\xDEx?\xCC\x1Cr\xD3\xBB\x8C\x18\x94\x13", []]], @amount=0, @chain_id=1337, @destination="CaA29806044A08E533963b2e573C1230A2cd9a2d", @gas_limit=29600, @gas_price=1000000000, @payload="", @sender="", @signature_r=0, @signature_s=0, @signature_y_parity=nil, @signer_nonce=0, @type=1>
Note, how Eth::Tx.estimate_intrinsic_gas
can compute the required gas_limit
by passing the data payload and access list to it.
You can also decode
raw transactions and create unsigned copies.
decoded_tx = Eth::Tx.decode "02f873050584b2d05e00851010b872008303841494caa29806044a08e533963b2e573c1230a2cd9a2d87f6a3d9c63df00080c080a03aa187d10b138d3e0155729adb961cd89e10f988ba2d19d6869770b9e5a23d10a04d40864600136ae214916043c7d63b849c98db757e95c86983a036982816e1af"
# => #<Eth::Tx::Eip1559:0x0000558e54f0fa18 @access_list=[], @amount=69423000000000000, @chain_id=5, @destination="caa29806044a08e533963b2e573c1230a2cd9a2d", @gas_limit=230420, @max_fee_per_gas=69000000000, @max_priority_fee_per_gas=3000000000, @payload="", @sender="0c53FFA57Ec554451315c2568d22477dB8e71356", @signature_r="3aa187d10b138d3e0155729adb961cd89e10f988ba2d19d6869770b9e5a23d10", @signature_s="4d40864600136ae214916043c7d63b849c98db757e95c86983a036982816e1af", @signature_y_parity=0, @signer_nonce=5, @type=2>
tx_copy = Eth::Tx.unsigned_copy decoded_tx
# => #<Eth::Tx::Eip1559:0x0000558e55077568 @access_list=[], @amount=69423000000000000, @chain_id=5, @destination="caa29806044a08e533963b2e573c1230a2cd9a2d", @gas_limit=230420, @max_fee_per_gas=69000000000, @max_priority_fee_per_gas=3000000000, @payload="", @sender="", @signature_r=0, @signature_s=0, @signature_y_parity=nil, @signer_nonce=5, @type=2>
That's it. Check out the API documentation for a more complete picture.