Understanding Sales

Add an adapter to the Core SDK, to normalize interactions with the contract

https://github.com/reservoirprotocol/core/tree/main/packages/sdk/src

Create a directory in /packages/sdk/src and name it using only lowercase characters and dash (-) instead of space. For example: lorem-ipsum for the Lorem Ipsum protocol.

Create addresses.ts and add the protocol’s exchange contract address for each network:

// addresses.ts
 import { ChainIdToAddress, Network } from "../utils";
 
 export const Exchange: ChainIdToAddress = {
  [Network.Ethereum]: "0x9757f2d2b135150bbeb65308d4a91804107cd8d6",
  [Network.EthereumGoerli]: "0xd4a57a3bd3657d0d46b4c5bac12b3f156b9b886b",
 };

Create index.ts an export the Exchange object from addresses.ts

import * as Addresses from "./addresses";
 
 export { Addresses };
```
Edit /packages/sdk/src/index.ts to export the new protocol’s addresses.

```
import * as LoremIpsum from "./lorem-ipsum";
 
export {
...
 LoremIpsum,
 };

Start listening to and saving events (fills, cancels, etc) in the Indexer

https://github.com/reservoirprotocol/indexer/tree/v5/src/sync/events/data

import { Interface } from "@ethersproject/abi";
 import { Rarible } from "@reservoir0x/sdk";
 import { config } from "@/config/index";
 import { EventData } from "@/events-sync/data";
 
 export const match: EventData = {
  kind: "rarible-match",
  addresses: { [Rarible.Addresses.Exchange[config.chainId].toLowerCase()
 ]: true },
  topic: "0x268820db288a211986b26a8fda86b1e0046281b21206936bb0e61c67b5c79ef4",
  numTopics: 1,
  abi: new Interface([
   `event Match(
     bytes32 leftHash,
     bytes32 rightHash,
     address leftMaker,
     address rightMaker,
     uint newLeftFill,
     uint newRightFill,
     (bytes4 assetClass, bytes data) leftAsset,
     (bytes4 assetClass, bytes data) rightAsset
   )`,
 ]),
};

Create [protocol-name].ts in /src/sync/events/data and add a method for each event that will be tracked. The fields correspond to the following:

  • kind: unique identifier for the event (format: lowercase and replace spaces with dash (-))
  • addresses: an object where the key is the exchange contract address and value equal true. Use the SDK to retrieve the contract address
  • topic: the even topic. Use the following script to get this value
const { Interface } = require('@ethersproject/abi')
 
const main = () => {
 const iface = new Interface([
   `event Match(
     bytes32 leftHash,
     bytes32 rightHash,
     address leftMaker,
     address rightMaker,
     uint newLeftFill,
     uint newRightFill,
     (bytes4 assetClass, bytes data) leftAsset,
     (bytes4 assetClass, bytes data) rightAsset
   )`,
 ])
 console.log(iface.getEventTopic('Match'))
}
 
main()

If the event contains an Interface, replace it with a solidity data type. For example, from IERC20 token to address token.

To run this script you need to run npm init -y and install ethers.js yarn add ethers. Once finished, run the script using node main.js

  • numTopics: The number of topics for the event
  • abi: The event’s abi

Go to /src/sync/events/data/index.ts and

  1. Import all the methods from /src/sync/events/data/[protocol-name].ts:
    import * as rarible from "@/events-sync/data/rarible";
  2. Add new event types to the EventDataKind type. Include the type for each event created in 3. /src/sync/events/data/[protocol-name].ts
  3. Pass the events in /src/sync/events/data/[protocol-name].ts to the getEventData method.
  4. Add a case for each event to the internalGetEventData method

Create a migration file which will add [protocol-name] as a valid order kind.

In your terminal go to the root directory of the indexer repo and call
yarn migrate create -t sql [protocol-name]-order-kind

and then change the content of the generated file to:

-- Up Migration
 
ALTER TYPE "order_kind_t" ADD VALUE '[protocol-name]';
 
-- Down Migration

Go to /src/sync/events/index.ts and in the switch case of the syncEvents method add a case for each event in /src/sync/events/data/[protocol-name].ts

case "event-name": {
             const { args } = eventData.abi.parseLog(log);
             const leftHash = args["leftHash"].toLowerCase();
             const leftMaker = args["leftMaker"].toLowerCase();
             const rightMaker = args["rightMaker"].toLowerCase();
             const newLeftFill = args["newLeftFill"].toString();
             const newRightFill = args["newRightFill"].toString();
             const leftAsset = args["leftAsset"];
             const rightAsset = args["rightAsset"];
 
             // Format or modify the parsed data from `args` and
             // push a new object to the database using
             // fillEventsPartial.push()
 
             fillEventsPartial.push({
               orderKind,
               orderId,
               orderSide,
               maker,
               taker,
               price,
               contract,
               tokenId,
               amount,
               baseEventParams,
             });
 
             break;
           }

Make sure to make all the addresses lowercase.

To test the integration:

  • Run docker-compose up to bootstrap a local postgres and redis instance. (The Docker daemon must be running in the background)
  • In a separate terminal, run yarn; yarn build; yarn start to migrate the database and start the indexer
  • Run
curl -X POST -H 'Content-Type: application/json' -H 'X-Admin-Api-Key: admin' -d '{"fromBlock": 1, "toBlock": 1}’ http://localhost:3000/admin/sync-events` 

To sync events for any particular block

The results would be shown in http://localhost:3000/sales/bulk/v1

You may log the args object to debug any issues.