L2 round-trips through JSON, so a Transaction's Date fields arrive as strings and its BigNumber / Address-branded fields lose their runtime shape on cross-process / post-L1 reads. Store a JSON-safe projection and rehydrate on read.
Transaction
Date
BigNumber
Address
Non-JSON-native fields enumerated field-by-field:
amount
sourceAmount?
targetAmount?
fees?
preBalance?
postBalance?
walletAddress
otherWallet.address
createdAt
updatedAt
Everything else (card, deviceLocation, subType, customer/entity ids and names, currency, etc.) is JSON-safe and rides the spread unchanged.
card
deviceLocation
subType
currency
L2 round-trips through JSON, so a
Transaction'sDatefields arrive as strings and itsBigNumber/Address-branded fields lose their runtime shape on cross-process / post-L1 reads. Store a JSON-safe projection and rehydrate on read.Non-JSON-native fields enumerated field-by-field:
amount(BigNumber, required),sourceAmount?/targetAmount?/fees?/preBalance?/postBalance?(BigNumber, optional) → stringwalletAddress(Address | null) → string | null (preserves the REWARD null; we deliberately do NOT coerce to "" like the old dashboard serializer)otherWallet.address(Address) → stringcreatedAt/updatedAt(Date, both required) → ISO stringEverything else (
card,deviceLocation,subType, customer/entity ids and names,currency, etc.) is JSON-safe and rides the spread unchanged.