Using the Router API

Reservoir gives you access to a fully functional Aggregated Orderbook that strives to be a global pool of NFT liquidity. You can both create orders (list for sale, make an offer) or fill orders (buy token, accept offer).

🚧

We recommend using Reservoir SDK

Reservoir SDK includes helpers that abstract the process of iterating through steps, and returning callbacks that can be used to update your UI.

Importantly, because it's a shared order book, tools can specialize on different parts of the market. For example, a market maker could generate bids and feed them directly into the order book, while a wallet could place a sell button next to every NFT in a user's wallet, giving them access to those bids. As more integrations get built, the network effects of the shared order book grow stronger.

Steps

When executing orders, there are often multiple steps, like approving an exchange to access your NFTs, or wrapping WETH for a bid. These steps differ for every different type of liquidity that Reservoir supports. To make this simple, you can use the Router endpoints, which return the exact steps that you need to follow, including descriptions that you can display to users.

The flow looks like this:

  1. Call the Router API with the action you want to take (create or fill)
  2. Iterate through the steps and the items within a step, taking the necessary actions. Steps with no items, or an empty array of items, should be skipped.

As mentioned above each step contains an array of one or more items. These items need to be iterated and completed depending on the kind of step. There are two kinds of steps:

Transaction

A transaction that needs to be submitted on-chain. After this item is complete you can poll the Transaction Status API to ensure that the transaction was successfully picked up by the indexer. Depending on the router api, if it's a sale or a buy transaction, you can additionally poll the Sales API to ensure that the sale event was indexed correctly. The step item can then be successfully marked as complete.

Signature

A message that needs to be signed. Every signature comes with sign data and post data. The first action we need to take is to sign the message, keep in mind the signatureKind and use the appropriate signing method. Refer to your crypto library of choice on how to sign (ethers, web3, etc). After the message is signed the second action is to submit the post body to the endpoint provided in the post data. You'll also need to provide the signature that was generated from the sign data as a query parameter. If the request is successful we can mark the step item as complete.

The API returns the exact data that you need to sign/submit, so it can be fed directly into an Ethereum library like ethers.js. What's nice about this design pattern is that it is completely generic. As new types of liquidity are added, you can support them automatically without needing to update your app.

Reference Material:

JS SDK

Options for filling orders

The listing and bid acceptance APIs (/execute/buy and /execute/sell) support a few ways of requesting transaction data for filling (any combination of the below options is accepted):

  • pass a list of tokens, in which case the API will simply pick the best-priced orders that can get filled on those particular tokens
  • pass a list of order ids, in which case the API will use those specific order ids
  • pass a list of raw orders, in which case the API will use those specific raw orders

The first two options are self-explanatory, while the 3rd option requires the raw order data to get passed in a certain format, as follows:

  • each rawOrder object has two fields: kind and data (the data field will get parsed according to the kind)
  • both of these fields will get returned in various orders APIs (/orders/asks or /orders/bids): kind and rawData
  • the actual schema of each the data field can be found in the core SDK source code, in the order.ts file corresponding to each supported exchange (the params field in the constructor will include it)

Here's some examples:

[
   {
      "kind":"looks-rare",
      "data":{
         "r":"0xfa491d0e0a13dccd6467c38c890cc90f89700b587a2e678261df70e91fef0101",
         "s":"0x40ec4ecbcd26902a23325aee0e20364e55b94e42db1d9bf16c201b5bd5a916ab",
         "v":28,
         "kind":"single-token",
         "nonce":"445747",
         "price":"5800000000000000",
         "amount":"1",
         "params":"0x",
         "signer":"0x9044a0bcddbd69822f6b0d0d426ff65bbef8a1bd",
         "endTime":1675948780,
         "tokenId":"281",
         "currency":"0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
         "strategy":"0x579af6fd30bf83a5ac0d636bc619f98dbdeb930c",
         "startTime":1675941580,
         "collection":"0x63c5f88155b22e913cc46ed569edb0133aee503c",
         "isOrderAsk":true,
         "minPercentageToAsk":8500
      }
   },
   {
      "kind":"x2y2",
      "data":{
         "id":50947214,
         "nft":{
            "token":"0xeaa708c29ffce22db864385f0c6509907af45c03",
            "tokenId":"2486"
         },
         "kind":"single-token",
         "type":"sell",
         "maker":"0x6f3339eac0deb3dbc78e628c174737046498cda4",
         "price":"6400000000000000",
         "taker":"0x0000000000000000000000000000000000000000",
         "currency":"0x0000000000000000000000000000000000000000",
         "deadline":1675956570,
         "itemHash":"0xdfda59f7e3687a07b51338bd6a40d30e39c1108d1c179a7a8f9793206fc35bb2",
         "royalty_fee":50000
      }
   },
   {
      "kind":"seaport",
      "data":{
         "kind":"single-token",
         "salt":"0x360c6ebe000000000000000000000000000000000000000015b4c41d94cfd586",
         "zone":"0x004c00500000ad104d7dbd00e3ae0a5c00560c00",
         "offer":[
            {
               "token":"0x8f6a4d8ad2493adfd7d1540ccdba11bde5c7eb9e",
               "itemType":2,
               "endAmount":"1",
               "startAmount":"1",
               "identifierOrCriteria":"3577"
            }
         ],
         "counter":"0",
         "endTime":1691493881,
         "offerer":"0xbb93664780e5e4e22f5255c774bfc455ebfa789e",
         "zoneHash":"0x0000000000000000000000000000000000000000000000000000000000000000",
         "orderType":2,
         "signature":"0xb3277794bf3f113dfbaaa9e4691883a0a7c51cdea56840e906b16c0eb62c052b5a36203276d55d7279397c9a9762638ad369cd2b241da6a7babe8109ceac7979",
         "startTime":1675941882,
         "conduitKey":"0x0000007b02230091a7ed01230072f7006a004d60a8d4e71d599b8104250f0000",
         "consideration":[
            {
               "token":"0x0000000000000000000000000000000000000000",
               "itemType":0,
               "endAmount":"73075000000000000",
               "recipient":"0xbb93664780e5e4e22f5255c774bfc455ebfa789e",
               "startAmount":"73075000000000000",
               "identifierOrCriteria":"0"
            },
            {
               "token":"0x0000000000000000000000000000000000000000",
               "itemType":0,
               "endAmount":"1975000000000000",
               "recipient":"0x0000a26b00c1f0df003000390027140000faa719",
               "startAmount":"1975000000000000",
               "identifierOrCriteria":"0"
            },
            {
               "token":"0x0000000000000000000000000000000000000000",
               "itemType":0,
               "endAmount":"3950000000000000",
               "recipient":"0x5b5173599a2f29973397c34d01a49b3a0ee8963d",
               "startAmount":"3950000000000000",
               "identifierOrCriteria":"0"
            }
         ]
      }
   },
   {
      "kind":"nftx",
      "data":{
         "path":[
            "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
            "0x227c7df69d3ed1ae7574a1a7685fded90292eb48"
         ],
         "pool":"0x227c7df69d3ed1ae7574a1a7685fded90292eb48",
         "extra":{
            "prices":[
               "1260108297127984902",
               "1276394899256615323",
               "1292999305888243388",
               "1309929839687630165",
               "1327195097557417461",
               "1344803961553668927",
               "1362765610311681745",
               "1381089531009513537",
               "1399785531898341045",
               "1418863755430552809"
            ]
         },
         "price":"1260108297127984902",
         "amount":"1",
         "amounts":[
            
         ],
         "vaultId":"392",
         "currency":"0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
         "collection":"0x5af0d9827e0c53e4799bb226655a1de152a425a5",
         "specificIds":[
            "70"
         ]
      }
   },
   {
      "kind":"sudoswap",
      "data":{
         "pair":"0x44d2193a0f966245baa6cb9576d7b675adb5956b",
         "extra":{
            "prices":[
               "1213109641829303257"
            ]
         }
      }
   }
]

Supported Actions

The following actions are possible with the Router API: