π² Metronome Token REST API
- Requirements
- Configuration
- Dev Setup
- Prod Setup
- REST API
- Query, Pagination & Sorting
- WebSockets Events
- License
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
ormainnet
. -
MONGO_URL
: The Mongo instance URL.I.E.
mongodb://localhost
. -
MONGO_DB_NAME
: The Mongo database name.I.E.
metronome-api
.
# Install dependencies
npm i
# Run dev mode
npm run dev
# Run test cases
npm test
# Install dependencies
npm i
# Run dev mode
npm start
-
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'stimestamp
is generated by the API according to block timestamp. ThemetaData
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 thebalance
is the amount of MET owned by that account. Thebalance
is always shown inwei
. -
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
andto
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.
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 MongoDBlimit()
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
and0
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 MongoDBsort()
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. -
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));
- Client Implementation
-
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));
- Client Implementation
-
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));
- Client Implementation