JSON serialization of signed states

This commit is contained in:
Mark Spanbroek 2021-04-06 12:25:47 +02:00
parent 9e16807145
commit 469a8d4154
5 changed files with 124 additions and 0 deletions

View File

@ -1,5 +1,7 @@
import ./nitro/protocol
import ./nitro/wallet
import ./nitro/json
export protocol
export wallet
export json

96
nitro/json.nim Normal file
View File

@ -0,0 +1,96 @@
import std/json
import std/typetraits
import pkg/stew/byteutils
import ./basics
import ./protocol
import ./wallet/signedstate
export signedstate
push: {.upraises:[].}
func `%`(value: Outcome | Allocation): JsonNode =
type Base = distinctBase(typeof value)
%(Base(value))
func `%`(value: seq[byte]): JsonNode =
%value.toHex
func `%`(value: EthAddress | Destination): JsonNode =
%($value)
func `%`(value: UInt256): JsonNode =
%(value.toHex)
func `%`(value: Signature): JsonNode =
%($value)
func `%`(value: AllocationItem): JsonNode =
%*{
"destination": value.destination,
"amount": value.amount
}
func toJson*(payment: SignedState): string =
$(%*payment)
{.pop.}
push: {.upraises: [ValueError].}
func expectKind(node: JsonNode, kind: JsonNodeKind) =
if node.kind != kind:
let message = "expected " & $kind & ", got: " & $node.kind
raise newException(JsonKindError, message)
func initFromJson*(bytes: var seq[byte], node: JsonNode, _: var string) =
node.expectKind(JString)
let parsed = seq[byte].fromHex(node.getStr)
if parsed.isOk:
bytes = parsed.get
else:
raise newException(ValueError, "invalid hex string")
func initFromJson*(address: var EthAddress, node: JsonNode, _: var string) =
node.expectKind(JString)
let parsed = EthAddress.parse(node.getStr)
if parsed.isSome:
address = parsed.get
else:
raise newException(ValueError, "invalid ethereum address")
func initFromJson*(dest: var Destination, node: JsonNode, _: var string) =
node.expectKind(JString)
let parsed = Destination.parse(node.getStr)
if parsed.isSome:
dest = parsed.get
else:
raise newException(ValueError, "invalid nitro destination")
func initFromJson*(number: var UInt256, node: JsonNode, _: var string) =
node.expectKind(JString)
number = UInt256.fromHex(node.getStr)
func initFromJson*(signature: var Signature, node: JsonNode, _: var string) =
node.expectKind(JString)
let parsed = Signature.parse(node.getStr)
if parsed.isSome:
signature = parsed.get
else:
raise newException(ValueError, "invalid signature")
{.pop.}
push: {.upraises: [].}
proc fromJson*(_: type SignedState, json: string): ?SignedState =
try:
{.warning[UnsafeSetLen]: off.}
return parseJson(json).to(SignedState).some
{.warning[UnsafeSetLen]: on.}
except ValueError:
return SignedState.none
except Exception as error:
raise (ref Defect)(msg: error.msg, parent: error)
{.pop.}

View File

@ -83,3 +83,9 @@ proc example*(_: type Signature): Signature =
let key = PrivateKey.random
let state = State.example
key.sign(state)
proc example*(_: type SignedState): SignedState =
let state = State.example
let key = PrivateKey.random
let signature = key.sign(state)
SignedState(state: state, signatures: @[signature])

19
tests/nitro/testJson.nim Normal file
View File

@ -0,0 +1,19 @@
import ./basics
suite "json serialization":
let payment = SignedState.example()
test "serializes signed states to json":
check payment.toJson.len > 0
test "deserializes signed state":
check SignedState.fromJson(payment.toJson) == payment.some
test "returns none when deserializing invalid json":
let invalid = "{"
check SignedState.fromJson(invalid).isNone
test "returns none when json cannot be converted to signed state":
let invalid = "{}"
check SignedState.fromJson(invalid).isNone

View File

@ -4,5 +4,6 @@ import ./nitro/protocol/testOutcome
import ./nitro/protocol/testState
import ./nitro/protocol/testSignature
import ./nitro/testWallet
import ./nitro/testJson
{.warning[UnusedImport]: off.}