Skip to content

Commit

Permalink
Add Symbol Mapping Endpoints to API (#4)
Browse files Browse the repository at this point in the history
  • Loading branch information
qs authored Jun 9, 2022
1 parent d5ea476 commit 37bd294
Show file tree
Hide file tree
Showing 15 changed files with 1,137 additions and 108 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
# env
.env

# test payload
payload.json

# logs
*.log

Expand Down
287 changes: 277 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,29 +1,40 @@
# Symbol Mapper Tool

The symbol mapper tool is used to build and maintain an internal symbology mapping between different data providers. Often a single asset or asset pair (base/quote) may have different symbolic IDs between data providers, so a reference table must be built and maintained continuously to ensure we are using the right symbols across all relevant providers.

The tool stores the reference mapping data in a Postgres instance, and exposes an API with `GET`, `POST`, and `DELETE` endpoints to allow users to fetch and update the mapping reference data.

---

## Prerequisites
1. Clone this repo:
```
git clone https://github.com/smartcontractkit/symbol-mapper.git
```
2. Install the following tools:
- [Docker](https://docs.docker.com/get-docker/)
- [Dbmate](https://github.com/amacneil/dbmate#installation)
- [pnpm](https://pnpm.io/installation)
- [Typescript](https://www.typescriptlang.org/download)
3. Create a `.env` file in the root directory with the following variables:

---

## Environment Variables
An `.env` file in the root directory is required when using the given `compose.yaml`. The following is a template to run all containers on the same machine:
```.env
BACKEND_HOST=0.0.0.0
BACKEND_PORT=3000
DB_USER=<admin-user>
DB_PASSWORD=<admin-pass>
DB_HOST=localhost
DB_HOST=host.docker.internal
DB_PORT=5432
DB_NAME=symbol-mapper-db
DATABASE_URL="postgres://{DB_USER}:{DB_PASSWORD}@{DB_HOST}:{DB_PORT}/{DB_NAME}?sslmode=disable"
```

### Local Setup
---

## Local Setup (using Docker)
1. Pull the latest changes from `main`:
```
git checkout main
Expand All @@ -35,22 +46,278 @@ git pull
docker-compose build
docker-compose up -d
```
3. Run the DB migrations with `dbmate` to set up the schema correctly:
3. From the `backend/` directory, install packages with `pnpm` and then run the DB migrations with `knex` to set up the schema correctly. For this to work properly, you either have to export all the env vars from `.env` into your environment beforehand, or run with `dotenv-cli` (after installing with `pnpm add -g dotenv-cli`).

With env vars exported beforehand:
```
cd backend
pnpm i
knex migrate:latest
```
dbmate up

With `.env` passed directly:
```
cd backend
pnpm i
dotenv -e ../.env knex migrate:latest
```

May require to install knex globally:
```
pnpm install knex -g
```

4. To stop the containers collectively, run `docker-compose down`. Read more about [docker-compose](https://docs.docker.com/compose/) to see how to start/stop individual containers.

### DB Migrations
---

## DB Migrations
Create new DB schema migration:
```
dbmate new <migration name>
knex migrate:make <name> -x ts
```
Run pending migrations:
```
dbmate up
knex migrate:latest
```
Rollback latest migration:
```
dbmate rollback
knex migrate:rollback
```

---

## API endpoints

### Create / Update Asset Mapping

Request from `payload.json` file:
```
curl -X POST http://localhost:3000/assetMapping -d @payload.json -H "Content-Type: application/json"
payload.json
{
"asset": {
"id": "LINK",
"name": "Link",
"class": "Crypto",
"product_type": "Spot",
"status": "Confirmed"
},
"data_provider": {
"id": "coinpaprika",
"name": "Coinpaprika",
"symbol_key": "id",
"symbol": "Chainlink"
},
"status": "Confirmed"
}
```

Request from raw `JSON`:
```
curl -X POST http://localhost:3000/assetMapping -d '{ "asset": { "id": "LINK", "name": "Link", "class": "Crypto", "product_type": "Spot", "status": "Confirmed" }, "data_provider": { "id": "coinpaprika", "name": "Coinpaprika", "symbol_key": "id", "symbol": "Chainlink" }, "status": "Confirmed" }' -H "Content-Type: application/json"
```

**Optional fields: `status`, `asset_class`, `asset_product_type`, `asset_status`**

Response:
```
{
"status": 201,
"msg": "Resource Added"
}
```

### Create / Update Asset Pair Mapping

Request from `payload.json` file:
```
curl -X POST http://localhost:3000/assetPairMapping -d @payload.json -H "Content-Type: application/json"
payload.json
{
"base_asset": {
"id": "LINK",
"name": "Link",
"class": "Crypto",
"product_type": "Spot",
"status": "Confirmed"
},
"quote_asset": {
"id": "USD",
"name": "U.S. Dollar",
"class": "Equity",
"product_type": "Spot",
"status": "Confirmed"
},
"asset_pair": {
"id": "LINK/USD",
"status": "Confirmed"
},
"data_provider": {
"id": "coinpaprika",
"name": "Coinpaprika",
"symbol_key": "id",
"symbol": "Chainlink"
},
"status": "Confirmed"
}
```

Request from raw `JSON`:
```
curl -X POST http://localhost:3000/assetMapping -d '{ "base_asset": { "id": "LINK", "name": "Link", "class": "Crypto", "product_type": "Spot", "status": "Confirmed" }, "quote_asset": { "id": "USD", "name": "U.S. Dollar", "class": "Equity", "product_type": "Spot", "status": "Confirmed" }, "asset_pair": { "id": "LINK/USD", "status": "Confirmed" }, "data_provider": { "id": "coinpaprika", "name": "Coinpaprika", "symbol_key": "id", "symbol": "Chainlink"}, "status": "Confirmed" }' -H "Content-Type: application/json"
```

**Optional fields: `status`, `<base/quote>_asset_class`, `<base/quote>_asset_product_type`, `<base/quote>_asset_status`**

Response:
```
{
"status": 201,
"msg": "Resource Added"
}
```

### Get Asset Mapping

Request:
```
curl http://localhost:3000/assetMapping
```

Response:
```
[
{
"asset_id": "LINK",
"data_provider_id": "coinpaprika",
"data_provider_symbol": "Chainlink",
"status": "Confirmed",
"suggested_status": null,
"created_at": "2022-06-01T13:54:27.222Z",
"updated_at": "2022-06-01T13:54:27.222Z",
"id": "LINK",
"name": "Link",
"class": "Crypto",
"product_type": "Spot"
}
]
```

### Get Mapping Tables

Request:
**note: the `tables` parameter should be a comma-separated list of the following options: `asset`, `asset_mapping`, `asset_pair`, `asset_pair_mapping`, and `data_provider`.
```
curl "http://localhost:3000/mappingTables?tables=asset,asset_mapping,data_provider" -H "Content-Type: application/json"
```

Response:
```
{
"asset_mapping": [
{
"asset_id":"LINK",
"data_provider_id":"coinpaprika",
"data_provider_symbol":"Chainlink",
"status":"Confirmed",
"suggested_status":null,
"created_at":"2022-06-09T04:53:45.303Z",
"updated_at":"2022-06-09T12:43:37.838Z"
}
],
"asset": [
{
"id":"USD",
"name":"U.S. Dollar",
"class":"Equity",
"product_type":"Spot",
"status":"Confirmed",
"created_at":"2022-06-08T21:50:40.942Z",
"updated_at":"2022-06-09T04:49:11.727Z"
},
{
"id":"LINK",
"name":"Link",
"class":"Crypto",
"product_type":"Spot",
"status":"Confirmed",
"created_at":"2022-06-08T21:50:40.942Z",
"updated_at":"2022-06-09T12:43:37.838Z"
}
],
"data_provider": [
{
"id":"coinpaprika",
"name":"Coinpaprika",
"symbol_key":"id",
"created_at":"2022-06-08T21:50:40.942Z",
"updated_at":"2022-06-09T12:43:37.838Z"
}
]
}
```

### Delete Asset

Request:
```
curl -X DELETE "http://localhost:3000/asset?asset_id=LINK"
```

Response:
```
{
"status": 204,
"msg": "Resource Removed"
}
```

### Delete Data Provider

Request:
```
curl -X DELETE "http://localhost:3000/dataProvider?data_provider_id=coinpaprika"
```

Response:
```
{
"status": 204,
"msg": "Resource Removed"
}
```

### Delete Asset Mapping

Request:
```
curl -X DELETE "http://localhost:3000/assetMapping?asset_id=LINK&data_provider_id=coinpaprika"
```

Response:
```
{
"status": 204,
"msg": "Resource Removed"
}
```

### Delete Asset Pair Mapping

Request:
```
curl -X DELETE "http://localhost:3000/assetPairMapping?asset_pair_id=LINKUSD&data_provider_id=coinpaprika"
```

Response:
```
{
"status": 204,
"msg": "Resource Removed"
}
```

---
48 changes: 48 additions & 0 deletions backend/knexfile.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import type { Knex } from "knex";
import * as db_config from './src/config'

const config: { [key: string]: Knex.Config } = {
development: {
client: "pg",
connection: {
host: db_config.DB_HOST,
port: db_config.DB_PORT,
user: db_config.DB_USER,
password: db_config.DB_PASSWORD,
database: db_config.DB_NAME,
},
migrations: {
tableName: 'migrations'
}
},

staging: {
client: "pg",
connection: {
host: db_config.DB_HOST,
port: db_config.DB_PORT,
user: db_config.DB_USER,
password: db_config.DB_PASSWORD,
database: db_config.DB_NAME,
},
migrations: {
tableName: 'migrations'
}
},

production: {
client: "pg",
connection: {
host: db_config.DB_HOST,
port: db_config.DB_PORT,
user: db_config.DB_USER,
password: db_config.DB_PASSWORD,
database: db_config.DB_NAME,
},
migrations: {
tableName: 'migrations'
}
}
};

module.exports = config;
Loading

0 comments on commit 37bd294

Please sign in to comment.