rename sender to from, update json error logging, add more conversions

This commit is contained in:
Eric 2024-01-25 17:20:04 +11:00
parent 526d954a01
commit c261e96274
No known key found for this signature in database
8 changed files with 50 additions and 64 deletions

View File

@ -101,8 +101,8 @@ proc call(contract: Contract,
overrides = TransactionOverrides()) {.async.} =
var transaction = createTransaction(contract, function, parameters, overrides)
if signer =? contract.signer and transaction.sender.isNone:
transaction.sender = some(await signer.getAddress())
if signer =? contract.signer and transaction.`from`.isNone:
transaction.`from` = some(await signer.getAddress())
discard await contract.provider.call(transaction, overrides)
@ -114,8 +114,8 @@ proc call(contract: Contract,
overrides = TransactionOverrides()): Future[ReturnType] {.async.} =
var transaction = createTransaction(contract, function, parameters, overrides)
if signer =? contract.signer and transaction.sender.isNone:
transaction.sender = some(await signer.getAddress())
if signer =? contract.signer and transaction.`from`.isNone:
transaction.`from` = some(await signer.getAddress())
let response = await contract.provider.call(transaction, overrides)
return decodeResponse(ReturnType, returnMultiple, response)

View File

@ -39,7 +39,7 @@ type
provider*: Provider
hash* {.serialize.}: TransactionHash
TransactionReceipt* = object
sender* {.serialize.}: ?Address
`from`* {.serialize.}: ?Address
to* {.serialize.}: ?Address
contractAddress* {.serialize.}: ?Address
transactionIndex* {.serialize.}: UInt256
@ -51,7 +51,7 @@ type
blockNumber* {.serialize.}: ?UInt256
cumulativeGasUsed* {.serialize.}: UInt256
effectiveGasPrice* {.serialize.}: ?UInt256
status*: TransactionStatus
status* {.serialize.}: TransactionStatus
`type`* {.serialize.}: TransactionType
LogHandler* = proc(log: Log) {.gcsafe, raises:[].}
BlockHandler* = proc(blck: Block) {.gcsafe, raises:[].}
@ -63,7 +63,7 @@ type
PastTransaction* = object
blockHash* {.serialize.}: BlockHash
blockNumber* {.serialize.}: UInt256
sender* {.serialize.}: Address
`from`* {.serialize.}: Address
gas* {.serialize.}: UInt256
gasPrice* {.serialize.}: UInt256
hash* {.serialize.}: TransactionHash
@ -87,7 +87,7 @@ template raiseProviderError(msg: string) =
func toTransaction*(past: PastTransaction): Transaction =
Transaction(
sender: some past.sender,
`from`: some past.`from`,
gasPrice: some past.gasPrice,
data: past.input,
nonce: some past.nonce,

View File

@ -31,6 +31,15 @@ proc getOrRaise*[T, E](self: ?!T, exc: typedesc[E]): T {.raises: [E].} =
raise newException(E, self.error.msg)
val
template mapFailure*[T, V, E](
exp: Result[T, V],
exc: typedesc[E],
): Result[T, ref CatchableError] =
## Convert `Result[T, E]` to `Result[E, ref CatchableError]`
##
exp.mapErr(proc (e: V): ref CatchableError = (ref exc)(msg: e.msg))
proc expectFields(json: JsonNode, expectedFields: varargs[string]) =
for fieldName in expectedFields:
if not json.hasKey(fieldName):
@ -161,6 +170,16 @@ func fromJson*(_: type BlockTag, json: JsonNode): ?!BlockTag =
"Failed to convert '" & $json &
"' to BlockTag: must be one of 'earliest', 'latest', 'pending'")
# TransactionStatus | TransactionType
proc fromJson*[E: TransactionStatus | TransactionType](
T: type E,
json: JsonNode
): ?!T =
expectJsonKind(string, JString, json)
let integer = ? fromHex[int](json.str).catch.mapFailure(SerializationError)
success T(integer)
# proc readValue*(r: var JsonReader[JrpcConv],
# result: var BlockTag) {.raises:[SerializationError, IOError].} =
# var json = r.readValue(JsonNode)

View File

@ -10,6 +10,7 @@ import pkg/chronicles
import pkg/contractabi
import pkg/stew/byteutils
import pkg/stint
import pkg/questionable
import pkg/questionable/results
import ../../basics
@ -204,7 +205,6 @@ proc fromJson*[T: ref object or object](
_: type T,
json: JsonNode
): ?!T =
when T is JsonNode:
return success T(json)
@ -212,17 +212,25 @@ proc fromJson*[T: ref object or object](
var res = when type(T) is ref: T.new() else: T.default
# Leave this in, it's good for debugging:
# trace "deserializing object", to = $T, json
trace "deserializing object", to = $T, json
for name, value in fieldPairs(when type(T) is ref: res[] else: res):
if jsonVal =? json{name}.catch and not jsonVal.isNil:
logScope:
field = $T & "." & name
if name in json and
jsonVal =? json{name}.catch and
not jsonVal.isNil:
without parsed =? type(value).fromJson(jsonVal), e:
error "error deserializing field",
field = $T & "." & name,
json = jsonVal,
error = e.msg
return failure(e)
value = parsed
else:
debug "object field does not exist in json, skipping", json
success(res)
proc parse*(json: string): ?!JsonNode =
@ -240,48 +248,6 @@ proc fromJson*[T: ref object or object](
let json = ? parse(string.fromBytes(bytes))
T.fromJson(json)
# import std/streams
# import std/parsejson
# type StringStreamFixed = ref object of StringStream
# closeImplFixed: proc (s: StringStreamFixed)
# {.nimcall, raises: [IOError, OSError], tags: [WriteIOEffect], gcsafe.}
# proc closeImpl*: proc (s: StringStreamFixed)
# {.nimcall, raises: [IOError, OSError], tags: [WriteIOEffect], gcsafe.} = discard
# proc ssCloseFixed(s: StringStreamFixed) =
# # var s = StringStream(s)
# s.data = ""
# proc close*(s: StringStreamFixed) {.raises: [IOError, OSError].} =
# ## Closes the stream `s`.
# ##
# ## See also:
# ## * `flush proc <#flush,Stream>`_
# # runnableExamples:
# # var strm = newStringStream("The first line\nthe second line\nthe third line")
# # ## do something...
# # strm.close()
# if not isNil(s.closeImplFixed): s.closeImplFixed(s)
# proc newStringStreamFixed*(s: sink string = ""): owned StringStreamFixed {.raises:[].} =
# var ss = StringStreamFixed(newStringStream(s))
# ss.closeImplFixed = ssCloseFixed
# ss
# proc parseJson*(buffer: string; rawIntegers = false, rawFloats = false): JsonNode {.raises: [IOError, OSError, JsonParsingError, ValueError].} =
# ## Parses JSON from `buffer`.
# ## If `buffer` contains extra data, it will raise `JsonParsingError`.
# ## If `rawIntegers` is true, integer literals will not be converted to a `JInt`
# ## field but kept as raw numbers via `JString`.
# ## If `rawFloats` is true, floating point literals will not be converted to a `JFloat`
# ## field but kept as raw numbers via `JString`.
# result = parseJson(newStringStreamFixed(buffer), "input", rawIntegers, rawFloats)
proc fromJson*(
_: type JsonNode,
json: string
@ -293,6 +259,7 @@ proc fromJson*[T: ref object or object](
_: type T,
json: string
): ?!T =
echo "[T.fromJson] T: ", T, ", json string: ", json
let json = ? parse(json)
T.fromJson(json)

View File

@ -57,7 +57,7 @@ method estimateGas*(signer: Signer,
transaction: Transaction,
blockTag = BlockTag.latest): Future[UInt256] {.base, async.} =
var transaction = transaction
transaction.sender = some(await signer.getAddress)
transaction.`from` = some(await signer.getAddress)
try:
return await signer.provider.estimateGas(transaction)
except ProviderError as e:
@ -97,7 +97,7 @@ method populateTransaction*(signer: Signer,
Future[Transaction] {.base, async.} =
echo "[signer.populatetransaction] signer type: ", typeof signer
if sender =? transaction.sender and sender != await signer.getAddress():
if sender =? transaction.`from` and sender != await signer.getAddress():
raiseSignerError("from address mismatch")
if chainId =? transaction.chainId and chainId != await signer.getChainId():
raiseSignerError("chain id mismatch")
@ -110,8 +110,8 @@ method populateTransaction*(signer: Signer,
var populated = transaction
try:
if transaction.sender.isNone:
populated.sender = some(await signer.getAddress())
if transaction.`from`.isNone:
populated.`from` = some(await signer.getAddress())
if transaction.chainId.isNone:
populated.chainId = some(await signer.getChainId())
if transaction.gasPrice.isNone and (transaction.maxFee.isNone or transaction.maxPriorityFee.isNone):
@ -150,7 +150,7 @@ method cancelTransaction*(
# cancels a transaction by sending with a 0-valued transaction to ourselves
# with the failed tx's nonce
without sender =? tx.sender:
without sender =? tx.`from`:
raiseSignerError "transaction must have sender"
without nonce =? tx.nonce:
raiseSignerError "transaction must have nonce"

View File

@ -8,7 +8,7 @@ type
AccessList = 1,
Dynamic = 2
Transaction* = object
sender* {.serialize.}: ?Address
`from`* {.serialize.}: ?Address
to* {.serialize.}: Address
data* {.serialize.}: seq[byte]
value* {.serialize.}: UInt256
@ -22,7 +22,7 @@ type
func `$`*(transaction: Transaction): string =
result = "("
if sender =? transaction.sender:
if sender =? transaction.`from`:
result &= "from: " & $sender & ", "
result &= "to: " & $transaction.to & ", "
result &= "value: " & $transaction.value & ", "

View File

@ -64,7 +64,7 @@ method getAddress(wallet: Wallet): Future[Address] {.async.} =
proc signTransaction*(wallet: Wallet,
transaction: Transaction): Future[seq[byte]] {.async.} =
if sender =? transaction.sender and sender != wallet.address:
if sender =? transaction.`from` and sender != wallet.address:
raiseWalletError "from address mismatch"
return wallet.privateKey.sign(transaction)

View File

@ -61,7 +61,7 @@ suite "JsonRpcSigner":
test "populate does not overwrite existing fields":
let signer = provider.getSigner()
var transaction = Transaction.example
transaction.sender = some await signer.getAddress()
transaction.`from` = some await signer.getAddress()
transaction.nonce = some UInt256.example
transaction.chainId = some await signer.getChainId()
transaction.gasPrice = some UInt256.example
@ -72,7 +72,7 @@ suite "JsonRpcSigner":
test "populate fails when sender does not match signer address":
let signer = provider.getSigner()
var transaction = Transaction.example
transaction.sender = accounts[1].some
transaction.`from` = accounts[1].some
expect SignerError:
discard await signer.populateTransaction(transaction)