diff --git a/ethers/contract.nim b/ethers/contract.nim index 9b9695c..cb62d48 100644 --- a/ethers/contract.nim +++ b/ethers/contract.nim @@ -69,7 +69,7 @@ proc createTransaction(contract: Contract, let data = @selector & AbiEncoder.encode(parameters) Transaction( to: contract.address, - data: some data, + data: data, nonce: overrides.nonce, chainId: overrides.chainId, gasPrice: overrides.gasPrice, @@ -259,6 +259,8 @@ proc confirm*(tx: Future[?TransactionResponse], let receipt = await response.confirm(confirmations, timeout) if receipt.status != TransactionStatus.Success: + logScope: + transactionHash = receipt.transactionHash echo "[ethers contract] transaction failed, status: ", receipt.status trace "transaction failed", status = receipt.status without blockNumber =? receipt.blockNumber: diff --git a/ethers/providers/jsonrpc/conversions.nim b/ethers/providers/jsonrpc/conversions.nim index 6514b57..98ccf41 100644 --- a/ethers/providers/jsonrpc/conversions.nim +++ b/ethers/providers/jsonrpc/conversions.nim @@ -1,4 +1,5 @@ import std/json +import std/strformat import std/strutils import pkg/json_rpc/jsonmarshal import pkg/stew/byteutils @@ -87,3 +88,26 @@ func fromJson*(json: JsonNode, name: string, result: var TransactionStatus) = func `%`*(status: TransactionStatus): JsonNode = %(status.int.toHex) + +# Transaction + +func fromJson*(json: JsonNode, name: string, result: var Transaction) = + # Deserializes a transaction response, eg eth_getTransactionByHash. + # Spec: https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_gettransactionbyhash + let expectedFields = + @["input", "from", "to", "value", "nonce", "chainId", "gasPrice"] + + for fieldName in expectedFields: + if not json.hasKey(fieldName): + raise newException(ValueError, + fmt"'{fieldName}' field not found in ${json}") + + result = Transaction( + sender: fromJson(?Address, json["from"], "from"), + to: Address.fromJson(json["to"], "to"), + data: seq[byte].fromJson(json["input"], "input"), + value: UInt256.fromJson(json["value"], "value"), + nonce: fromJson(?UInt256, json["nonce"], "nonce"), + chainId: fromJson(?UInt256, json["chainId"], "chainId"), + gasPrice: fromJson(?UInt256, json["gasPrice"], "gasPrice") + ) \ No newline at end of file diff --git a/ethers/transaction.nim b/ethers/transaction.nim index 1c1e7f9..29c7418 100644 --- a/ethers/transaction.nim +++ b/ethers/transaction.nim @@ -4,7 +4,7 @@ import ./basics type Transaction* = object sender*: ?Address to*: Address - data*: ?seq[byte] + data*: seq[byte] value*: UInt256 nonce*: ?UInt256 chainId*: ?UInt256 @@ -19,7 +19,7 @@ func `$`*(transaction: Transaction): string = result &= "from: " & $sender & ", " result &= "to: " & $transaction.to & ", " result &= "value: " & $transaction.value & ", " - result &= "data: 0x" & $(transaction.data.?toHex) + result &= "data: 0x" & $(transaction.data.toHex) if nonce =? transaction.nonce: result &= ", nonce: " & $nonce if chainId =? transaction.chainId: diff --git a/ethers/wallet/signing.nim b/ethers/wallet/signing.nim index 734e8b2..b56e406 100644 --- a/ethers/wallet/signing.nim +++ b/ethers/wallet/signing.nim @@ -26,7 +26,7 @@ func toSignableTransaction(transaction: Transaction): SignableTransaction = signable.gasLimit = GasInt(gasLimit.truncate(uint64)) signable.to = some EthAddress(transaction.to) signable.value = transaction.value - signable.payload = transaction.data |? newSeq[byte]() + signable.payload = transaction.data if maxFee =? transaction.maxFee and maxPriorityFee =? transaction.maxPriorityFee: diff --git a/testmodule/examples.nim b/testmodule/examples.nim index d2fc4f4..dfd7345 100644 --- a/testmodule/examples.nim +++ b/testmodule/examples.nim @@ -21,4 +21,4 @@ proc example*(_: type UInt256): UInt256 = UInt256.fromBytesBE(array[32, byte].example) proc example*(_: type Transaction): Transaction = - Transaction(to: Address.example, data: some seq[byte].example) + Transaction(to: Address.example, data: seq[byte].example) diff --git a/testmodule/providers/jsonrpc/testConversions.nim b/testmodule/providers/jsonrpc/testConversions.nim index 05edafb..d94e856 100644 --- a/testmodule/providers/jsonrpc/testConversions.nim +++ b/testmodule/providers/jsonrpc/testConversions.nim @@ -119,7 +119,7 @@ suite "JSON Conversions": expect ValueError: discard Log.fromJson(parseJson(json)) - test "missing data in Transaction isNone": + test "getTransactionByHash correctly deserializes 'data' field from 'input' for Transaction": let json = %*{ "blockHash":"0x595bffbe897e025ea2df3213c4cc52c3f3d69bc04b49011d558f1b0e70038922", "blockNumber":"0x22e", @@ -140,4 +140,4 @@ suite "JSON Conversions": } let receipt = Transaction.fromJson(json) - check receipt.data.isNone + check receipt.data.len > 0 diff --git a/testmodule/testWallet.nim b/testmodule/testWallet.nim index 4a8845b..703ccf5 100644 --- a/testmodule/testWallet.nim +++ b/testmodule/testWallet.nim @@ -66,7 +66,7 @@ suite "Wallet": gasPrice: some 20 * 10.u256.pow(9), gasLimit: some 21000.u256, value: 10.u256.pow(18), - data: none seq[byte] + data: @[] ) let signed = await wallet.signTransaction(transaction) check signed.toHex == "f86c098504a817c800825208943535353535353535353535353535353535353535880de0b6b3a76400008025a028ef61340bd939bc2195fe537567866003e1a15d3c71ff63e1590620aa636276a067cbe9d8997f761aecb703304b3800ccf555c9f3dc64214b297fb1966a3b6d83"