jsonrpc: extract error data from JSON RPC error

Inspired by 'spelunk' from ethers.js:
f97b92bbb1/packages/providers/src.ts/json-rpc-provider.ts (L25)
This commit is contained in:
Mark Spanbroek 2024-03-18 16:02:39 +01:00 committed by markspanbroek
parent 52d7d3dbed
commit 875900b493
4 changed files with 47 additions and 1 deletions

View File

@ -14,6 +14,7 @@ export blocktag
type
Provider* = ref object of RootObj
ProviderError* = object of EthersError
data*: ?seq[byte]
Subscription* = ref object of RootObj
EventFilter* {.serialize.} = ref object of RootObj
address*: Address

View File

@ -1,13 +1,30 @@
import std/strutils
import pkg/stew/byteutils
import ../../basics
import ../../provider
import ./conversions
{.push raises:[].}
type JsonRpcProviderError* = object of ProviderError
func new(_: type JsonRpcProviderError, json: JsonNode): ref JsonRpcProviderError =
func extractErrorData(json: JsonNode): ?seq[byte] =
if json.kind == JObject:
if "message" in json and "data" in json:
let message = json{"message"}.getStr()
let hex = json{"data"}.getStr()
if "reverted" in message and hex.startsWith("0x"):
if data =? hexToSeqByte(hex).catch:
return some data
for key in json.keys:
if data =? extractErrorData(json{key}):
return some data
func new*(_: type JsonRpcProviderError, json: JsonNode): ref JsonRpcProviderError =
let error = (ref JsonRpcProviderError)()
if "message" in json:
error.msg = json{"message"}.getStr
error.data = extractErrorData(json)
error
proc raiseJsonRpcProviderError*(

View File

@ -0,0 +1,27 @@
import std/unittest
import std/json
import pkg/questionable
import pkg/ethers/providers/jsonrpc/errors
suite "JSON RPC errors":
test "converts JSON RPC error to Nim error":
let error = %*{ "message": "some error" }
check JsonRpcProviderError.new(error).msg == "some error"
test "converts error data to bytes":
let error = %*{
"message": "VM Exception: reverted with 'some error'",
"data": "0xabcd"
}
check JsonRpcProviderError.new(error).data == some @[0xab'u8, 0xcd'u8]
test "converts nested error data to bytes":
let error = %*{
"message": "VM Exception: reverted with 'some error'",
"data": {
"message": "VM Exception: reverted with 'some error'",
"data": "0xabcd"
}
}
check JsonRpcProviderError.new(error).data == some @[0xab'u8, 0xcd'u8]

View File

@ -2,5 +2,6 @@ import ./jsonrpc/testJsonRpcProvider
import ./jsonrpc/testJsonRpcSigner
import ./jsonrpc/testJsonRpcSubscriptions
import ./jsonrpc/testConversions
import ./jsonrpc/testErrors
{.warning[UnusedImport]:off.}