mirror of
https://github.com/logos-storage/nim-ethers.git
synced 2026-01-10 17:43:06 +00:00
rename sender to from, update json error logging, add more conversions
This commit is contained in:
parent
526d954a01
commit
c261e96274
@ -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)
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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)
|
||||
|
||||
|
||||
@ -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"
|
||||
|
||||
@ -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 & ", "
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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)
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user