Skip to content
This repository has been archived by the owner on Oct 11, 2024. It is now read-only.

GraphQL API Draft Specification #854

Open
albrow opened this issue Jul 1, 2020 · 2 comments
Open

GraphQL API Draft Specification #854

albrow opened this issue Jul 1, 2020 · 2 comments
Labels
enhancement New feature or request question Further information is requested

Comments

@albrow
Copy link
Contributor

albrow commented Jul 1, 2020

0x Mesh GraphQL API Specification

This is a proposal for a new GraphQL API for Mesh which will replace the existing JSON-RPC API in Mesh version 10.0.0. The JSON-RPC API will be removed in Mesh v10 and users who upgrade to v10 will need to use the new GraphQL API.

Background and Motivation

There are several motivating factors for why we are introducing a new API:

Improve Queryability of Mesh

Currently, Mesh does not offer much in the way of querying or filtering orders in its JSON-RPC API. Part of the reason for this is that JSON-RPC does not lend itself well to complicated queries.

Because of this, if you need to query orders, you will need to follow a somewhat complicated process for syncing Mesh with your own database and then running queries from there. Practically speaking, there is no other way to get only the orders you care about and make sure they are up-to-date. This can create an unnecessary burden for developers, especially in the browser where there are limited database options.

The new API will make it possible for many use cases to avoid syncing with their own database entirely. Instead, Mesh can be thought of as the database for orders. For example, you can query Mesh directly to get all ETH-DAI orders that expire no sooner than 60 seconds from now while filtering out dust orders.

Some users may still wish to sync their database (for example, if they want to do SQL joins with application-specific data), but it is an option rather than a requirement. Even for users that do want to sync their own database, improved querying capabilities at the API layer can still make it easier to do so by filtering out orders you don't care about earlier on in the pipeline.

Unify and Simplify our Tooling

In the current 0x tech stack, there are many different APIs and libraries that effectively do the same thing: get a set of orders that can be filled by anyone.

  1. SRA endpoints in 0x API
  2. Mesh JSON-RPC API
  3. @0x/mesh-browser
  4. @0x/mesh-rpc-client
  5. @0x/connect
  6. @0x/orderbook

All of these APIs and tools work differently (sometimes in subtle ways) and generally one cannot be used as a drop in replacement for the other. Some of them are compatible with one another and others are not. For example, @0x/orderbook works with SRA or the Mesh JSON-RPC API but doesn't work when running Mesh in the browser.

One of the goals for the new GraphQL API is to provide a single API for getting orders whether you are talking to 0x API, running your own Mesh node, or even running Mesh in the browser.

We are still in the process of planning the timeline for this transition. One thing that's clear is that SRA will not disappear right away. A lot of users and bots rely on SRA, so our goal is to keep it up and running for the near future, although it may be marked as deprecated. In addition, any endpoints in 0x API not related to SRA (e.g. /swap and /meta_transaction) will be unaffected.

Better Documentation and Support for More Languages

The documentation for the existing JSON-RPC API is hand-written and must be manually updated whenever we make changes. Writing clients for new languages is also a largely manual process. While JSON-RPC is a widely accepted standard, it is not as structured or type safe as something like GraphQL. Additionally, Mesh relies on the subscriptions feature of JSON-RPC 2.0 which is not universally supported by clients.

Why GraphQL?

GraphQL was selected as a standard for the new API based on several important characteristics:

  1. Transport layer agnostic (e.g. HTTP, WebSockets, or calling a function).
  2. Type-safe, well-structured schemas.
  3. Wide support across many programming languages.
  4. Great tooling (including automatic doc generation and playground environments).
  5. Built-in support for subscriptions.
  6. Ability to only receive the fields that you need.

Playground Environment

We have deployed a playground environment which you can use to familiarize yourself with the new API. It supports autocompletion, syntax highlighting, subscriptions, and inline documentation. You can access the playground at https://meshmock.spaceship.0x.org/. See the Example Queries section below for some queries to try.

Some caveats to keep in mind:

  1. The playground uses mock data which is structurally correct (i.e. all the fields have the correct type) but may be semantically incorrect (e.g. orders may have the wrong signature).
  2. Some fields are not sorted in the correct order. For example, BigNumber fields are sorted alphanumerically instead of numerically. This also affects the results from filters that depend on ordering such as GREATER or LESS. This will not be the case in the final production API.
  3. Subscriptions are supported but can cause issues with scrolling in the playground. Refreshing the page usually fixes this.

GraphQL Schema

Here is the proposed GraphQL schema in its entirety:

"""
A 32-byte Keccak256 hash encoded as a hexadecimal string.
"""
scalar Hash
"""
An Ethereum address encoded as a hexadecimal string.
"""
scalar Address
"""
A BigNumber or uint256 value encoded as a numerical string.
"""
scalar BigNumber
"""
An array of arbitrary bytes encoded as a hexadecimal string.
"""
scalar Bytes
"""
A time encoded as a string using the RFC3339 standard.
"""
scalar Timestamp
"""
An arbitrary set of key-value pairs. Encoded as a JSON object.
"""
scalar Object

"""
A signed 0x order according to the [protocol specification](https://github.com/0xProject/0x-protocol-specification/blob/master/v3/v3-specification.md#order-message-format.)
"""
type Order {
  chainId: Int!
  exchangeAddress: Address!
  makerAddress: Address!
  makerAssetData: Bytes!
  makerAssetAmount: BigNumber!
  makerFeeAssetData: Bytes!
  makerFee: BigNumber!
  takerAddress: Address!
  takerAssetData: Bytes!
  takerAssetAmount: BigNumber!
  takerFeeAssetData: Bytes!
  takerFee: BigNumber!
  senderAddress: Address!
  feeRecipientAddress: Address!
  expirationTimeSeconds: BigNumber!
  salt: BigNumber!
  signature: Bytes!
}

"""
A signed 0x order along with some additional metadata about the order which is not part of the 0x protocol specification.
"""
type OrderWithMetadata {
  chainId: Int!
  exchangeAddress: Address!
  makerAddress: Address!
  makerAssetData: Bytes!
  makerAssetAmount: BigNumber!
  makerFeeAssetData: Bytes!
  makerFee: BigNumber!
  takerAddress: Address!
  takerAssetData: Bytes!
  takerAssetAmount: BigNumber!
  takerFeeAssetData: Bytes!
  takerFee: BigNumber!
  senderAddress: Address!
  feeRecipientAddress: Address!
  expirationTimeSeconds: BigNumber!
  salt: BigNumber!
  signature: Bytes!
  """
  The hash, which can be used to uniquely identify an order.
  """
  hash: Hash!
  """
  The remaining amount of the maker asset which has not yet been filled.
  """
  remainingFillableTakerAssetAmount: BigNumber!
}

"""
An enum containing all the order fields for which filters and/or sorting is supported.
"""
enum OrderField {
  hash
  chainId
  exchangeAddress
  makerAddress
  makerAssetData
  makerAssetAmount
  makerFeeAssetData
  makerFee
  takerAddress
  takerAssetData
  takerAssetAmount
  takerFeeAssetData
  takerFee
  senderAddress
  feeRecipientAddress
  expirationTimeSeconds
  salt
  remainingFillableTakerAssetAmount
}

"""
The kind of comparison to be used in a filter.
"""
enum FilterKind {
  EQUAL
  NOT_EQUAL
  GREATER
  GREATER_OR_EQUAL
  LESS
  LESS_OR_EQUAL
}

"""
The direction to sort in. Ascending means lowest to highest. Descending means highest to lowest.
"""
enum SortDirection {
  ASC
  DESC
}

"""
The value to filter with. Must be the same type as the field you are filtering by.
"""
scalar FilterValue

"""
A filter on orders. Can be used in queries to only return orders that meet certain criteria.
"""
input OrderFilter {
  field: OrderField!
  kind: FilterKind!
  value: FilterValue!
}

"""
A sort ordering for orders. Can be used in queries to control the order in which results are returned.
"""
input OrderSort {
  field: OrderField!
  direction: SortDirection!
}

"""
The block number and block hash for the latest block that has been processed by Mesh.
"""
type LatestBlock {
  number: BigNumber!
  hash: Hash!
}

"""
Contains configuration options and various stats for Mesh.
"""
type Stats {
  version: String!
  pubSubTopic: String!
  rendezvous: String!
  peerID: String!
  ethereumChainID: Int!
  latestBlock: LatestBlock
  numPeers: Int!
  numOrders: Int!
  numOrdersIncludingRemoved: Int!
  startOfCurrentUTCDay: Timestamp!
  ethRPCRequestsSentInCurrentUTCDay: Int!
  ethRPCRateLimitExpiredRequests: Int!
  maxExpirationTime: BigNumber!
}

type Query {
  """
  Returns the order with the specified hash, or null if no order is found with that hash.
  """
  order(hash: Hash!): OrderWithMetadata
  """
  Returns an array of orders that satisfy certain criteria.
  """
  orders(
    """
    Determines the order of the results. If more than one sort option is provided, results we be sorted by the
    first option first, then by any subsequent options. By default, orders are sorted by hash in ascending order.
    """
    sort: [OrderSort!] = [{ field: hash, direction: ASC }]
    """
    A set of filters. Only the orders that match all filters will be included in the results. By default no
    filters are used.
    """
    filters: [OrderFilter!] = []
    """
    The maximum number of orders to be included in the results. Defaults to 20.
    """
    limit: Int = 20
  ): [OrderWithMetadata!]!
  """
  Returns the current stats.
  """
  stats: Stats!
}

"""
A signed 0x order according to the [protocol specification](https://github.com/0xProject/0x-protocol-specification/blob/master/v3/v3-specification.md#order-message-format).
"""
input NewOrder {
  chainId: Int!
  exchangeAddress: Address!
  makerAddress: Address!
  makerAssetData: Bytes!
  makerAssetAmount: BigNumber!
  makerFeeAssetData: Bytes!
  makerFee: BigNumber!
  takerAddress: Address!
  takerAssetData: Bytes!
  takerAssetAmount: BigNumber!
  takerFeeAssetData: Bytes!
  takerFee: BigNumber!
  senderAddress: Address!
  feeRecipientAddress: Address!
  expirationTimeSeconds: BigNumber!
  salt: BigNumber!
  signature: Bytes!
}

"""
The results of the addOrders mutation. Includes which orders were accepted and which orders where rejected.
"""
type AddOrdersResults {
  """
  The set of orders that were accepted. Accepted orders will be watched and order events will be emitted if
  their status changes.
  """
  accepted: [AcceptedOrderResult!]!
  """
  The set of orders that were rejected, including the reason they were rejected. Rejected orders will not be
  watched.
  """
  rejected: [RejectedOrderResult!]!
}

type AcceptedOrderResult {
  """
  The order that was accepted, including metadata.
  """
  order: OrderWithMetadata!
  """
  Whether or not the order is new. Set to true if this is the first time this Mesh node has accepted the order
  and false otherwise.
  """
  isNew: Boolean!
}

type RejectedOrderResult {
  """
  The hash of the order. May be null if the hash could not be computed.
  """
  hash: Hash
  """
  The order that was rejected.
  """
  order: Order!
  """
  A machine-readable code indicating why the order was rejected. This code is designed to
  be used by programs and applications and will never change without breaking backwards-compatibility.
  """
  code: RejectedOrderCode!
  """
  A human-readable message indicating why the order was rejected. This message may change
  in future releases and is not covered by backwards-compatibility guarantees.
  """
  message: String!
}

"""
A set of all possible codes included in RejectedOrderResult. Note that more codes will be added
to the final spec. See the [current Mesh docs](https://godoc.org/github.com/0xProject/0x-mesh/zeroex/ordervalidator#pkg-variables)
for a list of all codes currently in use.
"""
enum RejectedOrderCode {
  ETH_RPC_REQUEST_FAILED
  INVALID_MAKER_ASSET_AMOUNT
  INVALID_TAKER_ASSET_AMOUNT
}

type Mutation {
  """
  Adds one or more orders to Mesh.
  """
  addOrders(orders: [NewOrder!]!, pinned: Boolean = true): AddOrdersResults!
}

type OrderEvent {
  """
  The order that was affected.
  """
  order: OrderWithMetadata!
  """
  A way of classifying the effect that the order event had on the order. You can
  think of different end states as different "types" of order events.
  """
  endState: OrderEndState!
  """
  The timestamp for the order event, which can be used for bookkeeping purposes.
  If the order event was generated as a direct result of on-chain events (e.g., FILLED,
  UNFUNDED, CANCELED), then it is set to the latest block timestamp at which the order
  was re-validated. Otherwise (e.g., for ADDED, STOPPED_WATCHING), the timestamp corresponds
  when the event was generated on the server side.
  """
  timestamp: Timestamp!
  """
  Contains all the contract events that triggered the order to be re-validated.
  All events that _may_ have affected the state of the order are included here.
  It is gauranteed that at least one of the events included here will have affected
  the order's state, but there may also be some false positives.
  """
  contractEvents: [ContractEvent!]!
}

enum OrderEndState {
  """
  The order was successfully validated and added to the Mesh node. The order is now being watched and any changes to
  the fillability will result in subsequent order events.
  """
  ADDED
  """
  The order was filled for a partial amount. The order is still fillable up to the remainingFillableTakerAssetAmount.
  """
  FILLED
  """
  The order was fully filled and its remaining fillableTakerAssetAmount is 0. The order is no longer fillable.
  """
  FULLY_FILLED
  """
  The order was cancelled and is no longer fillable.
  """
  CANCELLED
  """
  The order expired and is no longer fillable.
  """
  EXPIRED
  """
  The order was previously expired, but due to a block re-org it is no longer considered expired (should be rare).
  """
  UNEXPIRED
  """
  The order has become unfunded and is no longer fillable. This can happen if the maker makes a transfer or changes their allowance.
  """
  UNFUNDED
  """
  The fillability of the order has increased. This can happen if a previously processed fill event gets reverted due to a block re-org,
  or if a maker makes a transfer or changes their allowance.
  """
  FILLABILITY_INCREASED
  """
  The order is potentially still valid but was removed for a different reason (e.g.
  the database is full or the peer that sent the order was misbehaving). The order will no longer be watched
  and no further events for this order will be emitted. In some cases, the order may be re-added in the
  future.
  """
  STOPPED_WATCHING
}

"""
An on-chain contract event.
"""
type ContractEvent {
  """
  The hash of the block where the event was generated.
  """
  blockHash: Hash!
  """
  The hash of the transaction where the event was generated.
  """
  txHash: Hash!
  """
  The index of the transaction where the event was generated.
  """
  txIndex: Int!
  """
  The index of the event log.
  """
  logIndex: Int!
  """
  True when this was an event that was removed due to a block-reorg. False otherwise.
  """
  isRemoved: Boolean!
  """
  The address of the contract that generated the event.
  """
  address: Address!
  """
  The kind of event (e.g. "ERC20TransferEvent").
  """
  kind: String!
  """
  The parameters for the event. The parameters are different for each event kind.
  """
  parameters: Object!
}

type Subscription {
  """
  Subscribe to all order events. Events are emitted whenever the status of a watched order changes.
  """
  orderEvents: [OrderEvent!]!
}

Example Queries

This section includes some example queries which you can copy and paste in the playground. Of course, you would typically write queries programmatically with a GraphQL client, not by manually writing them. This is just for illustrative purposes.

Getting a Specific Order

You can get the details for any order by its hash:

{
  order(hash: "0x38c1b56f95bf168b303e4b62d64f7f475f2ac34124e9678f0bd852f95a4ca377") {
    hash
    chainId
    exchangeAddress
    makerAddress
    makerAssetData
    makerAssetAmount
    makerFeeAssetData
    makerFee
    takerAddress
    takerAssetData
    takerAssetAmount
    takerFeeAssetData
    takerFee
    senderAddress
    feeRecipientAddress
    expirationTimeSeconds
    salt
    signature
    remainingFillableTakerAssetAmount
  }
}

Querying and Filtering Orders

You can get all orders via the orders query. By default, it will return up to 20 orders at a time sorted by their hash.

{
  orders {
    hash
    chainId
    exchangeAddress
    makerAddress
    makerAssetData
    makerAssetAmount
    makerFeeAssetData
    makerFee
    takerAddress
    takerAssetData
    takerAssetAmount
    takerFeeAssetData
    takerFee
    senderAddress
    feeRecipientAddress
    expirationTimeSeconds
    salt
    signature
    remainingFillableTakerAssetAmount
  }
}

The orders query supports many different options. Here's an example of how to get orders with a minimum expirationTimeSeconds and minimum remainingFillableAssetAmount. You can use this to exclude dust orders and orders which may expire too soon.

{
  orders(
    filters: [
      {
        field: remainingFillableTakerAssetAmount
        kind: GREATER_OR_EQUAL
        value: "150000"
      }
      {
        field: expirationTimeSeconds
        kind: GREATER_OR_EQUAL
        value: "1598733429"
      }
    ]
  ) {
    hash
    makerAddress
    makerAssetData
    makerAssetAmount
    takerAddress
    takerAssetData
    takerAssetAmount
    expirationTimeSeconds
    remainingFillableTakerAssetAmount
  }
}

Here's an example of sorting orders by the remainingFillableAssetAmount. You can combine any number
of filters and sorts in an orders query.

{
  orders(
    sort: [{ field: remainingFillableTakerAssetAmount, direction: DESC }]
  ) {
    hash
    makerAddress
    makerAssetData
    makerAssetAmount
    takerAddress
    takerAssetData
    takerAssetAmount
    expirationTimeSeconds
    remainingFillableTakerAssetAmount
  }
}

Adding Orders

You can add orders using a mutation. Note that in the playground orders will not actually be added and will not show up in subsequent queries. Also in the playground every other order will be rejected in order to provide an example of what the rejected field in the response looks like.

mutation AddOrders {
  addOrders(
    orders: [
      {
        signature: "0x1c91055b1ce93cdd341c423b889be703ce436e25fe62d94aabbae97528b4d247646c3cd3a20f0566540ac5668336d147d844cf1a7715d700f1a7c3e72f1c60e21502"
        senderAddress: "0x0000000000000000000000000000000000000000"
        makerAddress: "0xd965a4f8f5b49dd2f5ba83ef4e61880d0646fd00"
        takerAddress: "0x0000000000000000000000000000000000000000"
        makerFee: "1250000000000000"
        takerFee: "0"
        makerAssetAmount: "50000000000000000"
        takerAssetAmount: "10"
        makerAssetData: "0xf47261b0000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"
        takerAssetData: "0xa7cb5fb7000000000000000000000000d4690a51044db77d91d7aa8f7a3a5ad5da331af0000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000e3a2a1f2146d86a604adc220b4967a898d7fe0700000000000000000000000009a379ef7218bcfd8913faa8b281ebc5a2e0bc040000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001360000000000000000000000000000000000000000000000000000000000000004"
        salt: "1584796917698"
        exchangeAddress: "0x61935cbdd02287b511119ddb11aeb42f1593b7ef"
        feeRecipientAddress: "0x0d056bb17ad4df5593b93a1efc29cb35ba4aa38d"
        expirationTimeSeconds: "1595164917"
        makerFeeAssetData: "0xf47261b0000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"
        chainId: 1
        takerFeeAssetData: "0x"
      }
      {
        signature: "0x1bf931ab06551bbbd3a7e272ca4833503d768caca2cac564b157b46c906c7b41c57fd6146b500e1ad2dac729c351142764cb76efc975c6d7c64aef6cf7930c075d02"
        senderAddress: "0x0000000000000000000000000000000000000000"
        makerAddress: "0x0c5fa5fa51d84227bfacdc56b36329286b37d051"
        takerAddress: "0x0000000000000000000000000000000000000000"
        makerFee: "0"
        takerFee: "0"
        makerAssetAmount: "50911000000000000"
        takerAssetAmount: "10000000000000000000"
        makerAssetData: "0xf47261b0000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"
        takerAssetData: "0xf47261b000000000000000000000000058b6a8a3302369daec383334672404ee733ab239"
        salt: "1590244702461"
        exchangeAddress: "0x61935cbdd02287b511119ddb11aeb42f1593b7ef"
        feeRecipientAddress: "0xa258b39954cef5cb142fd567a46cddb31a670124"
        expirationTimeSeconds: "1592663792"
        makerFeeAssetData: "0x"
        chainId: 1
        takerFeeAssetData: "0x"
      }
    ]
  ) {
    accepted {
      order {
        hash
      }
      isNew
    }
    rejected {
      hash
      code
      message
    }
  }
}

Subscribing to Order Events

You can subscribe to order events via a subscription. The playground will send a mock order event every second.

subscription {
  orderEvents {
    timestamp
    endState
    order {
      hash
      remainingFillableTakerAssetAmount
    }
  }
}

Getting Stats

You can get some stats about your Mesh node via the stats query.

{
  stats {
    version
    pubSubTopic
    rendezvous
    peerID
    ethereumChainID
    latestBlock {
      number
      hash
    }
    numPeers
    numOrders
    numOrdersIncludingRemoved
    startOfCurrentUTCDay
    ethRPCRequestsSentInCurrentUTCDay
    ethRPCRateLimitExpiredRequests
    maxExpirationTime
  }
}

Pagination

We recommend paginating through orders by using filters and limit. So for example, if you want to sort orders by their hash (which is the default), you first send a query without any filters:

{
  orders {
    hash
    makerAddress
    makerAssetData
    makerAssetAmount
    takerAddress
    takerAssetData
    takerAssetAmount
    expirationTimeSeconds
    remainingFillableTakerAssetAmount
  }
}

The orders in the response will be sorted by hash (which is the default). Look at the last order you received, which in this case has a hash of 0x75d2b56b11f21235ec8faec8be9d081090678cf62f5c69fa118236d829424719. Send the next request by using the last hash you received in a filter:

{
  orders(
    filters: [
      {
        field: hash
        kind: GREATER
        value: "0x75d2b56b11f21235ec8faec8be9d081090678cf62f5c69fa118236d829424719"
      }
    ]
  ) {
    hash
    makerAddress
    makerAssetData
    makerAssetAmount
    takerAddress
    takerAssetData
    takerAssetAmount
    expirationTimeSeconds
    remainingFillableTakerAssetAmount
  }
}

This will return any orders with a hash greater than 0x75d2b56b11f21235ec8faec8be9d081090678cf62f5c69fa118236d829424719. Repeat this process, changing the hash each time, until there are no orders left.

There may be orders added or removed while you are in the process of paginating. Following this method guarantees that:

  1. No order will be included more than once.
  2. Any order which was present at the start of pagination and at the end of pagination will be included.
  3. Any order which was added or removed after pagination started may or may not be included.

Query Fragments

GraphQL requires you to specify all the fields that you want included in the response. However, you can use query fragments to avoid repeating the same fields over and over. Here's an example of a query fragment that includes all the fields of an order.

fragment AllOrderFields on OrderWithMetadata {
  hash
  chainId
  exchangeAddress
  makerAddress
  makerAssetData
  makerAssetAmount
  makerFeeAssetData
  makerFee
  takerAddress
  takerAssetData
  takerAssetAmount
  takerFeeAssetData
  takerFee
  senderAddress
  feeRecipientAddress
  expirationTimeSeconds
  salt
  signature
  remainingFillableTakerAssetAmount
}

{
  order(
    hash: "0x06d15403630b6d73fbacbf0864eb76c2db3d6e6fc8adec8a95fc536593f17c54"
  ) {
    ...AllOrderFields
  }
}

Future Improvements

The API described above is what we are planning to ship with Mesh version 10.0.0. Our goal is to ship with a minimally viable API that improves the experience of interacting with Mesh for common use cases. However, this will not be the final state of the API and we are planning to follow up with a few specific improvements. Because of the way GraphQL requires specifying the fields you want to receive in the response, we can add new fields (e.g. to the OrderWithMetadata type) without increasing payload sizes for users who don't need those fields. These improvements will be backwards compatible.

  1. Add a price field to OrderWithMetadata. This will allow sorting orders by price or using a filter to only return orders with a certain price or better.
  2. Add parsed asset data fields to OrderWithMetadata. This could allow you to more easily e.g. only receive ERC20 orders or find all orders for a specific ERC721 contract address with any token ID. The variety of asset datas and the existence of the MultiAssetDataProxy make it challenging to structure the data in an efficient way and expose a querying interface that is easy to use. That said, it should be possible and we know this is something users have been asking for.
  3. Support filters in the orderEvents subscription. The current subscription returns all order events, since it is much easier to support on the backend. It should be possible, though somewhat challenging, to allow filtering similar to the orders query.

If you have any other ideas for improvements or new features, let us know 😄

@albrow albrow added enhancement New feature or request question Further information is requested labels Jul 1, 2020
@albrow albrow mentioned this issue Jul 9, 2020
36 tasks
@shanejonas
Copy link

I'd like to suggest to keep the JSON-RPC API.

The only thing JSON-RPC is missing is some tooling to fill the gap with GraphQL, thats exactly what OpenRPC is:

http://open-rpc.org/

heres a live example running the playground/inspector against ethereum:

https://playground.open-rpc.org/?url=https://services.jade.builders/core-geth/ethereum/1.11.2

@albrow
Copy link
Contributor Author

albrow commented Jul 31, 2020

@shanejonas thanks for sharing your thoughts! Would you mind sharing a little background info about your role/company and experience with Mesh so far?

Couple quick questions about OpenRPC:

  1. Does OpenRPC support subscriptions?
  2. Which languages have client support? How much of the client can be auto-generated?
  3. When was the OpenRPC spec created? Is anyone using it in production? If so, who?

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
enhancement New feature or request question Further information is requested
Projects
None yet
Development

No branches or pull requests

2 participants