Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add missing fields to the response of eth_getTransactionByHash #309

Merged
merged 2 commits into from
Jun 18, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ func (b *BlockChainAPI) GetTransactionByHash(
return handleError[*Transaction](b.logger, err)
}

return NewTransaction(tx, *rcp)
return NewTransaction(tx, *rcp, *b.config)
}

// GetTransactionByBlockHashAndIndex returns the transaction for the given block hash and index.
Expand Down
65 changes: 54 additions & 11 deletions api/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package api

import (
errs "github.com/onflow/flow-evm-gateway/api/errors"
"github.com/onflow/flow-evm-gateway/config"
"github.com/onflow/flow-evm-gateway/models"

"github.com/onflow/go-ethereum/common"
Expand Down Expand Up @@ -91,7 +92,11 @@ type Transaction struct {
YParity *hexutil.Uint64 `json:"yParity,omitempty"`
}

func NewTransaction(tx models.Transaction, receipt types.Receipt) (*Transaction, error) {
func NewTransaction(
tx models.Transaction,
receipt types.Receipt,
config config.Config,
) (*Transaction, error) {
txHash, err := tx.Hash()
if err != nil {
return nil, err
Expand All @@ -112,23 +117,61 @@ func NewTransaction(tx models.Transaction, receipt types.Receipt) (*Transaction,
v, r, s := tx.RawSignatureValues()
index := uint64(receipt.TransactionIndex)

return &Transaction{
Hash: txHash,
BlockHash: &receipt.BlockHash,
BlockNumber: (*hexutil.Big)(receipt.BlockNumber),
result := &Transaction{
Type: hexutil.Uint64(tx.Type()),
From: from,
To: to,
Gas: hexutil.Uint64(receipt.GasUsed),
GasPrice: (*hexutil.Big)(receipt.EffectiveGasPrice),
Gas: hexutil.Uint64(tx.Gas()),
GasPrice: (*hexutil.Big)(tx.GasPrice()),
Hash: txHash,
Input: tx.Data(),
Nonce: hexutil.Uint64(tx.Nonce()),
TransactionIndex: (*hexutil.Uint64)(&index),
To: to,
Value: (*hexutil.Big)(tx.Value()),
Type: hexutil.Uint64(tx.Type()),
V: (*hexutil.Big)(v),
R: (*hexutil.Big)(r),
S: (*hexutil.Big)(s),
}, nil
BlockHash: &receipt.BlockHash,
BlockNumber: (*hexutil.Big)(receipt.BlockNumber),
TransactionIndex: (*hexutil.Uint64)(&index),
}
chainID := config.EVMNetworkID

switch tx.Type() {
case types.LegacyTxType:
result.ChainID = (*hexutil.Big)(chainID)
case types.AccessListTxType:
al := tx.AccessList()
yparity := hexutil.Uint64(v.Sign())
result.Accesses = &al
result.ChainID = (*hexutil.Big)(chainID)
result.YParity = &yparity
case types.DynamicFeeTxType:
al := tx.AccessList()
yparity := hexutil.Uint64(v.Sign())
result.Accesses = &al
result.ChainID = (*hexutil.Big)(chainID)
result.YParity = &yparity
result.GasFeeCap = (*hexutil.Big)(tx.GasFeeCap())
result.GasTipCap = (*hexutil.Big)(tx.GasTipCap())
// Since BaseFee is `0`, this is the effective gas price
// the sender is willing to pay.
result.GasPrice = (*hexutil.Big)(tx.GasFeeCap())
case types.BlobTxType:
al := tx.AccessList()
yparity := hexutil.Uint64(v.Sign())
result.Accesses = &al
result.ChainID = (*hexutil.Big)(chainID)
result.YParity = &yparity
result.GasFeeCap = (*hexutil.Big)(tx.GasFeeCap())
result.GasTipCap = (*hexutil.Big)(tx.GasTipCap())
// Since BaseFee is `0`, this is the effective gas price
// the sender is willing to pay.
result.GasPrice = (*hexutil.Big)(tx.GasFeeCap())
result.MaxFeePerBlobGas = (*hexutil.Big)(tx.BlobGasFeeCap())
result.BlobVersionedHashes = tx.BlobHashes()
}

return result, nil
}

// SignTransactionResult represents a RLP encoded signed transaction.
Expand Down
2 changes: 1 addition & 1 deletion api/stream.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ func (s *StreamAPI) NewPendingTransactions(ctx context.Context, fullTx *bool) (*
return nil, fmt.Errorf("failed to compute tx hash: %w", err)
}

t, err := NewTransaction(tx, *rcp)
t, err := NewTransaction(tx, *rcp, *s.config)
if err != nil {
return nil, err
}
Expand Down
25 changes: 25 additions & 0 deletions models/transaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,14 @@ type Transaction interface {
Value() *big.Int
Type() uint8
Gas() uint64
GasFeeCap() *big.Int
GasTipCap() *big.Int
GasPrice() *big.Int
BlobGas() uint64
BlobGasFeeCap() *big.Int
BlobHashes() []common.Hash
Size() uint64
AccessList() gethTypes.AccessList
MarshalBinary() ([]byte, error)
}

Expand Down Expand Up @@ -79,6 +84,14 @@ func (dc DirectCall) Gas() uint64 {
return dc.DirectCall.GasLimit
}

func (dc DirectCall) GasFeeCap() *big.Int {
return big.NewInt(0)
}

func (dc DirectCall) GasTipCap() *big.Int {
return big.NewInt(0)
}

func (dc DirectCall) GasPrice() *big.Int {
return big.NewInt(0)
}
Expand All @@ -87,6 +100,14 @@ func (dc DirectCall) BlobGas() uint64 {
return 0
}

func (dc DirectCall) BlobGasFeeCap() *big.Int {
return big.NewInt(0)
}

func (dc DirectCall) BlobHashes() []common.Hash {
return []common.Hash{}
}

func (dc DirectCall) Size() uint64 {
encoded, err := dc.MarshalBinary()
if err != nil {
Expand All @@ -95,6 +116,10 @@ func (dc DirectCall) Size() uint64 {
return uint64(len(encoded))
}

func (dc DirectCall) AccessList() gethTypes.AccessList {
return gethTypes.AccessList{}
}

func (dc DirectCall) MarshalBinary() ([]byte, error) {
return dc.DirectCall.Encode()
}
Expand Down
8 changes: 6 additions & 2 deletions tests/e2e_web3js_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ func TestWeb3_E2E(t *testing.T) {
runWeb3Test(t, "eth_deploy_contract_and_interact_test")
})

t.Run("eth_getTransactionByHash", func(t *testing.T) {
runWeb3Test(t, "eth_get_transaction_by_hash_test")
})

t.Run("transfer Flow between EOA accounts", func(t *testing.T) {
runWeb3Test(t, "eth_transfer_between_eoa_accounts_test")
})
Expand All @@ -38,10 +42,10 @@ func TestWeb3_E2E(t *testing.T) {
runWeb3Test(t, "eth_get_filter_logs_test")
})

t.Run("rate-limit requests made by single client", func(t *testing.T) {
t.Run("rate-limit requests made by single client", func(t *testing.T) {
runWeb3Test(t, "eth_rate_limit_test")
})

t.Run("batch run transactions", func(t *testing.T) {
// create multiple value transfers and batch run them before the test
runWeb3TestWithSetup(t, "eth_batch_retrieval_test", func(emu emulator.Emulator) {
Expand Down
33 changes: 33 additions & 0 deletions tests/web3js/eth_get_transaction_by_hash_test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
const { assert } = require('chai')
const conf = require('./config')
const helpers = require('./helpers')
const web3 = conf.web3

it('returns proper response for eth_getTransactionByHash', async () => {
let deployed = await helpers.deployContract('storage')
let contractAddress = deployed.receipt.contractAddress

// make sure deploy results are correct
assert.equal(deployed.receipt.status, conf.successStatus)

let updateData = deployed.contract.methods.store(1337).encodeABI()
let result = await helpers.signAndSend({
from: conf.eoa.address,
to: contractAddress,
data: updateData,
gas: 25000,
value: 0,
maxFeePerGas: 3000000000,
maxPriorityFeePerGas: 800000000,
})
assert.equal(result.receipt.status, conf.successStatus)

let tx = await web3.eth.getTransactionFromBlock(result.receipt.blockNumber, 0)
assert.equal(tx.type, 2n)
assert.deepEqual(tx.accessList, [])
assert.equal(tx.chainId, 646n)
assert.equal(tx.gas, 25000n)
assert.equal(tx.maxFeePerGas, 3000000000n)
assert.equal(tx.maxPriorityFeePerGas, 800000000n)
assert.equal(tx.gasPrice, 3000000000n)
}).timeout(10 * 1000)
7 changes: 3 additions & 4 deletions tests/web3js/eth_non_interactive_test.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
const web3Utils = require('web3-utils')
const { assert } = require('chai')
const conf = require('./config')
const helpers = require('./helpers')
const web3 = conf.web3

it('get chain ID', async () => {
Expand Down Expand Up @@ -78,7 +77,7 @@ it('get transaction', async () => {
assert.deepEqual(blockTx, tx)
assert.isString(tx.hash)
assert.equal(tx.blockNumber, conf.startBlockHeight)
assert.isAbove(parseInt(tx.gas), 1)
assert.equal(tx.gas, 300000n)
assert.isNotEmpty(tx.from)
assert.isNotEmpty(tx.r)
assert.isNotEmpty(tx.s)
Expand All @@ -90,10 +89,10 @@ it('get transaction', async () => {
assert.equal(rcp.blockNumber, conf.startBlockHeight)
assert.equal(rcp.from, tx.from)
assert.equal(rcp.to, tx.to)
assert.equal(rcp.cumulativeGasUsed, tx.gas) // todo check
assert.equal(rcp.cumulativeGasUsed, 21000n) // todo check
assert.equal(rcp.transactionHash, tx.hash)
assert.equal(rcp.status, conf.successStatus)
assert.equal(rcp.gasUsed, tx.gas)
assert.equal(rcp.gasUsed, 21000n)
})

it('get mining status', async () => {
Expand Down
Loading