-module(gleeth@crypto@transaction). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/gleeth/crypto/transaction.gleam"). -export([sign_transaction/2, sign_eip1559_transaction/2, create_legacy_transaction/7, create_eth_transfer/6, create_contract_call/6, create_eip1559_transaction/9, signed_transaction_to_string/1, hash_raw_transaction/1, get_transaction_hash/1, get_eip1559_transaction_hash/1, signed_eip1559_transaction_to_string/1, error_to_string/1]). -export_type([unsigned_transaction/0, signed_transaction/0, eip1559_transaction/0, access_list_entry/0, signed_eip1559_transaction/0, transaction_type/0, transaction_error/0]). -if(?OTP_RELEASE >= 27). -define(MODULEDOC(Str), -moduledoc(Str)). -define(DOC(Str), -doc(Str)). -else. -define(MODULEDOC(Str), -compile([])). -define(DOC(Str), -compile([])). -endif. -type unsigned_transaction() :: {unsigned_transaction, binary(), binary(), binary(), binary(), binary(), binary(), integer()}. -type signed_transaction() :: {signed_transaction, binary(), binary(), binary(), binary(), binary(), binary(), integer(), binary(), binary(), binary(), binary()}. -type eip1559_transaction() :: {eip1559_transaction, binary(), binary(), binary(), binary(), binary(), binary(), binary(), integer(), list(access_list_entry())}. -type access_list_entry() :: {access_list_entry, binary(), list(binary())}. -type signed_eip1559_transaction() :: {signed_eip1559_transaction, binary(), binary(), binary(), binary(), binary(), binary(), binary(), integer(), list(access_list_entry()), binary(), binary(), binary(), binary()}. -type transaction_type() :: legacy | access_list | eip1559. -type transaction_error() :: {invalid_address, binary()} | {invalid_amount, binary()} | {invalid_gas, binary()} | {invalid_nonce, binary()} | {invalid_chain_id, binary()} | {invalid_data, binary()} | {signing_failed, binary()} | {encoding_failed, binary()}. -file("src/gleeth/crypto/transaction.gleam", 458). ?DOC( " Encode a hex string as raw bytes without stripping leading zeros.\n" " Used for address and data fields which are byte strings, not integers.\n" ). -spec encode_raw_hex(binary()) -> gleeth@encoding@rlp:rlp_item(). encode_raw_hex(Hex_string) -> case gleeth@utils@hex:decode(Hex_string) of {ok, Bytes} -> {rlp_bytes, Bytes}; {error, _} -> {rlp_bytes, <<>>} end. -file("src/gleeth/crypto/transaction.gleam", 364). ?DOC(" EIP-155 signing hash: keccak256(RLP([nonce, gasPrice, gasLimit, to, value, data, chainId, 0, 0]))\n"). -spec create_signing_hash(unsigned_transaction()) -> bitstring(). create_signing_hash(Transaction) -> Items = {rlp_list, [gleeth@encoding@rlp:encode_hex_field(erlang:element(6, Transaction)), gleeth@encoding@rlp:encode_hex_field(erlang:element(5, Transaction)), gleeth@encoding@rlp:encode_hex_field(erlang:element(4, Transaction)), encode_raw_hex(erlang:element(2, Transaction)), gleeth@encoding@rlp:encode_hex_field(erlang:element(3, Transaction)), encode_raw_hex(erlang:element(7, Transaction)), gleeth@encoding@rlp:encode_int(erlang:element(8, Transaction)), gleeth@encoding@rlp:encode_int(0), gleeth@encoding@rlp:encode_int(0)]}, gleeth@crypto@keccak:keccak256_binary(gleeth@encoding@rlp:encode(Items)). -file("src/gleeth/crypto/transaction.gleam", 451). -spec encode_access_list_entry(access_list_entry()) -> gleeth@encoding@rlp:rlp_item(). encode_access_list_entry(Entry) -> Storage_keys = gleam@list:map( erlang:element(3, Entry), fun encode_raw_hex/1 ), {rlp_list, [encode_raw_hex(erlang:element(2, Entry)), {rlp_list, Storage_keys}]}. -file("src/gleeth/crypto/transaction.gleam", 447). ?DOC(" Encode an access list as an RLP list of [address, [storageKeys]] entries\n"). -spec encode_access_list(list(access_list_entry())) -> gleeth@encoding@rlp:rlp_item(). encode_access_list(Entries) -> {rlp_list, gleam@list:map(Entries, fun encode_access_list_entry/1)}. -file("src/gleeth/crypto/transaction.gleam", 403). ?DOC(" EIP-1559 signing hash: keccak256(0x02 || RLP([chainId, nonce, maxPriorityFeePerGas, maxFeePerGas, gasLimit, to, value, data, accessList]))\n"). -spec create_eip1559_signing_hash(eip1559_transaction()) -> bitstring(). create_eip1559_signing_hash(Transaction) -> Items = {rlp_list, [gleeth@encoding@rlp:encode_int(erlang:element(9, Transaction)), gleeth@encoding@rlp:encode_hex_field(erlang:element(7, Transaction)), gleeth@encoding@rlp:encode_hex_field(erlang:element(6, Transaction)), gleeth@encoding@rlp:encode_hex_field(erlang:element(5, Transaction)), gleeth@encoding@rlp:encode_hex_field(erlang:element(4, Transaction)), encode_raw_hex(erlang:element(2, Transaction)), gleeth@encoding@rlp:encode_hex_field(erlang:element(3, Transaction)), encode_raw_hex(erlang:element(8, Transaction)), encode_access_list(erlang:element(10, Transaction))]}, Payload = gleeth@encoding@rlp:encode(Items), gleeth@crypto@keccak:keccak256_binary(<<16#02, Payload/bitstring>>). -file("src/gleeth/crypto/transaction.gleam", 466). ?DOC(" Strip leading zero bytes for minimal big-endian integer encoding\n"). -spec strip_leading_zeros(bitstring()) -> bitstring(). strip_leading_zeros(Data) -> case Data of <<0:8, Rest/bitstring>> -> strip_leading_zeros(Rest); _ -> Data end. -file("src/gleeth/crypto/transaction.gleam", 381). ?DOC(" RLP-encode the signed transaction: [nonce, gasPrice, gasLimit, to, value, data, v, r, s]\n"). -spec create_raw_transaction( unsigned_transaction(), integer(), bitstring(), bitstring() ) -> binary(). create_raw_transaction(Transaction, V, R, S) -> Items = {rlp_list, [gleeth@encoding@rlp:encode_hex_field(erlang:element(6, Transaction)), gleeth@encoding@rlp:encode_hex_field(erlang:element(5, Transaction)), gleeth@encoding@rlp:encode_hex_field(erlang:element(4, Transaction)), encode_raw_hex(erlang:element(2, Transaction)), gleeth@encoding@rlp:encode_hex_field(erlang:element(3, Transaction)), encode_raw_hex(erlang:element(7, Transaction)), gleeth@encoding@rlp:encode_int(V), {rlp_bytes, strip_leading_zeros(R)}, {rlp_bytes, strip_leading_zeros(S)}]}, gleeth@utils@hex:encode(gleeth@encoding@rlp:encode(Items)). -file("src/gleeth/crypto/transaction.gleam", 277). ?DOC( " Sign a legacy (EIP-155) transaction with a wallet.\n" " Produces an RLP-encoded raw transaction suitable for eth_sendRawTransaction.\n" ). -spec sign_transaction(unsigned_transaction(), gleeth@crypto@wallet:wallet()) -> {ok, signed_transaction()} | {error, transaction_error()}. sign_transaction(Transaction, Wallet) -> Signing_hash = create_signing_hash(Transaction), gleam@result:'try'( begin _pipe = gleeth@crypto@wallet:sign_hash(Wallet, Signing_hash), gleam@result:map_error( _pipe, fun(Err) -> {signing_failed, <<"Failed to sign transaction: "/utf8, (gleeth@crypto@wallet:error_to_string(Err))/binary>>} end ) end, fun(Signature) -> Eip155_v = (erlang:element(4, Signature) + (2 * erlang:element( 8, Transaction ))) + 35, V_hex = <<"0x"/utf8, (string:lowercase(gleam@int:to_base16(Eip155_v)))/binary>>, R_hex = gleeth@utils@hex:encode(erlang:element(2, Signature)), S_hex = gleeth@utils@hex:encode(erlang:element(3, Signature)), Raw_tx = create_raw_transaction( Transaction, Eip155_v, erlang:element(2, Signature), erlang:element(3, Signature) ), {ok, {signed_transaction, erlang:element(2, Transaction), erlang:element(3, Transaction), erlang:element(4, Transaction), erlang:element(5, Transaction), erlang:element(6, Transaction), erlang:element(7, Transaction), erlang:element(8, Transaction), V_hex, R_hex, S_hex, Raw_tx}} end ). -file("src/gleeth/crypto/transaction.gleam", 421). ?DOC(" RLP-encode the signed EIP-1559 transaction: 0x02 || RLP([chainId, nonce, maxPriorityFeePerGas, maxFeePerGas, gasLimit, to, value, data, accessList, v, r, s])\n"). -spec create_eip1559_raw_transaction( eip1559_transaction(), integer(), bitstring(), bitstring() ) -> binary(). create_eip1559_raw_transaction(Transaction, V, R, S) -> Items = {rlp_list, [gleeth@encoding@rlp:encode_int(erlang:element(9, Transaction)), gleeth@encoding@rlp:encode_hex_field(erlang:element(7, Transaction)), gleeth@encoding@rlp:encode_hex_field(erlang:element(6, Transaction)), gleeth@encoding@rlp:encode_hex_field(erlang:element(5, Transaction)), gleeth@encoding@rlp:encode_hex_field(erlang:element(4, Transaction)), encode_raw_hex(erlang:element(2, Transaction)), gleeth@encoding@rlp:encode_hex_field(erlang:element(3, Transaction)), encode_raw_hex(erlang:element(8, Transaction)), encode_access_list(erlang:element(10, Transaction)), gleeth@encoding@rlp:encode_int(V), {rlp_bytes, strip_leading_zeros(R)}, {rlp_bytes, strip_leading_zeros(S)}]}, Payload = gleeth@encoding@rlp:encode(Items), gleeth@utils@hex:encode(<<16#02, Payload/bitstring>>). -file("src/gleeth/crypto/transaction.gleam", 318). ?DOC( " Sign an EIP-1559 (Type 2) transaction with a wallet.\n" " Produces a type-prefixed RLP-encoded raw transaction: 0x02 || RLP([...]).\n" ). -spec sign_eip1559_transaction( eip1559_transaction(), gleeth@crypto@wallet:wallet() ) -> {ok, signed_eip1559_transaction()} | {error, transaction_error()}. sign_eip1559_transaction(Transaction, Wallet) -> Signing_hash = create_eip1559_signing_hash(Transaction), gleam@result:'try'( begin _pipe = gleeth@crypto@wallet:sign_hash(Wallet, Signing_hash), gleam@result:map_error( _pipe, fun(Err) -> {signing_failed, <<"Failed to sign transaction: "/utf8, (gleeth@crypto@wallet:error_to_string(Err))/binary>>} end ) end, fun(Signature) -> V = erlang:element(4, Signature), V_hex = <<"0x"/utf8, (string:lowercase(gleam@int:to_base16(V)))/binary>>, R_hex = gleeth@utils@hex:encode(erlang:element(2, Signature)), S_hex = gleeth@utils@hex:encode(erlang:element(3, Signature)), Raw_tx = create_eip1559_raw_transaction( Transaction, V, erlang:element(2, Signature), erlang:element(3, Signature) ), {ok, {signed_eip1559_transaction, erlang:element(2, Transaction), erlang:element(3, Transaction), erlang:element(4, Transaction), erlang:element(5, Transaction), erlang:element(6, Transaction), erlang:element(7, Transaction), erlang:element(8, Transaction), erlang:element(9, Transaction), erlang:element(10, Transaction), V_hex, R_hex, S_hex, Raw_tx}} end ). -file("src/gleeth/crypto/transaction.gleam", 530). ?DOC(" Validate chain ID\n"). -spec validate_chain_id(integer()) -> {ok, nil} | {error, transaction_error()}. validate_chain_id(Chain_id) -> case Chain_id > 0 of true -> {ok, nil}; false -> {error, {invalid_chain_id, <<"Chain ID must be positive"/utf8>>}} end. -file("src/gleeth/crypto/transaction.gleam", 538). ?DOC(" Check if character is valid hex\n"). -spec is_hex_char(binary()) -> boolean(). is_hex_char(Char) -> case Char of <<"0"/utf8>> -> true; <<"1"/utf8>> -> true; <<"2"/utf8>> -> true; <<"3"/utf8>> -> true; <<"4"/utf8>> -> true; <<"5"/utf8>> -> true; <<"6"/utf8>> -> true; <<"7"/utf8>> -> true; <<"8"/utf8>> -> true; <<"9"/utf8>> -> true; <<"a"/utf8>> -> true; <<"b"/utf8>> -> true; <<"c"/utf8>> -> true; <<"d"/utf8>> -> true; <<"e"/utf8>> -> true; <<"f"/utf8>> -> true; <<"A"/utf8>> -> true; <<"B"/utf8>> -> true; <<"C"/utf8>> -> true; <<"D"/utf8>> -> true; <<"E"/utf8>> -> true; <<"F"/utf8>> -> true; _ -> false end. -file("src/gleeth/crypto/transaction.gleam", 478). ?DOC(" Validate Ethereum address format\n"). -spec validate_address(binary()) -> {ok, nil} | {error, transaction_error()}. validate_address(Address) -> Cleaned = case gleam_stdlib:string_starts_with(Address, <<"0x"/utf8>>) of true -> gleam@string:drop_start(Address, 2); false -> Address end, case string:length(Cleaned) of 40 -> case begin _pipe = gleam@string:to_graphemes(Cleaned), gleam@list:all(_pipe, fun is_hex_char/1) end of true -> {ok, nil}; false -> {error, {invalid_address, <<"Address contains non-hex characters"/utf8>>}} end; 0 -> {ok, nil}; _ -> {error, {invalid_address, <<"Address must be 40 hex characters"/utf8>>}} end. -file("src/gleeth/crypto/transaction.gleam", 498). ?DOC(" Validate hex amount (like value, gas, nonce)\n"). -spec validate_hex_amount(binary()) -> {ok, nil} | {error, transaction_error()}. validate_hex_amount(Amount) -> Cleaned = case gleam_stdlib:string_starts_with(Amount, <<"0x"/utf8>>) of true -> gleam@string:drop_start(Amount, 2); false -> Amount end, case begin _pipe = gleam@string:to_graphemes(Cleaned), gleam@list:all(_pipe, fun is_hex_char/1) end of true -> {ok, nil}; false -> {error, {invalid_amount, <<"Amount contains non-hex characters"/utf8>>}} end. -file("src/gleeth/crypto/transaction.gleam", 511). ?DOC(" Validate hex data\n"). -spec validate_hex_data(binary()) -> {ok, nil} | {error, transaction_error()}. validate_hex_data(Data) -> case Data of <<"0x"/utf8>> -> {ok, nil}; _ -> Cleaned = case gleam_stdlib:string_starts_with(Data, <<"0x"/utf8>>) of true -> gleam@string:drop_start(Data, 2); false -> Data end, case begin _pipe = gleam@string:to_graphemes(Cleaned), gleam@list:all(_pipe, fun is_hex_char/1) end of true -> {ok, nil}; false -> {error, {invalid_data, <<"Data contains non-hex characters"/utf8>>}} end end. -file("src/gleeth/crypto/transaction.gleam", 552). ?DOC(" Normalize address to lowercase with 0x prefix\n"). -spec normalize_address(binary()) -> binary(). normalize_address(Address) -> case Address of <<""/utf8>> -> <<""/utf8>>; _ -> Cleaned = case gleam_stdlib:string_starts_with( Address, <<"0x"/utf8>> ) of true -> gleam@string:drop_start(Address, 2); false -> Address end, <<"0x"/utf8, (string:lowercase(Cleaned))/binary>> end. -file("src/gleeth/crypto/transaction.gleam", 566). ?DOC(" Normalize hex string to lowercase with 0x prefix\n"). -spec normalize_hex(binary()) -> binary(). normalize_hex(Hex) -> Cleaned = case gleam_stdlib:string_starts_with(Hex, <<"0x"/utf8>>) of true -> gleam@string:drop_start(Hex, 2); false -> Hex end, <<"0x"/utf8, (string:lowercase(Cleaned))/binary>>. -file("src/gleeth/crypto/transaction.gleam", 575). ?DOC(" Normalize hex data (keep \"0x\" for empty data)\n"). -spec normalize_hex_data(binary()) -> binary(). normalize_hex_data(Data) -> case Data of <<""/utf8>> -> <<"0x"/utf8>>; <<"0x"/utf8>> -> <<"0x"/utf8>>; _ -> normalize_hex(Data) end. -file("src/gleeth/crypto/transaction.gleam", 147). ?DOC( " Create a new unsigned legacy (Type 0) transaction.\n" "\n" " All numeric parameters must be `0x`-prefixed hex strings. The Ethereum\n" " JSON-RPC API returns values in this format, so results from\n" " `methods.get_gas_price`, `methods.get_transaction_count`, etc. can be\n" " passed directly.\n" "\n" " - `to` - recipient address (`\"0x...\"`, 40 hex chars after prefix)\n" " - `value` - amount in wei as hex (e.g. `\"0xde0b6b3a7640000\"` for 1 ETH)\n" " - `gas_limit` - gas limit as hex (e.g. `\"0x5208\"` for 21000)\n" " - `gas_price` - gas price in wei as hex\n" " - `nonce` - sender's transaction count as hex\n" " - `data` - calldata as hex (`\"0x\"` for simple transfers)\n" " - `chain_id` - network chain ID as integer (1 for mainnet, 11155111 for Sepolia)\n" "\n" " ## Examples\n" "\n" " ```gleam\n" " let assert Ok(tx) = transaction.create_legacy_transaction(\n" " \"0x70997970C51812dc3A010C7d01b50e0d17dc79C8\",\n" " \"0xde0b6b3a7640000\", // 1 ETH in wei\n" " \"0x5208\", // 21000 gas\n" " \"0x3b9aca00\", // 1 gwei gas price\n" " \"0x0\", // nonce 0\n" " \"0x\", // no calldata\n" " 1, // mainnet\n" " )\n" " ```\n" ). -spec create_legacy_transaction( binary(), binary(), binary(), binary(), binary(), binary(), integer() ) -> {ok, unsigned_transaction()} | {error, transaction_error()}. create_legacy_transaction( To, Value, Gas_limit, Gas_price, Nonce, Data, Chain_id ) -> gleam@result:'try'( validate_address(To), fun(_) -> gleam@result:'try'( validate_hex_amount(Value), fun(_) -> gleam@result:'try'( validate_hex_amount(Gas_limit), fun(_) -> gleam@result:'try'( validate_hex_amount(Gas_price), fun(_) -> gleam@result:'try'( validate_hex_amount(Nonce), fun(_) -> gleam@result:'try'( validate_hex_data(Data), fun(_) -> gleam@result:'try'( validate_chain_id( Chain_id ), fun(_) -> {ok, {unsigned_transaction, normalize_address( To ), normalize_hex( Value ), normalize_hex( Gas_limit ), normalize_hex( Gas_price ), normalize_hex( Nonce ), normalize_hex_data( Data ), Chain_id}} end ) end ) end ) end ) end ) end ) end ). -file("src/gleeth/crypto/transaction.gleam", 180). ?DOC( " Create a simple ETH transfer transaction (no calldata).\n" "\n" " Convenience wrapper around `create_legacy_transaction` with `data` set to\n" " `\"0x\"`. All numeric parameters are `0x`-prefixed hex strings.\n" ). -spec create_eth_transfer( binary(), binary(), binary(), binary(), binary(), integer() ) -> {ok, unsigned_transaction()} | {error, transaction_error()}. create_eth_transfer(To, Value_wei, Gas_limit, Gas_price, Nonce, Chain_id) -> create_legacy_transaction( To, Value_wei, Gas_limit, Gas_price, Nonce, <<"0x"/utf8>>, Chain_id ). -file("src/gleeth/crypto/transaction.gleam", 203). ?DOC( " Create a contract interaction transaction (zero value).\n" "\n" " Convenience wrapper around `create_legacy_transaction` with `value` set to\n" " `\"0x0\"`. All numeric parameters are `0x`-prefixed hex strings.\n" ). -spec create_contract_call( binary(), binary(), binary(), binary(), binary(), integer() ) -> {ok, unsigned_transaction()} | {error, transaction_error()}. create_contract_call( Contract_address, Call_data, Gas_limit, Gas_price, Nonce, Chain_id ) -> create_legacy_transaction( Contract_address, <<"0x0"/utf8>>, Gas_limit, Gas_price, Nonce, Call_data, Chain_id ). -file("src/gleeth/crypto/transaction.gleam", 238). ?DOC( " Create and validate an EIP-1559 (Type 2) transaction.\n" "\n" " All numeric parameters must be `0x`-prefixed hex strings. Fee parameters\n" " from `methods.get_gas_price` and `methods.get_max_priority_fee` can be\n" " passed directly.\n" "\n" " - `to` - recipient address\n" " - `value` - amount in wei as hex\n" " - `gas_limit` - gas limit as hex\n" " - `max_fee_per_gas` - maximum total fee per gas in wei as hex\n" " - `max_priority_fee_per_gas` - tip per gas in wei as hex\n" " - `nonce` - sender's transaction count as hex\n" " - `data` - calldata as hex (`\"0x\"` for simple transfers)\n" " - `chain_id` - network chain ID as integer\n" " - `access_list` - EIP-2930 access list (pass `[]` if not needed)\n" ). -spec create_eip1559_transaction( binary(), binary(), binary(), binary(), binary(), binary(), binary(), integer(), list(access_list_entry()) ) -> {ok, eip1559_transaction()} | {error, transaction_error()}. create_eip1559_transaction( To, Value, Gas_limit, Max_fee_per_gas, Max_priority_fee_per_gas, Nonce, Data, Chain_id, Access_list ) -> gleam@result:'try'( validate_address(To), fun(_) -> gleam@result:'try'( validate_hex_amount(Value), fun(_) -> gleam@result:'try'( validate_hex_amount(Gas_limit), fun(_) -> gleam@result:'try'( validate_hex_amount(Max_fee_per_gas), fun(_) -> gleam@result:'try'( validate_hex_amount( Max_priority_fee_per_gas ), fun(_) -> gleam@result:'try'( validate_hex_amount(Nonce), fun(_) -> gleam@result:'try'( validate_hex_data(Data), fun(_) -> gleam@result:'try'( validate_chain_id( Chain_id ), fun(_) -> {ok, {eip1559_transaction, normalize_address( To ), normalize_hex( Value ), normalize_hex( Gas_limit ), normalize_hex( Max_fee_per_gas ), normalize_hex( Max_priority_fee_per_gas ), normalize_hex( Nonce ), normalize_hex_data( Data ), Chain_id, Access_list}} end ) end ) end ) end ) end ) end ) end ) end ). -file("src/gleeth/crypto/transaction.gleam", 588). ?DOC(" Convert signed transaction to string for display\n"). -spec signed_transaction_to_string(signed_transaction()) -> binary(). signed_transaction_to_string(Tx) -> <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"SignedTransaction {\n"/utf8, " to: "/utf8>>/binary, (erlang:element( 2, Tx ))/binary>>/binary, "\n"/utf8>>/binary, " value: "/utf8>>/binary, (erlang:element( 3, Tx ))/binary>>/binary, "\n"/utf8>>/binary, " gas_limit: "/utf8>>/binary, (erlang:element( 4, Tx ))/binary>>/binary, "\n"/utf8>>/binary, " gas_price: "/utf8>>/binary, (erlang:element( 5, Tx ))/binary>>/binary, "\n"/utf8>>/binary, " nonce: "/utf8>>/binary, (erlang:element( 6, Tx ))/binary>>/binary, "\n"/utf8>>/binary, " data: "/utf8>>/binary, (erlang:element( 7, Tx ))/binary>>/binary, "\n"/utf8>>/binary, " chain_id: "/utf8>>/binary, (erlang:integer_to_binary( erlang:element( 8, Tx ) ))/binary>>/binary, "\n"/utf8>>/binary, " v: "/utf8>>/binary, (erlang:element(9, Tx))/binary>>/binary, "\n"/utf8>>/binary, " r: "/utf8>>/binary, (erlang:element(10, Tx))/binary>>/binary, "\n"/utf8>>/binary, " s: "/utf8>>/binary, (erlang:element(11, Tx))/binary>>/binary, "\n"/utf8>>/binary, " raw: "/utf8>>/binary, (erlang:element(12, Tx))/binary>>/binary, "\n"/utf8>>/binary, "}"/utf8>>. -file("src/gleeth/crypto/transaction.gleam", 637). ?DOC(" Hash a raw transaction hex string to get its transaction hash\n"). -spec hash_raw_transaction(binary()) -> binary(). hash_raw_transaction(Raw_transaction) -> case gleeth@utils@hex:decode(Raw_transaction) of {ok, Raw_bytes} -> gleeth@utils@hex:encode( gleeth@crypto@keccak:keccak256_binary(Raw_bytes) ); {error, _} -> <<""/utf8>> end. -file("src/gleeth/crypto/transaction.gleam", 627). ?DOC(" Get transaction hash from a signed legacy transaction\n"). -spec get_transaction_hash(signed_transaction()) -> binary(). get_transaction_hash(Tx) -> hash_raw_transaction(erlang:element(12, Tx)). -file("src/gleeth/crypto/transaction.gleam", 632). ?DOC(" Get transaction hash from a signed EIP-1559 transaction\n"). -spec get_eip1559_transaction_hash(signed_eip1559_transaction()) -> binary(). get_eip1559_transaction_hash(Tx) -> hash_raw_transaction(erlang:element(14, Tx)). -file("src/gleeth/crypto/transaction.gleam", 645). ?DOC(" Convert signed EIP-1559 transaction to string for display\n"). -spec signed_eip1559_transaction_to_string(signed_eip1559_transaction()) -> binary(). signed_eip1559_transaction_to_string(Tx) -> <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"SignedEip1559Transaction {\n"/utf8, " to: "/utf8>>/binary, (erlang:element( 2, Tx ))/binary>>/binary, "\n"/utf8>>/binary, " value: "/utf8>>/binary, (erlang:element( 3, Tx ))/binary>>/binary, "\n"/utf8>>/binary, " gas_limit: "/utf8>>/binary, (erlang:element( 4, Tx ))/binary>>/binary, "\n"/utf8>>/binary, " max_fee_per_gas: "/utf8>>/binary, (erlang:element( 5, Tx ))/binary>>/binary, "\n"/utf8>>/binary, " max_priority_fee_per_gas: "/utf8>>/binary, (erlang:element( 6, Tx ))/binary>>/binary, "\n"/utf8>>/binary, " nonce: "/utf8>>/binary, (erlang:element( 7, Tx ))/binary>>/binary, "\n"/utf8>>/binary, " data: "/utf8>>/binary, (erlang:element( 8, Tx ))/binary>>/binary, "\n"/utf8>>/binary, " chain_id: "/utf8>>/binary, (erlang:integer_to_binary( erlang:element( 9, Tx ) ))/binary>>/binary, "\n"/utf8>>/binary, " v: "/utf8>>/binary, (erlang:element(11, Tx))/binary>>/binary, "\n"/utf8>>/binary, " r: "/utf8>>/binary, (erlang:element(12, Tx))/binary>>/binary, "\n"/utf8>>/binary, " s: "/utf8>>/binary, (erlang:element(13, Tx))/binary>>/binary, "\n"/utf8>>/binary, " raw: "/utf8>>/binary, (erlang:element(14, Tx))/binary>>/binary, "\n"/utf8>>/binary, "}"/utf8>>. -file("src/gleeth/crypto/transaction.gleam", 689). ?DOC(" Convert TransactionError to string\n"). -spec error_to_string(transaction_error()) -> binary(). error_to_string(Error) -> case Error of {invalid_address, Msg} -> <<"Invalid address: "/utf8, Msg/binary>>; {invalid_amount, Msg@1} -> <<"Invalid amount: "/utf8, Msg@1/binary>>; {invalid_gas, Msg@2} -> <<"Invalid gas: "/utf8, Msg@2/binary>>; {invalid_nonce, Msg@3} -> <<"Invalid nonce: "/utf8, Msg@3/binary>>; {invalid_chain_id, Msg@4} -> <<"Invalid chain ID: "/utf8, Msg@4/binary>>; {invalid_data, Msg@5} -> <<"Invalid data: "/utf8, Msg@5/binary>>; {signing_failed, Msg@6} -> <<"Signing failed: "/utf8, Msg@6/binary>>; {encoding_failed, Msg@7} -> <<"Encoding failed: "/utf8, Msg@7/binary>> end.