Effect CommunityEC
Effect Community16mo ago
5 replies
fucory

Implementing JSON-RPC with Effect-TS RPC Package: Defining and Converting Request Shapes

I'm struggling to figure out the best way to implement json-rpc with the rpc package https://github.com/Effect-TS/effect/tree/main/packages/rpc

What I want to do is define the shape of a request

export class JsonRpcRequest extends Class<JsonRpcRequest>("JsonRpcRequest")({
  jsonrpc: optional(String),
  method: String,
  params: Union(Struct({}), Array(String)),
  id: optional(Union(String, Number))
}) {}

export class GetBlockByNumberJsonRpcRequest extends JsonRpcRequest.extend<GetBlockByNumberJsonRpcRequest>("GetBlockByNumberJsonRpcRequest")({
  method: Literal(identifier),
  params: Tuple(Union(HexString, Literal("latest")), Boolean)
}) {}


However reading source code of the rpc package it seems to be hardcoded to only accept requests that have a _tag property. So next step I thought was to define a way to convert between the two

export class GetBlockByNumber extends Schema.TaggedRequest<GetBlockByNumber>()(
  identifier,
  {
    failure: Schema.Never, 
    success: JsonRpcBlock, 
    payload: {
      blockTag: Union(BlockTag, BigIntFromSelf),
      fullTransactionObjects: Boolean,
    },
  }
) {}

export const JsonRpcToTaggedRequest = Schema.transform(
  GetBlockByNumberJsonRpcRequest,
  GetBlockByNumber,
  {
    strict: true,
    decode: ({ params }) => {
      const [blockTag, fullTransactionObjects] = params
      return new GetBlockByNumber({
        blockTag: decodeUnknownSync(JsonRpcBlockTagToBlockTag)(blockTag),
        fullTransactionObjects,
      })
    },
    encode: ({ blockTag, fullTransactionObjects }) => new GetBlockByNumberJsonRpcRequest({
      jsonrpc: "2.0",
      method: "eth_getBlockByNumber",
      params: [typeof blockTag === 'bigint' ? numberToHex(blockTag) : blockTag, fullTransactionObjects],
    })
  }
)


But I still can't quite figure out how to get all the pieces to click in place. It generally feels like there must be an easier way I'm missing.
Was this page helpful?