Skip to content
💻 Metronome Token REST API
JavaScript Dockerfile
Branch: develop
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
config
doc
lib
logger
patches
route
schema
test
.dockerignore
.eslintignore
.eslintrc.json
.gitignore
.npmrc
.travis.yml
Dockerfile
LICENSE
README.md
logo.png
newrelic.js
package-lock.json
package.json
server.js

README.md

Metronome API

🖲 Metronome Token REST API

Build Status Code Style Known Vulnerabilities

Index

  1. Requirements
  2. Configuration
  3. Dev Setup
  4. Prod Setup
  5. REST API
  6. Query, Pagination & Sorting
  7. WebSockets Events
  8. License

Requirements

Configuration

The following environment variables are needed for the API to work:

  • ETH_WS_URL: The WebSocket URL of the Ethereum node.

    I.E. ws://node.metronome.io:8546.

  • ETH_CHAIN: The name of the Ethereum chain.

    I.E. ropsten or mainnet.

  • MONGO_URL: The Mongo instance URL.

    I.E. mongodb://localhost.

  • MONGO_DB_NAME: The Mongo database name.

    I.E. metronome-api.

Dev Setup

# Install dependencies
npm i

# Run dev mode
npm run dev

# Run test cases
npm test

Prod Setup

# Install dependencies
npm i

# Run dev mode
npm start

REST API

  • GET /

    Will return a JSON object with basic information like project name and versions

    {
      "name": "metronome-api",
      "version": "1.0.0"
    }
  • GET /status

    Will return a 204 HTTP status code while the API is up and running.

  • GET /event

    Will return a JSON object that contains an array with all the events processed by the API exporter. This list includes past events and new events retrieved from ETH node through web3. This endpoint will also return the total amount of events.

    {
      "count": 2,
      "events": [
        {
          "_id": "552776_0_2",
          "metaData": {
            "address": "0x825A2cE3547e77397b7EAc4eb464E2eDCFaAE514",
            "blockHash":
              "0x198cf44b2175f0927a19c14c81ff4d0b680b1689cb2688253cd3b6f43219719e",
            "blockNumber": 552776,
            "logIndex": 2,
            "transactionHash":
              "0x1c31d0459ff37a518acaafb73b75d9fc1db36745c7c3ce8b6025d1ea3a564076",
            "transactionIndex": 0,
            "returnValues": {},
            "event": "Transfer",
            "topics": [],
            "timestamp": 1520534045
          }
        },
        {
          "_id": "552776_0_3",
          "metaData": {
            "address": "0xa25A2cE3547e77397b7EAc4eb464E2eDCFaAE511",
            "blockHash":
              "0x198cf44b2175f0927a19c14c81ff4d0b680b1689cb2688253cd3b6f43219719e",
            "blockNumber": 552776,
            "logIndex": 3,
            "transactionHash":
              "0x1c31d0459ff37a518acaafb73b75d9fc1db36745c7c3ce8b6025d1ea3a564076",
            "transactionIndex": 0,
            "returnValues": {},
            "event": "Approval",
            "topics": [],
            "timestamp": 1520534045
          }
        }
      ]
    }

    The event's _id is generated by the API based on block number, transaction index and log index. The event's timestamp is generated by the API according to block timestamp. The metaData object is basically the entire output we retrieved from the ETH node using web3. So this object could contain different properties depending the event.

  • GET /event/account/:address

    Will return a JSON object with an array that contains all events matching the given address parameter. The match will be succeded if any of these properties: metaData.returnValues._from, metaData.returnValues._to, metaData.returnValues._owner, metaData.returnValues._spender are equals to the given address. This endpoint will also return the total amount matching events.

    I.E. GET /event/account/0xa25A2cE3547e77397b7EAc4eb464E2eDCFaAE511

    {
      "count": 1,
      "events": [
        {
          "_id": "552776_0_3",
          "metaData": {
            "address": "0xa25A2cE3547e77397b7EAc4eb464E2eDCFaAE511",
            "blockHash":
              "0x198cf44b2175f0927a19c14c81ff4d0b680b1689cb2688253cd3b6f43219719e",
            "blockNumber": 552776,
            "logIndex": 3,
            "transactionHash":
              "0x1c31d0459ff37a518acaafb73b75d9fc1db36745c7c3ce8b6025d1ea3a564076",
            "transactionIndex": 0,
            "returnValues": {},
            "event": "Approval",
            "topics": [],
            "timestamp": 1520534045
          }
        }
      ]
    }
  • GET /event/:id

    Will return a JSON object with the event that matchs the given id parameter.

    I.E. GET /event/552776_0_3

    {
      "_id": "552776_0_3",
      "metaData": {
        "address": "0xa25A2cE3547e77397b7EAc4eb464E2eDCFaAE511",
        "blockHash":
          "0x198cf44b2175f0927a19c14c81ff4d0b680b1689cb2688253cd3b6f43219719e",
        "blockNumber": 552776,
        "logIndex": 3,
        "transactionHash":
          "0x1c31d0459ff37a518acaafb73b75d9fc1db36745c7c3ce8b6025d1ea3a564076",
        "transactionIndex": 0,
        "returnValues": {},
        "event": "Approval",
        "topics": [],
        "timestamp": 1520534045
      }
    }
  • GET /account

    Will return a JSON object that contains an array with all the accounts stored by the API exporter. Any time an address appears in a new transaction, the exporter updates the MET balance corresponding to that address and stores the value in MongoDB. This endpoint will also return the total amount of accounts.

    {
      "count": 2,
      "accounts": [
        {
          "_id": "0x25d99454D94D9459f0aBB06009840A48bD04ca44",
          "balance": "0",
          "updatedAt": "2018-03-20T21:29:02.410Z"
        },
        {
          "_id": "0x0EE6101fE14E198Fc0f617B56A85A3Ae5EaAB245",
          "balance": "999999500000000000000000",
          "updatedAt": "2018-03-20T21:28:31.076Z"
        }
      ]
    }

    The account's _id is the address and the balance is the amount of MET owned by that account. The balance is always shown in wei.

  • GET /account/:address

    Will return a JSON object with the account that matchs the given address parameter.

    I.E. GET /account/0x0EE6101fE14E198Fc0f617B56A85A3Ae5EaAB245

    {
      "_id": "0x0EE6101fE14E198Fc0f617B56A85A3Ae5EaAB245",
      "balance": "999999500000000000000000",
      "updatedAt": "2018-03-20T21:28:31.076Z"
    },
  • GET /history?from&to

    Will return auction and converter historical data points between from and to times. The two parameters are optional and will default to the last hour if not specified. The result will be an array of data points with a maximun length of 100 items.

    I.E. GET /history

    [
      {
          "_id": 1543436051,
          "_lastPurchasePrice": "7591582931609796",
          "currAuction": "157",
          "currentAuctionPrice": "7591582931609796",
          "currTick": "235933",
          "_dailyMintable": "2880000000000000000000",
          "hash": "0xcf7a685ed11fdb1dfb42b4f77692aa579b8ad562068b38c78af09bd86933793b",
          "minting": "0",
          "number": 6790138,
          "proceedsBal": "20513204809437326749593",
          "timestamp": 1543436051,
          "totalMET": "10452160000000000000000000",
          "availableMet": "645158546385600485235111",
          "availableEth": "4959324846430778366640",
          "currentConverterPrice": "7686962375818597"
      },
      ...
    ]
  • GET /history/auction?from&to

    Similar to GET /history but will use a downsampling algorithm that is better suited for auction data. Therefore the data points will represent much better the actual auction price behavior over time, removing the consecutive equal-price data points first and then downsampling.

Query, Pagination & Sorting

Endpoints that retrieve multiple results, (like GET /event and GET /account) allow MongoDB queries, pagination and sorting. You can even combine this features in a single query.

  • Query

    You can set some MongoDB allowed queries using URL query string format to filter and get specific results. Here some examples:

    • Get all events with address equals to 0x825A2cE3547e77397b7EAc4eb464E2eDCFaAE514

      GET /event?metaData.address=0x825A2cE3547e77397b7EAc4eb464E2eDCFaAE514

    • Get all accounts with balance equals to 0

      GET /account?balance=0

  • Pagination

    You can use the keys $limit and $skip as query string values to paginate the results. Internally the API uses MongoDB limit() and $skip() methods.

    • Get first set of 5 events

      GET /event?$limit=5

    • Get second set of 5 events

      GET /event?$limit=5$skip=0

    The defaults values are 1000 for $limit and 0 for $skip

  • Sorting

    You can use the $sort key as query string vlaue to set the desired order to retrieve the results. Internally the API uses MongoDB sort() method.

    • Get accounts sort by balance

      GET /account?$sort=balance

      GET /account?$sort=-balance

    • Get events sort by timestamp

      GET /event?$sort=metaData.timestamp

      GET /event?$sort=-metaData.timestamp

    Use the prefix - to set descending order.

WebSocket Events

The API is integrated with socket.io to dispatch different kind of web socket events and be able to handle information by clients in real time. Using the socket.io client you must be able to establish a connection with the API and start listening for new events.

import io from "socket.io-client";
const socket = io("http://localhost:3002"); // API URL
  • status-updated

    This event is emitted any time the status of MET auction and converter changes. It provides a JSON object with the Initial / Daily Auctions and Converter information

    {
      "auction": {
        "currentAuction": "10",
        "currentPrice": "3300000000000",
        "genesisTime": 1520035200,
        "lastPurchasePrice": "3300000000000",
        "lastPurchaseTime": 1521508680,
        "nextAuctionStartTime": 1521590400,
        "tokenSupply": "10028800000000000000000000",
        "tokenRemaining": "0",
        "tokenSold": "10028800000000000000000000",
      },
      "converter": {
        "availableMet": "55676878422677971892811",
        "availableEth": "491097768014131034348",
        "currentPrice": "8820180684783793"
      }
    }
    • Client Implementation

      import io from "socket.io-client";
      const socket = io("http://localhost:3002"); // API URL
      socket.on("status-updated", ({ auction, converter }) =>
        console.log("Auction status: ", auction)
        console.log("Converter status", converter)
      );
  • NEW_EVENT

    This event is emitted any time the API exporter process a new ETH event. Attaching to this event you can get all new ETH events in real time without making HTTP request to REST API.

    {
      "_id": "552776_0_3",
      "metaData": {
        "address": "0xa25A2cE3547e77397b7EAc4eb464E2eDCFaAE511",
        "blockHash":
          "0x198cf44b2175f0927a19c14c81ff4d0b680b1689cb2688253cd3b6f43219719e",
        "blockNumber": 552776,
        "logIndex": 3,
        "transactionHash":
          "0x1c31d0459ff37a518acaafb73b75d9fc1db36745c7c3ce8b6025d1ea3a564076",
        "transactionIndex": 0,
        "returnValues": {},
        "event": "Approval",
        "topics": [],
        "timestamp": 1520534045
      }
    }

    The output is the same you get when you request events using REST API events endpoints.

    • Client Implementation
      import io from "socket.io-client";
      const socket = io("http://localhost:3002"); // API URL
      socket.on("NEW_EVENT", event => console.log(event));
  • LATEST_BLOCK

    This event is emitted any time a new block is mined. Attaching to this event you can get the entire new block information.

    {
      "author": "0x0a194f4b9f5f904ec3b4548d63bee1c55b1d61d6",
      "difficulty": "2628345",
      "extraData": "0xd583010701846765746885676f312e39856c696e7578",
      "gasLimit": 4712388,
      "gasUsed": 0,
      "hash":
        "0x26475158371994b10caeb098f0efc8c71c18e02f441a43fa9262ed26699ed85b",
      "logsBloom": "",
      "miner": "0x0a194f4b9F5F904EC3b4548d63Bee1C55b1D61d6",
      "mixHash":
        "0xc58740831a5041fa618ce10d8e072785de37750897a1539835a87d2eea0c4905",
      "nonce": "0x079ad3803a89f70e",
      "number": 623303,
      "parentHash":
        "0x0e70a313ee49736bdb0f72000d9d0850cb781ea185f56c05dc94f5bdbd8c9c51",
      "receiptsRoot":
        "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
      "sealFields": [],
      "sha3Uncles":
        "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
      "size": 536,
      "stateRoot":
        "0xaa584ee7a8d30599cb904a16562424bb0c233fdf2a6a1d3ef8c6eccea7349618",
      "timestamp": 1521584303,
      "totalDifficulty": "431363800748",
      "transactions": [],
      "transactionsRoot":
        "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
      "uncles": []
    }
    • Client Implementation
      import io from "socket.io-client";
      const socket = io("http://localhost:3002"); // API URL
      socket.on("LATEST_BLOCK", block => console.log(block));
  • BALANCE_UPDATED

    This event is emitted any time a API exporter updates an account's balance. Attaching to this event you can get balances updates in real time

    {
      "_id": "0x0EE6101fE14E198Fc0f617B56A85A3Ae5EaAB245",
      "balance": "999999500000000000000000"
    }
    • Client Implementation
      import io from "socket.io-client";
      const socket = io("http://localhost:3002"); // API URL
      socket.on("BALANCE_UPDATED", account => console.log(account));

LICENSE

MIT License.

You can’t perform that action at this time.