Repository: trustwallet/blockatlas
Pull request #840 (2020-02-12 02:41:41)

Update to microservices architecture
1. Split markets, swagger, platform, observer to workers and rest APIs
2. Update swagger docs to remove double handlers
3. New Rancher CI/CD and production  

Still in progress 


Patch:
diff --git a/.goreleaser.yml b/.goreleaser.yml
index 78ed5dc..a9ea728 100644
--- a/.goreleaser.yml
+++ b/.goreleaser.yml
@@ -21,9 +21,9 @@ builds:
       - amd64
     env:
       - CGO_ENABLED=0
-  - id: syncmarkets
-    binary: syncmarkets
-    main: "./cmd/syncmarkets/main.go"
+  - id: market
+    binary: market
+    main: "./cmd/market/main.go"
     goos:
       - linux
     goarch:
diff --git a/Makefile b/Makefile
index 71ccab7..4e1284e 100644
--- a/Makefile
+++ b/Makefile
@@ -4,9 +4,12 @@
 VERSION := $(shell git describe --tags)
 BUILD := $(shell git rev-parse --short HEAD)
 PROJECT_NAME := $(shell basename "$(PWD)")
-API_SERVICE := api
-OBSERVER_SERVICE := observer
-SYNC_SERVICE := syncmarkets
+API_SERVICE := platform_api
+OBSERVER_SERVICE := platform_observer
+OBSERVER_API := observer_api
+MARKET_SERVICE := market_observer
+MARKET_API := market_api
+SWAGGER_API := swagger_api
 COIN_FILE := coin/coins.yml
 COIN_GO_FILE := coin/coins.go
 GEN_COIN_FILE := coin/gen.go
@@ -31,8 +34,10 @@ STDERR := /tmp/.$(PROJECT_NAME)-stderr.txt
 # PID file will keep the process id of the server
 PID_API := /tmp/.$(PROJECT_NAME).$(API_SERVICE).pid
 PID_OBSERVER := /tmp/.$(PROJECT_NAME).$(OBSERVER_SERVICE).pid
-PID_SYNC := /tmp/.$(PROJECT_NAME).$(SYNC_SERVICE).pid
-
+PID_OBSERVER_API := /tmp/.$(PROJECT_NAME).$(OBSERVER_API).pid
+PID_MARKET := /tmp/.$(PROJECT_NAME).$(MARKET_SERVICE).pid
+PID_MARKET_API := /tmp/.$(PROJECT_NAME).$(MARKET_API).pid
+PID_SWAGGER_API := /tmp/.$(PROJECT_NAME).$(SWAGGER_API).pid
 # Make is verbose in Linux. Make it silent.
 MAKEFLAGS += --silent
 
@@ -41,36 +46,60 @@ install: go-get
 
 ## start: Start API, Observer and Sync in development mode.
 start:
-	@bash -c "$(MAKE) clean compile start-api start-observer start-syncmarkets"
+	@bash -c "$(MAKE) clean compile start-platform-api start-platform-observer start-observer-api start-market-observer start-market-api"
 
 ## start-api: Start API in development mode.
-start-api: stop
+start-platform-api: stop
 	@echo "  >  Starting $(PROJECT_NAME) API"
-	@-$(GOBIN)/$(API_SERVICE)/api -c $(CONFIG_FILE) 2>&1 & echo $$! > $(PID_API)
+	@-$(GOBIN)/$(API_SERVICE)/platform_api -c $(CONFIG_FILE) 2>&1 & echo $$! > $(PID_API)
 	@cat $(PID_API) | sed "/^/s/^/  \>  API PID: /"
 	@echo "  >  Error log: $(STDERR)"
 
 ## start-observer: Start Observer in development mode.
-start-observer: stop
+start-platform-observer: stop
 	@echo "  >  Starting $(PROJECT_NAME) Observer"
-	@-$(GOBIN)/$(OBSERVER_SERVICE)/observer -c $(CONFIG_FILE) 2>&1 & echo $$! > $(PID_OBSERVER)
+	@-$(GOBIN)/$(OBSERVER_SERVICE)/platform_observer -c $(CONFIG_FILE) 2>&1 & echo $$! > $(PID_OBSERVER)
 	@cat $(PID_OBSERVER) | sed "/^/s/^/  \>  Observer PID: /"
 	@echo "  >  Error log: $(STDERR)"
 
-## start-sync-markets: Start Sync markets in development mode.
-start-syncmarkets: stop
+## start-observer: Start Observer in development mode.
+start-observer-api: stop
+	@echo "  >  Starting $(PROJECT_NAME) Observer"
+	@-$(GOBIN)/$(OBSERVER_API)/observer_api -c $(CONFIG_FILE) 2>&1 & echo $$! > $(PID_OBSERVER_API)
+	@cat $(PID_OBSERVER_API) | sed "/^/s/^/  \>  Observer PID: /"
+	@echo "  >  Error log: $(STDERR)"
+
+## start-sync-market: Start Sync market in development mode.
+start-market-observer: stop
 	@echo "  >  Starting $(PROJECT_NAME) Sync"
-	@-$(GOBIN)/$(SYNC_SERVICE)/syncmarkets -c $(CONFIG_FILE) 2>&1 & echo $$! > $(PID_SYNC)
-	@cat $(PID_SYNC) | sed "/^/s/^/  \>  Sync PID: /"
+	@-$(GOBIN)/$(MARKET_SERVICE)/market_observer -c $(CONFIG_FILE) 2>&1 & echo $$! > $(PID_MARKET)
+	@cat $(PID_MARKET) | sed "/^/s/^/  \>  Sync PID: /"
+	@echo "  >  Error log: $(STDERR)"
+
+## start-sync-market-api: Start Sync market api in development mode.
+start-market-api: stop
+	@echo "  >  Starting $(PROJECT_NAME) Sync API"
+	@-$(GOBIN)/$(MARKET_API)/market_api -c $(CONFIG_FILE) 2>&1 & echo $$! > $(PID_MARKET_API)
+	@cat $(PID_MARKET_API) | sed "/^/s/^/  \>  Sync PID: /"
+	@echo "  >  Error log: $(STDERR)"
+
+## start-sync-market-api: Start Sync market api in development mode.
+start-swagger-api: stop
+	@echo "  >  Starting $(PROJECT_NAME) Sync API"
+	@-$(GOBIN)/$(SWAGGER_API)/swagger_api -c $(CONFIG_FILE) 2>&1 & echo $$! > $(PID_SWAGGER_API)
+	@cat $(PID_SWAGGER_API) | sed "/^/s/^/  \>  Sync PID: /"
 	@echo "  >  Error log: $(STDERR)"
 
 ## stop: Stop development mode.
 stop:
-	@-touch $(PID_API) $(PID_OBSERVER)
+	@-touch $(PID_API) $(PID_OBSERVER) $(PID_OBSERVER_API) $(PID_MARKET) $(PID_MARKET_API) $(PID_SWAGGER_API)
 	@-kill `cat $(PID_API)` 2> /dev/null || true
 	@-kill `cat $(PID_OBSERVER)` 2> /dev/null || true
-	@-kill `cat $(PID_SYNC)` 2> /dev/null || true
-	@-rm $(PID_API) $(PID_OBSERVER)
+	@-kill `cat $(PID_OBSERVER_API)` 2> /dev/null || true
+	@-kill `cat $(PID_MARKET)` 2> /dev/null || true
+	@-kill `cat $(PID_MARKET_API)` 2> /dev/null || true
+	@-kill `cat $(PID_SWAGGER_API)` 2> /dev/null || true
+	@-rm $(PID_API) $(PID_OBSERVER) $(PID_OBSERVER_API) $(PID_MARKET) $(PID_MARKET_API) $(PID_SWAGGER_API)
 
 ## compile: Compile the project.
 compile:
@@ -130,15 +159,6 @@ endif
 ## newman: Run Postman Newman test, the host parameter is required, and you can specify the name of the test do you wanna run (transaction, token, staking, collection, domain, healthcheck, observer). e.g $ make newman test=staking host=http//localhost
 newman: install-newman
 	@echo "  >  Runing $(test) tests"
-ifndef observer_auth
-override observer_auth = "test"
-endif
-ifndef market_auth
-override market_auth = ""
-endif
-ifndef platform_auth
-override platform_auth = ""
-endif
 ifeq (,$(host))
 	@echo "  >  Host parameter is missing. e.g: make newman test=staking host=http://localhost:8420"
 	@exit 1
@@ -153,18 +173,24 @@ ifeq (,$(test))
 	@bash -c "$(MAKE) newman test=observer host=$(host)"
 	@bash -c "$(MAKE) newman test=market host=$(host)"
 else
-	@newman run pkg/tests/postman/Blockatlas.postman_collection.json --folder $(test) -d pkg/tests/postman/$(test)_data.json --env-var "host=$(host)" --env-var "observer_auth=$(observer_auth)" --env-var "platform_auth=$(platform_auth)" --env-var "market_auth=$(market_auth)"
+	@newman run pkg/tests/postman/Blockatlas.postman_collection.json --folder $(test) -d pkg/tests/postman/$(test)_data.json --env-var "host=$(host)"
 endif
 
 go-compile: go-get go-build
 
 go-build:
-	@echo "  >  Building api binary..."
-	GOBIN=$(GOBIN) go build $(LDFLAGS) -o $(GOBIN)/$(API_SERVICE)/api ./cmd/$(API_SERVICE)
-	@echo "  >  Building syncmarkets binary..."
-	GOBIN=$(GOBIN) go build $(LDFLAGS) -o $(GOBIN)/$(SYNC_SERVICE)/syncmarkets ./cmd/$(SYNC_SERVICE)
-	@echo "  >  Building observer binary..."
-	GOBIN=$(GOBIN) go build $(LDFLAGS) -o $(GOBIN)/$(OBSERVER_SERVICE)/observer ./cmd/$(OBSERVER_SERVICE)
+	@echo "  >  Building platform_api binary..."
+	GOBIN=$(GOBIN) go build $(LDFLAGS) -o $(GOBIN)/$(API_SERVICE)/platform_api ./cmd/$(API_SERVICE)
+	@echo "  >  Building market_observer binary..."
+	GOBIN=$(GOBIN) go build $(LDFLAGS) -o $(GOBIN)/$(MARKET_SERVICE)/market_observer ./cmd/$(MARKET_SERVICE)
+	@echo "  >  Building market_api binary..."
+	GOBIN=$(GOBIN) go build $(LDFLAGS) -o $(GOBIN)/$(MARKET_API)/market_api ./cmd/$(MARKET_API)
+	@echo "  >  Building platform_observer binary..."
+	GOBIN=$(GOBIN) go build $(LDFLAGS) -o $(GOBIN)/$(OBSERVER_SERVICE)/platform_observer ./cmd/$(OBSERVER_SERVICE)
+	@echo "  >  Building observer_api binary..."
+	GOBIN=$(GOBIN) go build $(LDFLAGS) -o $(GOBIN)/$(OBSERVER_API)/observer_api ./cmd/$(OBSERVER_API)
+	@echo "  >  Building swagger_api binary..."
+	GOBIN=$(GOBIN) go build $(LDFLAGS) -o $(GOBIN)/$(SWAGGER_API)/swagger_api ./cmd/$(SWAGGER_API)
 
 go-generate:
 	@echo "  >  Generating dependency files..."
@@ -203,7 +229,7 @@ go-gen-coins:
 
 go-gen-docs:
 	@echo "  >  Generating swagger files"
-	swag init -g ./cmd/api/main.go -o ./docs
+	swag init -g ./cmd/platform_api/main.go -o ./docs
 
 go-goreleaser:
 	@echo "  >  Releasing a new version"
diff --git a/Procfile b/Procfile
index 2f26c14..4b7f58f 100644
--- a/Procfile
+++ b/Procfile
@@ -1,3 +1,5 @@
-web: bin/api -p $PORT -c config.yml
-observer: bin/observer -c config.yml
-market: bin/syncmarkets -c config.yml
+platform_api: bin/platform_api -p $PORT -c config.yml
+platform_observer: bin/platform_observer -c config.yml
+observer_api: bin/observer_api -p $PORT -c config.yml
+market_api: bin/market_api -p $PORT -c config.yml
+market_observer: bin/market_observer -c config.yml
diff --git a/api/batch.go b/api/batch.go
index bbfc76e..a6bebd7 100644
--- a/api/batch.go
+++ b/api/batch.go
@@ -33,7 +33,7 @@ type CoinsRequest []CoinBatchRequest
 // @Description Get Stake Delegations for multiple coins
 // @Accept json
 // @Produce json
-// @Tags platform,staking
+// @Tags Platform-Staking
 // @Param delegations body api.AddressesRequest true "Validators addresses and coins"
 // @Success 200 {object} blockatlas.DelegationsBatchPage
 // @Router /v2/staking/delegations [post]
@@ -70,8 +70,8 @@ func makeStakingDelegationsBatchRoute(router gin.IRouter) {
 // @Description Get Stake Delegations for multiple coins
 // @Accept json
 // @Produce json
-// @Tags platform,staking
-// @Param delegations body api.CoinsRequest true "Validators addresses and coins"
+// @Tags Platform-Staking
+// @Param delegations body api.AddressesRequest true "Validators addresses and coins"
 // @Success 200 {object} blockatlas.DelegationsBatchPage
 // @Router /v2/staking/list [post]
 func makeStakingDelegationsSimpleBatchRoute(router gin.IRouter) {
@@ -104,7 +104,7 @@ func makeStakingDelegationsSimpleBatchRoute(router gin.IRouter) {
 // @Summary Get list of collections from a specific coin and addresses
 // @Accept json
 // @Produce json
-// @Tags Collectibles
+// @Tags Platform-Collections
 // @Param data body string true "Payload" default({"60": ["0xb3624367b1ab37daef42e1a3a2ced012359659b0"]})
 // @Success 200 {object} blockatlas.DocsResponse
 // @Router /v2/collectibles/categories [post]
@@ -144,7 +144,7 @@ func oldMakeCategoriesBatchRoute(router gin.IRouter) {
 // @Summary Get list of collections from a specific coin and addresses
 // @Accept json
 // @Produce json
-// @Tags Collectibles
+// @Tags Platform-Collections
 // @Param data body string true "Payload" default({"60": ["0xb3624367b1ab37daef42e1a3a2ced012359659b0"]})
 // @Success 200 {object} blockatlas.DocsResponse
 // @Router /v3/collectibles/categories [post]
diff --git a/api/handlers.go b/api/handlers.go
index 8937d82..faca610 100644
--- a/api/handlers.go
+++ b/api/handlers.go
@@ -16,7 +16,7 @@ import (
 // @Description Get transactions from the address
 // @Accept json
 // @Produce json
-// @Tags platform,tx
+// @Tags Platform-Transactions
 // @Param coin path string true "the coin name" default(tezos)
 // @Param address path string true "the query address" default(tz1WCd2jm4uSt4vntk4vSuUWoZQGhLcDuR9q)
 // @Failure 500 {object} ginutils.ApiError
@@ -30,7 +30,7 @@ func makeTxRouteV1(router gin.IRouter, api blockatlas.Platform) {
 // @Description Get transactions from the address
 // @Accept json
 // @Produce json
-// @Tags platform,tx
+// @Tags Platform-Transactions
 // @Param coin path string true "the coin name" default(tezos)
 // @Param address path string true "the query address" default(tz1WCd2jm4uSt4vntk4vSuUWoZQGhLcDuR9q)
 // @Success 200 {object} blockatlas.TxPage
@@ -112,7 +112,7 @@ func makeTxRoute(router gin.IRouter, api blockatlas.Platform, path string) {
 // @Description Get all collections from the address
 // @Accept json
 // @Produce json
-// @Tags platform,collection
+// @Tags Platform-Collections
 // @Param coin path string true "the coin name" default(ethereum)
 // @Param address path string true "the query address" default(0x5574Cd97432cEd0D7Caf58ac3c4fEDB2061C98fB)
 // @Success 200 {object} blockatlas.CollectionPage
@@ -143,7 +143,7 @@ func oldMakeCollectionsRoute(router gin.IRouter, api blockatlas.Platform) {
 // @Description Get all collections from the address
 // @Accept json
 // @Produce json
-// @Tags platform,collection
+// @Tags Platform-Collections
 // @Param coin path string true "the coin name" default(ethereum)
 // @Param address path string true "the query address" default(0x5574Cd97432cEd0D7Caf58ac3c4fEDB2061C98fB)
 // @Success 200 {object} blockatlas.CollectionPage
@@ -173,7 +173,7 @@ func makeCollectionsRoute(router gin.IRouter, api blockatlas.Platform) {
 // @Description Get a collection from the address
 // @Accept json
 // @Produce json
-// @Tags platform,collection
+// @Tags Platform-Collections
 // @Param coin path string true "the coin name" default(ethereum)
 // @Param owner path string true "the query address" default(0x0875BCab22dE3d02402bc38aEe4104e1239374a7)
 // @Param collection_id path string true "the query collection" default(0x06012c8cf97bead5deae237070f9587f8e7a266d)
@@ -205,7 +205,7 @@ func oldMakeCollectionRoute(router gin.IRouter, api blockatlas.Platform) {
 // @Description Get a collection from the address
 // @Accept json
 // @Produce json
-// @Tags platform,collection
+// @Tags Platform-Collections
 // @Param coin path string true "the coin name" default(ethereum)
 // @Param owner path string true "the query address" default(0x0875BCab22dE3d02402bc38aEe4104e1239374a7)
 // @Param collection_id path string true "the query collection" default(0x06012c8cf97bead5deae237070f9587f8e7a266d)
@@ -236,7 +236,7 @@ func makeCollectionRoute(router gin.IRouter, api blockatlas.Platform) {
 // @Description Get tokens from the address
 // @Accept json
 // @Produce json
-// @Tags platform,token
+// @Tags Platform-Transactions
 // @Param coin path string true "the coin name" default(ethereum)
 // @Param address path string true "the query address" default(0x5574Cd97432cEd0D7Caf58ac3c4fEDB2061C98fB)
 // @Success 200 {object} blockatlas.CollectionPage
@@ -267,11 +267,6 @@ func makeTokenRoute(router gin.IRouter, api blockatlas.Platform) {
 	})
 }
 
-// @Summary Get Metrics
-// @ID metrics
-// @Description Get application metrics
-// @Tags metrics
-// @Router /metrics [get]
 func MakeMetricsRoute(router gin.IRouter) {
 	router.Use(metrics.PromMiddleware())
 	m := router.Group("/metrics")
diff --git a/api/maketdata.go b/api/maketdata.go
index aeb026e..d8633e8 100644
--- a/api/maketdata.go
+++ b/api/maketdata.go
@@ -4,13 +4,13 @@ import (
 	"github.com/gin-gonic/gin"
 	"github.com/spf13/viper"
 	"github.com/trustwallet/blockatlas/coin"
+	"github.com/trustwallet/blockatlas/market"
 	"github.com/trustwallet/blockatlas/pkg/blockatlas"
 	"github.com/trustwallet/blockatlas/pkg/ginutils"
 	"github.com/trustwallet/blockatlas/pkg/ginutils/gincache"
 	"github.com/trustwallet/blockatlas/pkg/logger"
 	"github.com/trustwallet/blockatlas/services/assets"
 	"github.com/trustwallet/blockatlas/storage"
-	"github.com/trustwallet/blockatlas/syncmarkets"
 	"math/big"
 	"net/http"
 	"strconv"
@@ -48,7 +48,7 @@ func SetupMarketAPI(router gin.IRouter, db storage.Market) {
 // @Description Get the ticker value from an market and coin/token
 // @Accept json
 // @Produce json
-// @Tags ticker
+// @Tags Market
 // @Param coin query int true "coin id"
 // @Param token query string false "token id"
 // @Param currency query string false "the currency to show the quote" default(USD)
@@ -87,12 +87,12 @@ func getTickerHandler(storage storage.Market) func(c *gin.Context) {
 	}
 }
 
-// @Summary Get ticker values for a specific markets
+// @Summary Get ticker values for a specific market
 // @Id get_tickers
-// @Description Get the ticker values from many markets and coin/token
+// @Description Get the ticker values from many market and coin/token
 // @Accept json
 // @Produce json
-// @Tags ticker
+// @Tags Market
 // @Param tickers body api.TickerRequest true "Ticker"
 // @Success 200 {object} blockatlas.Tickers
 // @Router /v1/market/ticker [post]
@@ -156,7 +156,7 @@ func getTickersHandler(storage storage.Market) func(c *gin.Context) {
 // @Description Get the charts data from an market and coin/token
 // @Accept json
 // @Produce json
-// @Tags charts
+// @Tags Market
 // @Param coin query int true "Coin ID" default(60)
 // @Param token query string false "Token ID"
 // @Param time_start query int false "Start timestamp" default(1574483028)
@@ -165,7 +165,7 @@ func getTickersHandler(storage storage.Market) func(c *gin.Context) {
 // @Success 200 {object} blockatlas.ChartData
 // @Router /v1/market/charts [get]
 func getChartsHandler() func(c *gin.Context) {
-	var charts = syncmarkets.InitCharts()
+	var charts = market.InitCharts()
 	return func(c *gin.Context) {
 		coinQuery := c.Query("coin")
 		coinId, err := strconv.Atoi(coinQuery)
@@ -202,7 +202,7 @@ func getChartsHandler() func(c *gin.Context) {
 // @Description Get the charts coin info data from an market and coin/contract
 // @Accept json
 // @Produce json
-// @Tags charts
+// @Tags Market
 // @Param coin query int true "Coin ID" default(60)
 // @Param token query string false "Token ID"
 // @Param time_start query int false "Start timestamp" default(1574483028)
@@ -210,7 +210,7 @@ func getChartsHandler() func(c *gin.Context) {
 // @Success 200 {object} blockatlas.ChartCoinInfo
 // @Router /v1/market/info [get]
 func getCoinInfoHandler() func(c *gin.Context) {
-	var charts = syncmarkets.InitCharts()
+	var charts = market.InitCharts()
 	return func(c *gin.Context) {
 		coinQuery := c.Query("coin")
 		coinId, err := strconv.Atoi(coinQuery)
diff --git a/api/naming_service.go b/api/naming_service.go
index 44cfdd2..a67506b 100644
--- a/api/naming_service.go
+++ b/api/naming_service.go
@@ -19,7 +19,7 @@ type LookupBatchPage []blockatlas.Resolved
 // @ID lookup
 // @Description Lookup ENS/ZNS to find registered addresses
 // @Produce json
-// @Tags ns
+// @Tags Platform-Naming-Service
 // @Param name query string empty "string name"
 // @Param coin query string 60 "string coin"
 // @Success 200 {object} blockatlas.Resolved
@@ -52,7 +52,7 @@ func MakeLookupRoute(router gin.IRouter) {
 // @ID lookup
 // @Description Lookup ENS/ZNS to find registered addresses for multiple coins
 // @Produce json
-// @Tags ns
+// @Tags Platform-Naming-Service
 // @Param name query string empty "string name"
 // @Param coins query string true "List of coins"
 // @Success 200 {array} blockatlas.Resolved
diff --git a/api/observer.go b/api/observer.go
index 6b59017..4a9fc84 100644
--- a/api/observer.go
+++ b/api/observer.go
@@ -21,7 +21,7 @@ func SetupObserverAPI(router gin.IRouter, db *storage.Storage) {
 // @Description Create a webhook for addresses transactions
 // @Accept json
 // @Produce json
-// @Tags observer,subscriptions
+// @Tags Observer
 // @Param subscriptions body blockatlas.Webhook true "Accounts subscriptions"
 // @Param Authorization header string true "Bearer authorization header" default(Bearer test)
 // @Header 200 {string} Authorization {token}
@@ -53,7 +53,7 @@ func addCall(storage storage.Addresses) func(c *gin.Context) {
 // @Description Delete a webhook for addresses transactions
 // @Accept json
 // @Produce json
-// @Tags observer,subscriptions
+// @Tags Observer
 // @Param subscriptions body blockatlas.Webhook true "Accounts subscriptions"
 // @Param Authorization header string true "Bearer authorization header" default(Bearer test)
 // @Header 200 {string} Authorization {token}
@@ -85,7 +85,7 @@ func deleteCall(storage storage.Addresses) func(c *gin.Context) {
 // @Description Get coin status
 // @Accept json
 // @Produce json
-// @Tags observer,subscriptions
+// @Tags Observer
 // @Param Authorization header string true "Bearer authorization header" default(Bearer test)
 // @Header 200 {string} Authorization {token}
 // @Success 200 {object} blockatlas.CoinStatus
diff --git a/api/stake.go b/api/stake.go
index 9e7c129..a350a6c 100644
--- a/api/stake.go
+++ b/api/stake.go
@@ -16,7 +16,7 @@ import (
 // @Description Get validators from the address
 // @Accept json
 // @Produce json
-// @Tags platform,staking
+// @Tags Platform-Staking
 // @Param coin path string true "the coin name" default(cosmos)
 // @Success 200 {object} blockatlas.DocsResponse
 // @Failure 500 {object} ginutils.ApiError
@@ -45,7 +45,7 @@ func makeStakingValidatorsRoute(router gin.IRouter, api blockatlas.Platform) {
 // @Description Get stake delegations from the address
 // @Accept json
 // @Produce json
-// @Tags platform,staking
+// @Tags Platform-Staking
 // @Param coin path string true "the coin name" default(tron)
 // @Param address path string true "the query address" default(TPJYCz8ppZNyvw7pTwmjajcx4Kk1MmEUhD)
 // @Success 200 {object} blockatlas.DelegationResponse
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index b19a757..983d963 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -11,6 +11,7 @@ pr:
   branches:
     include:
       - master
+      - dev
 
 pool:
   vmImage: 'Ubuntu 16.04'
diff --git a/cmd/api/main.go b/cmd/api/main.go
deleted file mode 100644
index ec1d8ff..0000000
--- a/cmd/api/main.go
+++ /dev/null
@@ -1,125 +0,0 @@
-package main
-
-import (
-	"context"
-	"flag"
-	"github.com/getsentry/sentry-go/gin"
-	"github.com/gin-gonic/gin"
-	"github.com/spf13/viper"
-	"github.com/swaggo/gin-swagger"
-	"github.com/swaggo/gin-swagger/swaggerFiles"
-	"github.com/trustwallet/blockatlas/api"
-	"github.com/trustwallet/blockatlas/config"
-	_ "github.com/trustwallet/blockatlas/docs"
-	"github.com/trustwallet/blockatlas/pkg/ginutils"
-	"github.com/trustwallet/blockatlas/pkg/logger"
-	"github.com/trustwallet/blockatlas/platform"
-	"github.com/trustwallet/blockatlas/storage"
-	"net/http"
-	"os"
-	"os/signal"
-	"path/filepath"
-	"syscall"
-	"time"
-)
-
-const (
-	defaultPort       = "8420"
-	defaultConfigPath = "../../config.yml"
-)
-
-var (
-	port, confPath string
-	cache          *storage.Storage
-	sg             gin.HandlerFunc
-)
-
-func init() {
-	sg = sentrygin.New(sentrygin.Options{})
-	cache = storage.New()
-
-	flag.StringVar(&port, "p", defaultPort, "port for api")
-	flag.StringVar(&confPath, "c", defaultConfigPath, "config file for api")
-
-	flag.Parse()
-
-	confPath, err := filepath.Abs(confPath)
-	if err != nil {
-		logger.Fatal(err)
-	}
-
-	config.LoadConfig(confPath)
-	logger.InitLogger()
-	platform.Init()
-
-	host := viper.GetString("storage.redis")
-	err = cache.Init(host)
-	if err != nil {
-		logger.Fatal(err)
-	}
-}
-
-func main() {
-	gin.SetMode(viper.GetString("gin.mode"))
-	engine := gin.New()
-
-	engine.Use(ginutils.CheckReverseProxy, sg)
-	engine.Use(ginutils.CORSMiddleware())
-	engine.OPTIONS("/*path", ginutils.CORSMiddleware())
-
-	engine.GET("swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
-	engine.GET("/", api.GetRoot)
-	engine.GET("/status", func(c *gin.Context) {
-		ginutils.RenderSuccess(c, map[string]interface{}{
-			"status": true,
-		})
-	})
-
-	api.MakeMetricsRoute(engine)
-	api.LoadPlatforms(engine)
-
-	if viper.GetBool("observer.enabled") {
-		logger.Info("Loading observer API")
-		observerAPI := engine.Group("/observer/v1")
-		api.SetupObserverAPI(observerAPI, cache)
-	}
-	if viper.GetBool("market.enabled") {
-		logger.Info("Loading market API")
-		marketAPI := engine.Group("/v1/market")
-		api.SetupMarketAPI(marketAPI, cache)
-	}
-
-	signalForExit := make(chan os.Signal, 1)
-
-	signal.Notify(signalForExit,
-		syscall.SIGHUP,
-		syscall.SIGINT,
-		syscall.SIGTERM,
-		syscall.SIGQUIT)
-
-	srv := &http.Server{
-		Addr:    ":" + port,
-		Handler: engine,
-	}
-
-	go func() {
-		if err := srv.ListenAndServe(); err != nil {
-			logger.Fatal("Application failed", err)
-		}
-	}()
-
-	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
-	defer cancel()
-
-	defer func() {
-		if err := srv.Shutdown(ctx); err != nil {
-			logger.Fatal("Server Shutdown: ", err)
-		}
-	}()
-
-	logger.Info("Running application", logger.Params{"bind": port})
-
-	stop := <-signalForExit
-	logger.Info("Stop signal Received", stop)
-	logger.Info("Waiting for all jobs to stop")
-}
diff --git a/cmd/market_api/main.go b/cmd/market_api/main.go
new file mode 100644
index 0000000..14017cd
--- /dev/null
+++ b/cmd/market_api/main.go
@@ -0,0 +1,51 @@
+package main
+
+import (
+	"github.com/gin-gonic/gin"
+	"github.com/spf13/viper"
+	"github.com/trustwallet/blockatlas/api"
+	_ "github.com/trustwallet/blockatlas/docs"
+	"github.com/trustwallet/blockatlas/internal"
+	"github.com/trustwallet/blockatlas/pkg/ginutils"
+	"github.com/trustwallet/blockatlas/pkg/logger"
+	"github.com/trustwallet/blockatlas/storage"
+)
+
+const (
+	defaultPort       = "8421"
+	defaultConfigPath = "../../config.yml"
+)
+
+var (
+	port, confPath string
+	cache          *storage.Storage
+	sg             *gin.HandlerFunc
+)
+
+func init() {
+	port, confPath, sg, cache = internal.InitAPIWithRedis(defaultPort, defaultConfigPath)
+}
+
+func main() {
+	gin.SetMode(viper.GetString("gin.mode"))
+
+	engine := gin.New()
+	engine.Use(ginutils.CheckReverseProxy, *sg)
+	engine.Use(ginutils.CORSMiddleware())
+	engine.Use(gin.Logger())
+
+	engine.OPTIONS("/*path", ginutils.CORSMiddleware())
+	engine.GET("/", api.GetRoot)
+	engine.GET("/status", func(c *gin.Context) {
+		ginutils.RenderSuccess(c, map[string]interface{}{
+			"status": true,
+		})
+	})
+
+	logger.Info("Loading market API")
+
+	marketAPI := engine.Group("/v1/market")
+
+	api.SetupMarketAPI(marketAPI, cache)
+	internal.SetupGracefulShutdown(port, engine)
+}
diff --git a/cmd/market_observer/main.go b/cmd/market_observer/main.go
new file mode 100644
index 0000000..6474614
--- /dev/null
+++ b/cmd/market_observer/main.go
@@ -0,0 +1,26 @@
+package main
+
+import (
+	"github.com/trustwallet/blockatlas/internal"
+	"github.com/trustwallet/blockatlas/market"
+	"github.com/trustwallet/blockatlas/storage"
+)
+
+const (
+	defaultConfigPath = "../../config.yml"
+)
+
+var (
+	confPath string
+	cache    *storage.Storage
+)
+
+func init() {
+	_, confPath, _, cache = internal.InitAPIWithRedis("", defaultConfigPath)
+}
+
+func main() {
+	market.InitRates(cache)
+	market.InitMarkets(cache)
+	<-make(chan struct{})
+}
diff --git a/cmd/observer_api/main.go b/cmd/observer_api/main.go
new file mode 100644
index 0000000..72e9c67
--- /dev/null
+++ b/cmd/observer_api/main.go
@@ -0,0 +1,51 @@
+package main
+
+import (
+	"github.com/gin-gonic/gin"
+	"github.com/spf13/viper"
+	"github.com/trustwallet/blockatlas/api"
+	_ "github.com/trustwallet/blockatlas/docs"
+	"github.com/trustwallet/blockatlas/internal"
+	"github.com/trustwallet/blockatlas/pkg/ginutils"
+	"github.com/trustwallet/blockatlas/pkg/logger"
+	"github.com/trustwallet/blockatlas/storage"
+)
+
+const (
+	defaultPort       = "8422"
+	defaultConfigPath = "../../config.yml"
+)
+
+var (
+	port, confPath string
+	cache          *storage.Storage
+	sg             *gin.HandlerFunc
+)
+
+func init() {
+	port, confPath, sg, cache = internal.InitAPIWithRedis(defaultPort, defaultConfigPath)
+}
+
+func main() {
+	gin.SetMode(viper.GetString("gin.mode"))
+
+	engine := gin.New()
+	engine.Use(ginutils.CheckReverseProxy, *sg)
+	engine.Use(ginutils.CORSMiddleware())
+	engine.Use(gin.Logger())
+
+	engine.OPTIONS("/*path", ginutils.CORSMiddleware())
+	engine.GET("/", api.GetRoot)
+	engine.GET("/status", func(c *gin.Context) {
+		ginutils.RenderSuccess(c, map[string]interface{}{
+			"status": true,
+		})
+	})
+
+	logger.Info("Loading observer API")
+
+	observerAPI := engine.Group("/observer/v1")
+
+	api.SetupObserverAPI(observerAPI, cache)
+	internal.SetupGracefulShutdown(port, engine)
+}
diff --git a/cmd/platform_api/main.go b/cmd/platform_api/main.go
new file mode 100644
index 0000000..4cb9b79
--- /dev/null
+++ b/cmd/platform_api/main.go
@@ -0,0 +1,48 @@
+package main
+
+import (
+	"github.com/gin-gonic/gin"
+	"github.com/spf13/viper"
+	"github.com/trustwallet/blockatlas/api"
+	_ "github.com/trustwallet/blockatlas/docs"
+	"github.com/trustwallet/blockatlas/internal"
+	"github.com/trustwallet/blockatlas/pkg/ginutils"
+	"github.com/trustwallet/blockatlas/platform"
+)
+
+const (
+	defaultPort       = "8420"
+	defaultConfigPath = "../../config.yml"
+	allPlatforms      = "all"
+)
+
+var (
+	port, confPath, chosenPlatform string
+	sg                             *gin.HandlerFunc
+)
+
+func init() {
+	port, confPath, sg = internal.InitAPI(defaultPort, defaultConfigPath)
+	chosenPlatform = viper.GetString("platform")
+	platform.Init(chosenPlatform)
+}
+
+func main() {
+	gin.SetMode(viper.GetString("gin.mode"))
+	engine := gin.New()
+	engine.Use(ginutils.CheckReverseProxy, *sg)
+	engine.Use(ginutils.CORSMiddleware())
+	engine.Use(gin.Logger())
+
+	engine.OPTIONS("/*path", ginutils.CORSMiddleware())
+	engine.GET("/", api.GetRoot)
+	engine.GET("/status", func(c *gin.Context) {
+		ginutils.RenderSuccess(c, map[string]interface{}{
+			"status": true,
+		})
+	})
+
+	api.LoadPlatforms(engine)
+
+	internal.SetupGracefulShutdown(port, engine)
+}
diff --git a/cmd/observer/main.go b/cmd/platform_observer/main.go
similarity index 79%
rename from cmd/observer/main.go
rename to cmd/platform_observer/main.go
index 2680373..1466238 100644
--- a/cmd/observer/main.go
+++ b/cmd/platform_observer/main.go
@@ -2,14 +2,12 @@ package main
 
 import (
 	"context"
-	"flag"
 	"github.com/spf13/viper"
-	"github.com/trustwallet/blockatlas/config"
+	"github.com/trustwallet/blockatlas/internal"
 	"github.com/trustwallet/blockatlas/observer"
 	"github.com/trustwallet/blockatlas/pkg/logger"
 	"github.com/trustwallet/blockatlas/platform"
 	"github.com/trustwallet/blockatlas/storage"
-	"path/filepath"
 	"sync"
 	"time"
 )
@@ -24,25 +22,9 @@ var (
 )
 
 func init() {
-	cache = storage.New()
+	_, confPath, _, cache = internal.InitAPIWithRedis("", defaultConfigPath)
 
-	flag.StringVar(&confPath, "c", defaultConfigPath, "config file for observer")
-	flag.Parse()
-
-	confPath, err := filepath.Abs(confPath)
-	if err != nil {
-		logger.Fatal(err)
-	}
-
-	config.LoadConfig(confPath)
-	logger.InitLogger()
-	platform.Init()
-
-	host := viper.GetString("storage.redis")
-	err = cache.Init(host)
-	if err != nil {
-		logger.Fatal(err)
-	}
+	platform.Init(viper.GetString("platform"))
 }
 
 func main() {
diff --git a/cmd/swagger_api/main.go b/cmd/swagger_api/main.go
new file mode 100644
index 0000000..644ee8d
--- /dev/null
+++ b/cmd/swagger_api/main.go
@@ -0,0 +1,47 @@
+package main
+
+import (
+	"github.com/gin-gonic/gin"
+	"github.com/spf13/viper"
+	ginSwagger "github.com/swaggo/gin-swagger"
+	"github.com/swaggo/gin-swagger/swaggerFiles"
+	"github.com/trustwallet/blockatlas/api"
+	_ "github.com/trustwallet/blockatlas/docs"
+	"github.com/trustwallet/blockatlas/internal"
+	"github.com/trustwallet/blockatlas/pkg/ginutils"
+)
+
+const (
+	defaultPort       = "8423"
+	defaultConfigPath = "../../config.yml"
+	allPlatforms      = "all"
+)
+
+var (
+	port, confPath string
+	sg             *gin.HandlerFunc
+)
+
+func init() {
+	port, confPath, sg = internal.InitAPI(defaultPort, defaultConfigPath)
+}
+
+func main() {
+	gin.SetMode(viper.GetString("gin.mode"))
+
+	engine := gin.New()
+	engine.Use(ginutils.CheckReverseProxy, *sg)
+	engine.Use(ginutils.CORSMiddleware())
+
+	engine.OPTIONS("/*path", ginutils.CORSMiddleware())
+	engine.GET("/", api.GetRoot)
+	engine.GET("/status", func(c *gin.Context) {
+		ginutils.RenderSuccess(c, map[string]interface{}{
+			"status": true,
+		})
+	})
+
+	engine.GET("swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
+
+	internal.SetupGracefulShutdown(port, engine)
+}
diff --git a/cmd/syncmarkets/main.go b/cmd/syncmarkets/main.go
deleted file mode 100644
index 8c36941..0000000
--- a/cmd/syncmarkets/main.go
+++ /dev/null
@@ -1,47 +0,0 @@
-package main
-
-import (
-	"flag"
-	"github.com/spf13/viper"
-	"github.com/trustwallet/blockatlas/config"
-	"github.com/trustwallet/blockatlas/pkg/logger"
-	"github.com/trustwallet/blockatlas/storage"
-	"github.com/trustwallet/blockatlas/syncmarkets"
-	"path/filepath"
-)
-
-const (
-	defaultConfigPath = "../../config.yml"
-)
-
-var (
-	confPath string
-	cache    *storage.Storage
-)
-
-func init() {
-	cache = storage.New()
-
-	flag.StringVar(&confPath, "c", defaultConfigPath, "config file for observer")
-	flag.Parse()
-
-	confPath, err := filepath.Abs(confPath)
-	if err != nil {
-		logger.Fatal(err)
-	}
-
-	config.LoadConfig(confPath)
-	logger.InitLogger()
-
-	host := viper.GetString("storage.redis")
-	err = cache.Init(host)
-	if err != nil {
-		logger.Fatal(err)
-	}
-}
-
-func main() {
-	syncmarkets.InitRates(cache)
-	syncmarkets.InitMarkets(cache)
-	<-make(chan struct{})
-}
diff --git a/config.yml b/config.yml
index 0309dfa..f840aa1 100644
--- a/config.yml
+++ b/config.yml
@@ -6,6 +6,7 @@ gin:
   # If set, HTTP Forwarded headers will be respected
   reverse_proxy: false
 
+platform: all
 #metrics:
 #  api_token: xxxxxx
 
@@ -19,7 +20,7 @@ observer:
   # TODO : Add description
   auth: test
   # Redis Subscription Database
-  redis: redis://localhost:6379
+  redis: redis://redis:6379
   # Smallest possible block polling interval
   min_poll: 250ms
   # Don't request blocks older than this
@@ -53,7 +54,7 @@ market:
     api: https://api.coingecko.com/api
 
 storage:
-  redis: redis://localhost:6379
+  redis: redis://redis:6379
 
 # [BNB] Binance DEX: https://wallet.binance.org
 #       Binance Chain: https://explorer.binance.org
diff --git a/docker-compose.yml b/docker-compose.yml
index 775604f..a18c8d6 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -1,36 +1,64 @@
 version: '3.7'
 services:
-  api:
-    container_name: api
+  market_api:
+    container_name: market_api
     build:
       context: .
       args:
-      - SERVICE=api
+        - SERVICE=market_api
     ports:
-    - 8420:8420
+    - 8421:8421
     links:
-    - redis
+      - redis
 
-  observer:
-    container_name: observer
+  market_observer:
+    container_name: market_observer
     build:
       context: .
       args:
-       - SERVICE=observer
+      - SERVICE=market_observer
     links:
     - redis
 
-  syncmarkets:
-    container_name: syncmarkets
+  observer_api:
+    container_name: observer_api
     build:
       context: .
       args:
-        - SERVICE=syncmarkets
+        - SERVICE=observer_api
+    ports:
+      - 8422:8422
     links:
-    - redis
+      - redis
+
+  platform_api:
+    container_name: platform_api
+    build:
+      context: .
+      args:
+        - SERVICE=platform_api
+    ports:
+    - 8420:8420
+
+  swagger_api:
+    container_name: swagger_api
+    build:
+      context: .
+      args:
+        - SERVICE=swagger_api
+    ports:
+      - 8423:8423
+
+  platform_observer:
+    build:
+      context: .
+      args:
+        - SERVICE=platform_observer
+    links:
+      - redis
 
   redis:
-    container_name: redis
+    container_name: redis1
     image: neojt/mredis
     ports:
     - 6379:6379
diff --git a/docs/docs.go b/docs/docs.go
index c36afb8..b3327af 100644
--- a/docs/docs.go
+++ b/docs/docs.go
@@ -1,6 +1,6 @@
 // GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
 // This file was generated by swaggo/swag at
-// 2020-02-12 08:02:39.698276 -0300 -03 m=+0.093560371
+// 2020-02-13 21:02:22.715378 -0700 MST m=+0.143781826
 
 package docs
 
@@ -26,16 +26,6 @@ var doc = `{
     "host": "{{.Host}}",
     "basePath": "{{.BasePath}}",
     "paths": {
-        "/metrics": {
-            "get": {
-                "description": "Get application metrics",
-                "tags": [
-                    "metrics"
-                ],
-                "summary": "Get Metrics",
-                "operationId": "metrics"
-            }
-        },
         "/ns/lookup": {
             "get": {
                 "description": "Lookup ENS/ZNS to find registered addresses",
@@ -43,7 +33,7 @@ var doc = `{
                     "application/json"
                 ],
                 "tags": [
-                    "ns"
+                    "Platform-Naming-Service"
                 ],
                 "summary": "Lookup .eth / .zil addresses",
                 "operationId": "lookup",
@@ -87,8 +77,7 @@ var doc = `{
                     "application/json"
                 ],
                 "tags": [
-                    "observer",
-                    "subscriptions"
+                    "Observer"
                 ],
                 "summary": "Get coin status",
                 "operationId": "coin_status",
@@ -122,8 +111,7 @@ var doc = `{
                     "application/json"
                 ],
                 "tags": [
-                    "observer",
-                    "subscriptions"
+                    "Observer"
                 ],
                 "summary": "Create a webhook",
                 "operationId": "create_webhook",
@@ -164,8 +152,7 @@ var doc = `{
                     "application/json"
                 ],
                 "tags": [
-                    "observer",
-                    "subscriptions"
+                    "Observer"
                 ],
                 "summary": "Delete a webhook",
                 "operationId": "delete_webhook",
@@ -208,7 +195,7 @@ var doc = `{
                     "application/json"
                 ],
                 "tags": [
-                    "charts"
+                    "Market"
                 ],
                 "summary": "Get charts data for a specific coin",
                 "operationId": "get_charts_data",
@@ -269,7 +256,7 @@ var doc = `{
                     "application/json"
                 ],
                 "tags": [
-                    "charts"
+                    "Market"
                 ],
                 "summary": "Get charts coin info data for a specific coin",
                 "operationId": "get_charts_coin_info",
@@ -323,7 +310,7 @@ var doc = `{
                     "application/json"
                 ],
                 "tags": [
-                    "ticker"
+                    "Market"
                 ],
                 "summary": "Get ticker value for a specific market",
                 "operationId": "get_ticker",
@@ -359,7 +346,7 @@ var doc = `{
                 }
             },
             "post": {
-                "description": "Get the ticker values from many markets and coin/token",
+                "description": "Get the ticker values from many market and coin/token",
                 "consumes": [
                     "application/json"
                 ],
@@ -367,9 +354,9 @@ var doc = `{
                     "application/json"
                 ],
                 "tags": [
-                    "ticker"
+                    "Market"
                 ],
-                "summary": "Get ticker values for a specific markets",
+                "summary": "Get ticker values for a specific market",
                 "operationId": "get_tickers",
                 "parameters": [
                     {
@@ -402,8 +389,7 @@ var doc = `{
                     "application/json"
                 ],
                 "tags": [
-                    "platform",
-                    "tx"
+                    "Platform-Transactions"
                 ],
                 "summary": "Get xpub transactions",
                 "operationId": "xpub",
@@ -445,8 +431,7 @@ var doc = `{
                     "application/json"
                 ],
                 "tags": [
-                    "platform",
-                    "tx"
+                    "Platform-Transactions"
                 ],
                 "summary": "Get Transactions",
                 "operationId": "tx_v1",
@@ -488,7 +473,7 @@ var doc = `{
                     "application/json"
                 ],
                 "tags": [
-                    "Collectibles"
+                    "Platform-Collections"
                 ],
                 "summary": "Get list of collections from a specific coin and addresses",
                 "operationId": "collection_categories_v2",
@@ -521,7 +506,7 @@ var doc = `{
                     "application/json"
                 ],
                 "tags": [
-                    "ns"
+                    "Platform-Naming-Service"
                 ],
                 "summary": "Lookup .eth / .zil addresses",
                 "operationId": "lookup",
@@ -569,8 +554,7 @@ var doc = `{
                     "application/json"
                 ],
                 "tags": [
-                    "platform",
-                    "staking"
+                    "Platform-Staking"
                 ],
                 "summary": "Get Multiple Stake Delegations",
                 "operationId": "batch_delegations",
@@ -605,8 +589,7 @@ var doc = `{
                     "application/json"
                 ],
                 "tags": [
-                    "platform",
-                    "staking"
+                    "Platform-Staking"
                 ],
                 "summary": "Get Multiple Stake Delegations",
                 "operationId": "batch_delegations",
@@ -617,7 +600,7 @@ var doc = `{
                         "in": "body",
                         "required": true,
                         "schema": {
-                            "$ref": "#/definitions/api.CoinsRequest"
+                            "$ref": "#/definitions/api.AddressesRequest"
                         }
                     }
                 ],
@@ -641,8 +624,7 @@ var doc = `{
                     "application/json"
                 ],
                 "tags": [
-                    "platform",
-                    "collection"
+                    "Platform-Collections"
                 ],
                 "summary": "Get Collections",
                 "operationId": "collections_v2",
@@ -690,8 +672,7 @@ var doc = `{
                     "application/json"
                 ],
                 "tags": [
-                    "platform",
-                    "collection"
+                    "Platform-Collections"
                 ],
                 "summary": "Get Collection",
                 "operationId": "collection_v2",
@@ -747,8 +728,7 @@ var doc = `{
                     "application/json"
                 ],
                 "tags": [
-                    "platform",
-                    "staking"
+                    "Platform-Staking"
                 ],
                 "summary": "Get Stake Delegations",
                 "operationId": "delegations",
@@ -796,8 +776,7 @@ var doc = `{
                     "application/json"
                 ],
                 "tags": [
-                    "platform",
-                    "staking"
+                    "Platform-Staking"
                 ],
                 "summary": "Get Validators",
                 "operationId": "validators",
@@ -837,8 +816,7 @@ var doc = `{
                     "application/json"
                 ],
                 "tags": [
-                    "platform",
-                    "token"
+                    "Platform-Transactions"
                 ],
                 "summary": "Get Tokens",
                 "operationId": "tokens",
@@ -886,8 +864,7 @@ var doc = `{
                     "application/json"
                 ],
                 "tags": [
-                    "platform",
-                    "tx"
+                    "Platform-Transactions"
                 ],
                 "summary": "Get Transactions",
                 "operationId": "tx_v2",
@@ -935,7 +912,7 @@ var doc = `{
                     "application/json"
                 ],
                 "tags": [
-                    "Collectibles"
+                    "Platform-Collections"
                 ],
                 "summary": "Get list of collections from a specific coin and addresses",
                 "operationId": "collection_categories_v3",
@@ -971,8 +948,7 @@ var doc = `{
                     "application/json"
                 ],
                 "tags": [
-                    "platform",
-                    "collection"
+                    "Platform-Collections"
                 ],
                 "summary": "Get Collections",
                 "operationId": "collections_v3",
@@ -1020,8 +996,7 @@ var doc = `{
                     "application/json"
                 ],
                 "tags": [
-                    "platform",
-                    "collection"
+                    "Platform-Collections"
                 ],
                 "summary": "Get Collection",
                 "operationId": "collection_v3",
@@ -1100,20 +1075,6 @@ var doc = `{
                 }
             }
         },
-        "api.CoinBatchRequest": {
-            "type": "object",
-            "properties": {
-                "coin": {
-                    "type": "integer"
-                }
-            }
-        },
-        "api.CoinsRequest": {
-            "type": "array",
-            "items": {
-                "$ref": "#/definitions/api.CoinBatchRequest"
-            }
-        },
         "api.TickerRequest": {
             "type": "object",
             "properties": {
diff --git a/docs/swagger.json b/docs/swagger.json
index 24e1d6a..dbdec9b 100644
--- a/docs/swagger.json
+++ b/docs/swagger.json
@@ -5,16 +5,6 @@
         "license": {}
     },
     "paths": {
-        "/metrics": {
-            "get": {
-                "description": "Get application metrics",
-                "tags": [
-                    "metrics"
-                ],
-                "summary": "Get Metrics",
-                "operationId": "metrics"
-            }
-        },
         "/ns/lookup": {
             "get": {
                 "description": "Lookup ENS/ZNS to find registered addresses",
@@ -22,7 +12,7 @@
                     "application/json"
                 ],
                 "tags": [
-                    "ns"
+                    "Platform-Naming-Service"
                 ],
                 "summary": "Lookup .eth / .zil addresses",
                 "operationId": "lookup",
@@ -66,8 +56,7 @@
                     "application/json"
                 ],
                 "tags": [
-                    "observer",
-                    "subscriptions"
+                    "Observer"
                 ],
                 "summary": "Get coin status",
                 "operationId": "coin_status",
@@ -101,8 +90,7 @@
                     "application/json"
                 ],
                 "tags": [
-                    "observer",
-                    "subscriptions"
+                    "Observer"
                 ],
                 "summary": "Create a webhook",
                 "operationId": "create_webhook",
@@ -143,8 +131,7 @@
                     "application/json"
                 ],
                 "tags": [
-                    "observer",
-                    "subscriptions"
+                    "Observer"
                 ],
                 "summary": "Delete a webhook",
                 "operationId": "delete_webhook",
@@ -187,7 +174,7 @@
                     "application/json"
                 ],
                 "tags": [
-                    "charts"
+                    "Market"
                 ],
                 "summary": "Get charts data for a specific coin",
                 "operationId": "get_charts_data",
@@ -248,7 +235,7 @@
                     "application/json"
                 ],
                 "tags": [
-                    "charts"
+                    "Market"
                 ],
                 "summary": "Get charts coin info data for a specific coin",
                 "operationId": "get_charts_coin_info",
@@ -302,7 +289,7 @@
                     "application/json"
                 ],
                 "tags": [
-                    "ticker"
+                    "Market"
                 ],
                 "summary": "Get ticker value for a specific market",
                 "operationId": "get_ticker",
@@ -338,7 +325,7 @@
                 }
             },
             "post": {
-                "description": "Get the ticker values from many markets and coin/token",
+                "description": "Get the ticker values from many market and coin/token",
                 "consumes": [
                     "application/json"
                 ],
@@ -346,9 +333,9 @@
                     "application/json"
                 ],
                 "tags": [
-                    "ticker"
+                    "Market"
                 ],
-                "summary": "Get ticker values for a specific markets",
+                "summary": "Get ticker values for a specific market",
                 "operationId": "get_tickers",
                 "parameters": [
                     {
@@ -381,8 +368,7 @@
                     "application/json"
                 ],
                 "tags": [
-                    "platform",
-                    "tx"
+                    "Platform-Transactions"
                 ],
                 "summary": "Get xpub transactions",
                 "operationId": "xpub",
@@ -424,8 +410,7 @@
                     "application/json"
                 ],
                 "tags": [
-                    "platform",
-                    "tx"
+                    "Platform-Transactions"
                 ],
                 "summary": "Get Transactions",
                 "operationId": "tx_v1",
@@ -467,7 +452,7 @@
                     "application/json"
                 ],
                 "tags": [
-                    "Collectibles"
+                    "Platform-Collections"
                 ],
                 "summary": "Get list of collections from a specific coin and addresses",
                 "operationId": "collection_categories_v2",
@@ -500,7 +485,7 @@
                     "application/json"
                 ],
                 "tags": [
-                    "ns"
+                    "Platform-Naming-Service"
                 ],
                 "summary": "Lookup .eth / .zil addresses",
                 "operationId": "lookup",
@@ -548,8 +533,7 @@
                     "application/json"
                 ],
                 "tags": [
-                    "platform",
-                    "staking"
+                    "Platform-Staking"
                 ],
                 "summary": "Get Multiple Stake Delegations",
                 "operationId": "batch_delegations",
@@ -584,8 +568,7 @@
                     "application/json"
                 ],
                 "tags": [
-                    "platform",
-                    "staking"
+                    "Platform-Staking"
                 ],
                 "summary": "Get Multiple Stake Delegations",
                 "operationId": "batch_delegations",
@@ -596,7 +579,7 @@
                         "in": "body",
                         "required": true,
                         "schema": {
-                            "$ref": "#/definitions/api.CoinsRequest"
+                            "$ref": "#/definitions/api.AddressesRequest"
                         }
                     }
                 ],
@@ -620,8 +603,7 @@
                     "application/json"
                 ],
                 "tags": [
-                    "platform",
-                    "collection"
+                    "Platform-Collections"
                 ],
                 "summary": "Get Collections",
                 "operationId": "collections_v2",
@@ -669,8 +651,7 @@
                     "application/json"
                 ],
                 "tags": [
-                    "platform",
-                    "collection"
+                    "Platform-Collections"
                 ],
                 "summary": "Get Collection",
                 "operationId": "collection_v2",
@@ -726,8 +707,7 @@
                     "application/json"
                 ],
                 "tags": [
-                    "platform",
-                    "staking"
+                    "Platform-Staking"
                 ],
                 "summary": "Get Stake Delegations",
                 "operationId": "delegations",
@@ -775,8 +755,7 @@
                     "application/json"
                 ],
                 "tags": [
-                    "platform",
-                    "staking"
+                    "Platform-Staking"
                 ],
                 "summary": "Get Validators",
                 "operationId": "validators",
@@ -816,8 +795,7 @@
                     "application/json"
                 ],
                 "tags": [
-                    "platform",
-                    "token"
+                    "Platform-Transactions"
                 ],
                 "summary": "Get Tokens",
                 "operationId": "tokens",
@@ -865,8 +843,7 @@
                     "application/json"
                 ],
                 "tags": [
-                    "platform",
-                    "tx"
+                    "Platform-Transactions"
                 ],
                 "summary": "Get Transactions",
                 "operationId": "tx_v2",
@@ -914,7 +891,7 @@
                     "application/json"
                 ],
                 "tags": [
-                    "Collectibles"
+                    "Platform-Collections"
                 ],
                 "summary": "Get list of collections from a specific coin and addresses",
                 "operationId": "collection_categories_v3",
@@ -950,8 +927,7 @@
                     "application/json"
                 ],
                 "tags": [
-                    "platform",
-                    "collection"
+                    "Platform-Collections"
                 ],
                 "summary": "Get Collections",
                 "operationId": "collections_v3",
@@ -999,8 +975,7 @@
                     "application/json"
                 ],
                 "tags": [
-                    "platform",
-                    "collection"
+                    "Platform-Collections"
                 ],
                 "summary": "Get Collection",
                 "operationId": "collection_v3",
@@ -1079,20 +1054,6 @@
                 }
             }
         },
-        "api.CoinBatchRequest": {
-            "type": "object",
-            "properties": {
-                "coin": {
-                    "type": "integer"
-                }
-            }
-        },
-        "api.CoinsRequest": {
-            "type": "array",
-            "items": {
-                "$ref": "#/definitions/api.CoinBatchRequest"
-            }
-        },
         "api.TickerRequest": {
             "type": "object",
             "properties": {
diff --git a/docs/swagger.yaml b/docs/swagger.yaml
index 93586ae..4c0fb07 100644
--- a/docs/swagger.yaml
+++ b/docs/swagger.yaml
@@ -19,15 +19,6 @@ definitions:
       type:
         type: string
     type: object
-  api.CoinBatchRequest:
-    properties:
-      coin:
-        type: integer
-    type: object
-  api.CoinsRequest:
-    items:
-      $ref: '#/definitions/api.CoinBatchRequest'
-    type: array
   api.TickerRequest:
     properties:
       assets:
@@ -387,13 +378,6 @@ info:
   contact: {}
   license: {}
 paths:
-  /metrics:
-    get:
-      description: Get application metrics
-      operationId: metrics
-      summary: Get Metrics
-      tags:
-      - metrics
   /ns/lookup:
     get:
       description: Lookup ENS/ZNS to find registered addresses
@@ -420,7 +404,7 @@ paths:
             $ref: '#/definitions/ginutils.ApiError'
       summary: Lookup .eth / .zil addresses
       tags:
-      - ns
+      - Platform-Naming-Service
   /observer/v1/status:
     get:
       consumes:
@@ -443,8 +427,7 @@ paths:
             $ref: '#/definitions/blockatlas.CoinStatus'
       summary: Get coin status
       tags:
-      - observer
-      - subscriptions
+      - Observer
   /observer/v1/webhook/register:
     delete:
       consumes:
@@ -473,8 +456,7 @@ paths:
             $ref: '#/definitions/blockatlas.Observer'
       summary: Delete a webhook
       tags:
-      - observer
-      - subscriptions
+      - Observer
     post:
       consumes:
       - application/json
@@ -502,8 +484,7 @@ paths:
             $ref: '#/definitions/blockatlas.Observer'
       summary: Create a webhook
       tags:
-      - observer
-      - subscriptions
+      - Observer
   /v1/{coin}/{address}:
     get:
       consumes:
@@ -532,8 +513,7 @@ paths:
             $ref: '#/definitions/ginutils.ApiError'
       summary: Get Transactions
       tags:
-      - platform
-      - tx
+      - Platform-Transactions
   /v1/{coin}/xpub/{xpub}:
     get:
       consumes:
@@ -562,8 +542,7 @@ paths:
             $ref: '#/definitions/blockatlas.TxPage'
       summary: Get xpub transactions
       tags:
-      - platform
-      - tx
+      - Platform-Transactions
   /v1/market/charts:
     get:
       consumes:
@@ -605,7 +584,7 @@ paths:
             $ref: '#/definitions/blockatlas.ChartData'
       summary: Get charts data for a specific coin
       tags:
-      - charts
+      - Market
   /v1/market/info:
     get:
       consumes:
@@ -642,7 +621,7 @@ paths:
             $ref: '#/definitions/blockatlas.ChartCoinInfo'
       summary: Get charts coin info data for a specific coin
       tags:
-      - charts
+      - Market
   /v1/market/ticker:
     get:
       consumes:
@@ -673,11 +652,11 @@ paths:
             $ref: '#/definitions/blockatlas.Ticker'
       summary: Get ticker value for a specific market
       tags:
-      - ticker
+      - Market
     post:
       consumes:
       - application/json
-      description: Get the ticker values from many markets and coin/token
+      description: Get the ticker values from many market and coin/token
       operationId: get_tickers
       parameters:
       - description: Ticker
@@ -693,9 +672,9 @@ paths:
           description: OK
           schema:
             $ref: '#/definitions/blockatlas.Tickers'
-      summary: Get ticker values for a specific markets
+      summary: Get ticker values for a specific market
       tags:
-      - ticker
+      - Market
   /v2/{coin}/collections/{address}:
     get:
       consumes:
@@ -728,8 +707,7 @@ paths:
             $ref: '#/definitions/ginutils.ApiError'
       summary: Get Collections
       tags:
-      - platform
-      - collection
+      - Platform-Collections
   /v2/{coin}/collections/{owner}/collection/{collection_id}:
     get:
       consumes:
@@ -768,8 +746,7 @@ paths:
             $ref: '#/definitions/ginutils.ApiError'
       summary: Get Collection
       tags:
-      - platform
-      - collection
+      - Platform-Collections
   /v2/{coin}/staking/delegations/{address}:
     get:
       consumes:
@@ -802,8 +779,7 @@ paths:
             $ref: '#/definitions/ginutils.ApiError'
       summary: Get Stake Delegations
       tags:
-      - platform
-      - staking
+      - Platform-Staking
   /v2/{coin}/staking/validators:
     get:
       consumes:
@@ -830,8 +806,7 @@ paths:
             $ref: '#/definitions/ginutils.ApiError'
       summary: Get Validators
       tags:
-      - platform
-      - staking
+      - Platform-Staking
   /v2/{coin}/tokens/{address}:
     get:
       consumes:
@@ -864,8 +839,7 @@ paths:
             $ref: '#/definitions/ginutils.ApiError'
       summary: Get Tokens
       tags:
-      - platform
-      - token
+      - Platform-Transactions
   /v2/{coin}/transactions/{address}:
     get:
       consumes:
@@ -898,8 +872,7 @@ paths:
             $ref: '#/definitions/ginutils.ApiError'
       summary: Get Transactions
       tags:
-      - platform
-      - tx
+      - Platform-Transactions
   /v2/collectibles/categories:
     post:
       consumes:
@@ -923,7 +896,7 @@ paths:
             $ref: '#/definitions/blockatlas.DocsResponse'
       summary: Get list of collections from a specific coin and addresses
       tags:
-      - Collectibles
+      - Platform-Collections
   /v2/ns/lookup:
     get:
       description: Lookup ENS/ZNS to find registered addresses for multiple coins
@@ -953,7 +926,7 @@ paths:
             $ref: '#/definitions/ginutils.ApiError'
       summary: Lookup .eth / .zil addresses
       tags:
-      - ns
+      - Platform-Naming-Service
   /v2/staking/delegations:
     post:
       consumes:
@@ -976,8 +949,7 @@ paths:
             $ref: '#/definitions/blockatlas.DelegationsBatchPage'
       summary: Get Multiple Stake Delegations
       tags:
-      - platform
-      - staking
+      - Platform-Staking
   /v2/staking/list:
     post:
       consumes:
@@ -990,7 +962,7 @@ paths:
         name: delegations
         required: true
         schema:
-          $ref: '#/definitions/api.CoinsRequest'
+          $ref: '#/definitions/api.AddressesRequest'
       produces:
       - application/json
       responses:
@@ -1000,8 +972,7 @@ paths:
             $ref: '#/definitions/blockatlas.DelegationsBatchPage'
       summary: Get Multiple Stake Delegations
       tags:
-      - platform
-      - staking
+      - Platform-Staking
   /v3/{coin}/collections/{address}:
     get:
       consumes:
@@ -1034,8 +1005,7 @@ paths:
             $ref: '#/definitions/ginutils.ApiError'
       summary: Get Collections
       tags:
-      - platform
-      - collection
+      - Platform-Collections
   /v3/{coin}/collections/{owner}/collection/{collection_id}:
     get:
       consumes:
@@ -1074,8 +1044,7 @@ paths:
             $ref: '#/definitions/ginutils.ApiError'
       summary: Get Collection
       tags:
-      - platform
-      - collection
+      - Platform-Collections
   /v3/collectibles/categories:
     post:
       consumes:
@@ -1099,5 +1068,5 @@ paths:
             $ref: '#/definitions/blockatlas.DocsResponse'
       summary: Get list of collections from a specific coin and addresses
       tags:
-      - Collectibles
+      - Platform-Collections
 swagger: "2.0"
diff --git a/go.sum b/go.sum
index 9e56ad9..f5dc222 100644
--- a/go.sum
+++ b/go.sum
@@ -18,12 +18,15 @@ github.com/CloudyKit/fastprinter v0.0.0-20170127035650-74b38d55f37a/go.mod h1:EF
 github.com/CloudyKit/jet v2.1.3-0.20180809161101-62edd43e4f88+incompatible/go.mod h1:HPYO+50pSWkPoj9Q/eq0aRGByCL6ScRlUmiEX5Zgm+w=
 github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY=
 github.com/Joker/jade v1.0.1-0.20190614124447-d475f43051e7/go.mod h1:6E6s8o2AE4KhCrqr6GRJjdC/gNfTdxkIXvuGZZda2VM=
+github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc=
 github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE=
 github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
 github.com/OneOfOne/xxhash v1.2.5/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q=
 github.com/Pantani/httpexpect v2.0.0+incompatible/go.mod h1:+8VdK+EZPV0YorWMMNyakEIYKcDl9OHtde3DdkPqbwQ=
 github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
+github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI=
 github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
+github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
 github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
 github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398/go.mod h1:a1uqRtAwp2Xwc6WNPJEufxJ7fx3npB4UV/JOLmbu5I0=
 github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
@@ -32,6 +35,7 @@ github.com/VictoriaMetrics/fastcache v1.5.3/go.mod h1:+jv9Ckb+za/P1ZRg/sulP5Ni1v
 github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII=
 github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY=
 github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
+github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM=
 github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
 github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
 github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
@@ -47,25 +51,33 @@ github.com/aws/aws-sdk-go v1.25.48/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpi
 github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g=
 github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
 github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
+github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
 github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
 github.com/btcsuite/btcd v0.0.0-20171128150713-2e60448ffcc6/go.mod h1:Dmm/EzmjnCiweXmzRIAiUWCInVmPgjkzgv5k4tVyXiQ=
 github.com/btcsuite/btcd v0.0.0-20190418232430-6867ff32788a/go.mod h1:DrZx5ec/dmnfpw9KyYoQyYo7d0KEvTkk/5M/vbZjAr8=
+github.com/btcsuite/btcd v0.20.1-beta h1:Ik4hyJqN8Jfyv3S4AGBOmyouMsYE3EdYODkMbQjwPGw=
 github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ=
+github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo=
 github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA=
 github.com/btcsuite/btcutil v0.0.0-20190207003914-4c204d697803/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg=
 github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg=
+github.com/btcsuite/btcutil v1.0.1 h1:GKOz8BnRjYrb/JTKgaOk+zh26NWNdSNvdvv0xoAZMSA=
 github.com/btcsuite/btcutil v1.0.1/go.mod h1:j9HUFwoQRsZL3V4n+qG+CUnEGHOarIxfC3Le2Yhbcts=
 github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg=
 github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY=
 github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc=
 github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY=
 github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs=
+github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4=
 github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
 github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s=
 github.com/cespare/cp v1.1.1/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s=
+github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
 github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
 github.com/cespare/xxhash/v2 v2.0.1-0.20190104013014-3767db7a7e18/go.mod h1:HD5P3vAIAh+Y2GAxg0PrPN1P8WkepXGpjbUPDHJqqKM=
+github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
 github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
+github.com/chenjiandongx/ginprom v0.0.0-20191227144730-e11ebf56bc05 h1:2qhpRcnS61pafr2CbHYBr9ZWN7I8txgEOkBUm8Z7NH4=
 github.com/chenjiandongx/ginprom v0.0.0-20191227144730-e11ebf56bc05/go.mod h1:lINNCb1ZH3c0uL/9ApaQ8muR4QILsi0STj8Ojt8ZmwU=
 github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
 github.com/cloudflare/cloudflare-go v0.10.2-0.20190916151808-a80f83b9add9/go.mod h1:1MxXX1Ux4x6mqPmjkUgTP1CdXIBXKX7T+Jk9Gxrmx+U=
@@ -76,13 +88,16 @@ github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8Nz
 github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
 github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
 github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
+github.com/cpacia/bchutil v0.0.0-20181003130114-b126f6a35b6c h1:4e6Zsb6LFd3kadoMiut2zcd3hCb4zywpJnQa8+NV2Cs=
 github.com/cpacia/bchutil v0.0.0-20181003130114-b126f6a35b6c/go.mod h1:k5D13LCXSsMrQyfdW0yGYs4GWUvirqoxHht8qwtqyRY=
 github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
 github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
 github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ=
+github.com/deckarep/golang-set v1.7.1 h1:SCQV0S6gTtp6itiFrTqI+pfmJ4LN85S1YzhDf9rTHJQ=
 github.com/deckarep/golang-set v1.7.1/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ=
 github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd h1:83Wprp6ROGeiHFAP8WJdI2RoxALQYgdllERc3N5N2DM=
 github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
@@ -94,13 +109,16 @@ github.com/docker/docker v1.4.2-0.20180625184442-8e610b2b55bf/go.mod h1:eEKB0N0r
 github.com/docker/docker v1.13.1/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
 github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
 github.com/edsrzf/mmap-go v0.0.0-20160512033002-935e0e8a636c/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
+github.com/edsrzf/mmap-go v1.0.0 h1:CEBF7HpRnUCSJgGUb5h1Gm7e3VkmVDrR8lvWVLtrOFw=
 github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
 github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM=
 github.com/elastic/gosigar v0.8.1-0.20180330100440-37f05ff46ffa/go.mod h1:cdorVVzy1fhmEqmtgqkoE3bYtCfSCkVyjTyCIo22xvs=
+github.com/elastic/gosigar v0.10.4 h1:6jfw75dsoflhBMRdO6QPzQUgLqUYTsQQQRkkcsHsuPo=
 github.com/elastic/gosigar v0.10.4/go.mod h1:cdorVVzy1fhmEqmtgqkoE3bYtCfSCkVyjTyCIo22xvs=
 github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0=
 github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw=
 github.com/ethereum/go-ethereum v1.9.2/go.mod h1:PwpWDrCLZrV+tfrhqqF6kPknbISMHaJv9Ln3kPCZLwY=
+github.com/ethereum/go-ethereum v1.9.10 h1:jooX7tWcscpC7ytufk73t9JMCeJQ7aJF2YmZJQEuvFo=
 github.com/ethereum/go-ethereum v1.9.10/go.mod h1:lXHkVo/MTvsEXfYsmNzelZ8R1e0DTvdk/wMZJIRpaRw=
 github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8=
 github.com/fatih/color v1.3.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
@@ -108,17 +126,22 @@ github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga
 github.com/fjl/memsize v0.0.0-20180418122429-ca190fb6ffbc/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0=
 github.com/fjl/memsize v0.0.0-20180929194037-2a09253e352a/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0=
 github.com/flosch/pongo2 v0.0.0-20190707114632-bbf5a6c351f4/go.mod h1:T9YF2M40nIgbVgp3rreNmTged+9HrbNTIQf1PsaIiTA=
+github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
 github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
 github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc=
+github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqGNY4FhTFhk+o9oFHGINQ/+vhlm8HFzi6znCI=
 github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww=
+github.com/getsentry/sentry-go v0.4.0 h1:WqRI2/7EiALbdG9qGB47c0Aks1tdznG5DZd6GSQ1y/8=
 github.com/getsentry/sentry-go v0.4.0/go.mod h1:xkGcb82SipKQloDNa5b7hTV4VdEyc2bhwd1/UczP52k=
 github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
 github.com/gin-contrib/gzip v0.0.1/go.mod h1:fGBJBCdt6qCZuCAOwWuFhBB4OOq9EFqlo5dEaFhhu5w=
 github.com/gin-contrib/sse v0.0.0-20170109093832-22d885f9ecc7/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s=
 github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s=
+github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
 github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
 github.com/gin-gonic/gin v1.3.0/go.mod h1:7cKuhb5qV2ggCFctp2fJQ+ErvciLZrIeoOSOm6mUr7Y=
 github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/3rZdM=
+github.com/gin-gonic/gin v1.5.0 h1:fi+bqFAx/oLK54somfCtEZs9HeH1LHVoEPUgARpTqyc=
 github.com/gin-gonic/gin v1.5.0/go.mod h1:Nd6IXA8m5kNZdNEHMBd93KT+mdY3+bewLgRvmCsR2Do=
 github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98=
 github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
@@ -130,20 +153,28 @@ github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AE
 github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8=
 github.com/go-openapi/jsonpointer v0.17.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M=
 github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg=
+github.com/go-openapi/jsonpointer v0.19.3 h1:gihV7YNZK1iK6Tgwwsxo2rJbD1GTbdm72325Bq8FI3w=
 github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
 github.com/go-openapi/jsonreference v0.17.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I=
 github.com/go-openapi/jsonreference v0.19.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I=
 github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc=
+github.com/go-openapi/jsonreference v0.19.3 h1:5cxNfTy0UVC3X8JL5ymxzyoUZmo8iZb+jeTWn7tUa8o=
 github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8=
 github.com/go-openapi/spec v0.19.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI=
+github.com/go-openapi/spec v0.19.4 h1:ixzUSnHTd6hCemgtAJgluaTSGYpLNpJY4mA2DIkdOAo=
 github.com/go-openapi/spec v0.19.4/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo=
 github.com/go-openapi/swag v0.17.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg=
 github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
+github.com/go-openapi/swag v0.19.5 h1:lTz6Ys4CmqqCQmZPBlbQENR1/GucA2bzYTE12Pw4tFY=
 github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
+github.com/go-playground/locales v0.12.1 h1:2FITxuFt/xuCNP1Acdhv62OzaCiviiE4kotfhkmOqEc=
 github.com/go-playground/locales v0.12.1/go.mod h1:IUMDtCfWo/w/mtMfIE/IG2K+Ey3ygWanZIBtBW0W2TM=
+github.com/go-playground/universal-translator v0.16.0 h1:X++omBR/4cE2MNg91AoC3rmGrCjJ8eAeUP/K/EKx4DM=
 github.com/go-playground/universal-translator v0.16.0/go.mod h1:1AnU7NaIRDWWzGEKwgtJRd2xk99HeFyHw3yid4rvQIY=
+github.com/go-redis/redis v6.15.6+incompatible h1:H9evprGPLI8+ci7fxQx6WNZHJSb7be8FqJQRhdQZ5Sg=
 github.com/go-redis/redis v6.15.6+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
 github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
+github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
 github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
 github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo=
 github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
@@ -158,8 +189,10 @@ github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfb
 github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
 github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
 github.com/golang/protobuf v1.3.2-0.20190517061210-b285ee9cfc6c/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
 github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
 github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
+github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
 github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
 github.com/gomodule/redigo v1.7.1-0.20190724094224-574c33c3df38/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4=
 github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
@@ -169,11 +202,13 @@ github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
 github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
 github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
+github.com/google/uuid v1.0.0 h1:b4Gk+7WdP/d3HZH8EJsZpvV7EtDOgaZLtnaNGIu1adA=
 github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
 github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
 github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
 github.com/gorilla/websocket v1.4.1-0.20190629185528-ae1634f6a989/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
+github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM=
 github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
 github.com/graph-gophers/graphql-go v0.0.0-20190724201507-010347b5f9e6/go.mod h1:Au3iQ8DvDis8hZ4q2OzRcaKYlAsPt+fYvib5q4nIqu4=
 github.com/graph-gophers/graphql-go v0.0.0-20191115155744-f33e81362277/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc=
@@ -182,12 +217,16 @@ github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgf
 github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
 github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
 github.com/hashicorp/golang-lru v0.0.0-20160813221303-0a025b7e63ad/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
+github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU=
 github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
+github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
 github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
+github.com/hewigovens/go-coincodec v1.0.4 h1:asF02q8WfDwVQjU1O0VZYbOBer0cPJUmTiZKfAgqBYM=
 github.com/hewigovens/go-coincodec v1.0.4/go.mod h1:+LTdzScnu782gMt0J3ZccPY9S2uyrGe0R1LUYGWecfc=
 github.com/howeyc/fsnotify v0.9.0/go.mod h1:41HzSPxBGeFRQKEEwgh49TRw/nKBsYZ2cF1OzPjSJsA=
 github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
 github.com/huin/goupnp v0.0.0-20161224104101-679507af18f3/go.mod h1:MZ2ZmwcBpvOoJ22IJsc7va19ZwoheaBk43rKg12SKag=
+github.com/huin/goupnp v1.0.0 h1:wg75sLpL6DZqwHQN6E1Cfk6mtfzS45z8OV+ic+DtHRo=
 github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7Bnc=
 github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o=
 github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA=
@@ -202,7 +241,9 @@ github.com/jackpal/go-nat-pmp v1.0.1/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+
 github.com/jackpal/go-nat-pmp v1.0.2-0.20160603034137-1fa385a6f458 h1:6OvNmYgJyexcZ3pYbTI9jWx5tHo1Dee/tWbLMfPe2TA=
 github.com/jackpal/go-nat-pmp v1.0.2-0.20160603034137-1fa385a6f458/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc=
 github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
+github.com/jinzhu/gorm v1.9.12 h1:Drgk1clyWT9t9ERbzHza6Mj/8FY/CqMyVzOiHviMo6Q=
 github.com/jinzhu/gorm v1.9.12/go.mod h1:vhTjlKSJUTWNtcbQtrMBFCxy7eXTzeCAzfL5fBZT/Qs=
+github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
 github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
 github.com/jinzhu/now v1.0.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
 github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
@@ -242,9 +283,12 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
 github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
 github.com/labstack/echo/v4 v4.1.11/go.mod h1:i541M3Fj6f76NZtHSj7TXnyM8n2gaodfvfxNnFqi74g=
 github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k=
+github.com/leodido/go-urn v1.1.0 h1:Sm1gr51B1kKyfD2BlRcLSiEkffoG96g6TPv6eRoEiB8=
 github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw=
+github.com/lib/pq v1.1.1 h1:sJZmqHoEaY7f+NPP8pgLB/WxulyR3fewgCM2qaSlBb4=
 github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
 github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
+github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4=
 github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
 github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
 github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
@@ -260,20 +304,25 @@ github.com/mattn/go-isatty v0.0.5-0.20180830101745-3fb116b82035/go.mod h1:M+lRXT
 github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
 github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
 github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
+github.com/mattn/go-isatty v0.0.9 h1:d5US/mDsogSGW37IV293h//ZFaeajb69h+EHFsv2xGg=
 github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
 github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
+github.com/mattn/go-runewidth v0.0.4 h1:2BvfKmzob6Bmd4YsL0zygOqfdFnK7GR4QL06Do4/p7Y=
 github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
 github.com/mattn/go-sqlite3 v2.0.1+incompatible h1:xQ15muvnzGBHpIpdrNi1DA5x0+TcBZzsIDwmw9uTHzw=
 github.com/mattn/go-sqlite3 v2.0.1+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
 github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw=
+github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
 github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
 github.com/mediocregopher/mediocre-go-lib v0.0.0-20181029021733-cb65787f37ed/go.mod h1:dSsfyI2zABAdhcbvkXqgxOxrCsbYeHCPgrZkku60dSg=
 github.com/mediocregopher/radix/v3 v3.3.0/go.mod h1:EmfVyvspXz1uZEyPBMyGK+kjWiKQGvsUt6O3Pj+LDCQ=
 github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc=
+github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 h1:lYpkrQH5ajf0OXOcUbGjvZxxijuBwbbmlSxLiuofa+g=
 github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ=
 github.com/minio/sha256-simd v0.0.0-20190328051042-05b4dd3047e5 h1:l16XLUUJ34wIz+RIvLhSwGvLvKyy+W598b135bJN6mg=
 github.com/minio/sha256-simd v0.0.0-20190328051042-05b4dd3047e5/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U=
 github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
+github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
 github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
 github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
 github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
@@ -282,6 +331,7 @@ github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3Rllmb
 github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
 github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ=
 github.com/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
+github.com/mr-tron/base58 v1.1.3 h1:v+sk57XuaCKGXpWtVBX8YJzO7hMGx4Aajh4TQbdEFdc=
 github.com/mr-tron/base58 v1.1.3/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
 github.com/multiformats/go-multihash v0.0.5 h1:1wxmCvTXAifAepIMyF39vZinRw5sbqjPs/UIi93+uik=
 github.com/multiformats/go-multihash v0.0.5/go.mod h1:lt/HCbqlQwlPBz7lv0sQCdtfcMtlJvakRUn/0Ual8po=
@@ -302,18 +352,24 @@ github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1Cpa
 github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
 github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
 github.com/oschwald/maxminddb-golang v1.3.1/go.mod h1:3jhIUymTJ5VREKyIhWm66LJiQt04F0UCDdodShpjWsY=
+github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
 github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
 github.com/pborman/uuid v0.0.0-20170112150404-1b00554d8222/go.mod h1:VyrYX9gd7irzKovcSS6BIIEwPRkP2Wm2m9ufcdFSJ34=
+github.com/pborman/uuid v1.2.0 h1:J7Q5mO4ysT1dv8hyrUGHb9+ooztCXu1D8MY8DZYsu3g=
 github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
+github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=
 github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
 github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0=
 github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8=
 github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
 github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
 github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
 github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
+github.com/prometheus/client_golang v1.4.0 h1:YVIb/fVcOTMSqtqZWSKnHpSLBxu8DKgxq8z6RuBZwqI=
 github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU=
 github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
 github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
@@ -331,13 +387,17 @@ github.com/prometheus/procfs v0.0.8 h1:+fpWZdT24pJBiqJdAwYBjPSk+5YmQzYNPYzQsdzLk
 github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
 github.com/prometheus/tsdb v0.6.2-0.20190402121629-4f204dcbc150/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
 github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
+github.com/prometheus/tsdb v0.10.0 h1:If5rVCMTp6W2SiRAQFlbpJNgVlgMEd+U2GZckwK38ic=
 github.com/prometheus/tsdb v0.10.0/go.mod h1:oi49uRhEe9dPUTlS3JRZOwJuVi6tmh10QSgwXEyGCt4=
 github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho=
+github.com/rjeczalik/notify v0.9.2 h1:MiTWrPj55mNDHEiIX5YUSKefw/+lCQVoAFmD6oQm5w8=
 github.com/rjeczalik/notify v0.9.2/go.mod h1:aErll2f0sUX9PXZnVNyeiObbmTlk5jnMoCa4QEjJeqM=
 github.com/robertkrimen/otto v0.0.0-20170205013659-6a77b7cbc37d/go.mod h1:xvqspoSXJTIpemEonrMDFq6XzwHYYgToXWj5eRX1OtY=
+github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
 github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
 github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
 github.com/rs/cors v0.0.0-20160617231935-a62a804a8a00/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
+github.com/rs/cors v1.6.0 h1:G9tHG9lebljV9mfp9SNPDL36nCDxmo3zTlAf1YgvzmI=
 github.com/rs/cors v1.6.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
 github.com/rs/xhandler v0.0.0-20160618193221-ed27b6fd6521/go.mod h1:RvLn4FgxWubrpZHtQLnOf6EwhN2hEMusxZOhcW9H3UQ=
 github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
@@ -345,9 +405,11 @@ github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD
 github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
 github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
 github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
+github.com/shopspring/decimal v0.0.0-20200105231215-408a2507e114 h1:Pm6R878vxWWWR+Sa3ppsLce/Zq+JNTs6aVvRu13jv9A=
 github.com/shopspring/decimal v0.0.0-20200105231215-408a2507e114/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
 github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
 github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
+github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
 github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
 github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
 github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
@@ -355,42 +417,58 @@ github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9
 github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
 github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
 github.com/spaolacci/murmur3 v1.0.1-0.20190317074736-539464a789e9/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
+github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
 github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
+github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI=
 github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
 github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
+github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng=
 github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
 github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
+github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk=
 github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
+github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
 github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
 github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
+github.com/spf13/viper v1.6.2 h1:7aKfF+e8/k68gda3LOjo5RxiUqddoFxVq4BKBPrxk5E=
 github.com/spf13/viper v1.6.2/go.mod h1:t3iDnF5Jlj76alVNuyFBk5oUMCvsrkbvZK0WQdfDi5k=
 github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q=
+github.com/status-im/keycard-go v0.0.0-20190424133014-d95853db0f48 h1:ju5UTwk5Odtm4trrY+4Ca4RMj5OyXbmVeDAVad2T0Jw=
 github.com/status-im/keycard-go v0.0.0-20190424133014-d95853db0f48/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q=
+github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570 h1:gIlAHnH1vJb5vwEjIp5kBj/eu99p/bl0Ay2goiPe5xE=
 github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570/go.mod h1:8OR4w3TdeIHIh1g6EMY5p0gVNOovcWC+1vpc7naMuAw=
+github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3 h1:njlZPzLwU639dk2kqnCPPv+wNjq7Xb6EfUxe/oX0/NM=
 github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3/go.mod h1:hpGUWaI9xL8pRQCTXQgocU38Qw1g0Us7n5PxxTwTCYU=
 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
 github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
 github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
 github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
+github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
 github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
 github.com/swaggo/files v0.0.0-20190704085106-630677cd5c14/go.mod h1:gxQT6pBGRuIGunNf/+tSOB5OHvguWi8Tbt82WOkf35E=
+github.com/swaggo/gin-swagger v1.2.0 h1:YskZXEiv51fjOMTsXrOetAjrMDfFaXD79PEoQBOe2W0=
 github.com/swaggo/gin-swagger v1.2.0/go.mod h1:qlH2+W7zXGZkczuL+r2nEBR2JTT+/lX05Nn6vPhc7OI=
 github.com/swaggo/swag v1.5.1/go.mod h1:1Bl9F/ZBpVWh22nY0zmYyASPO1lI/zIwRDrpZU+tv8Y=
+github.com/swaggo/swag v1.6.5 h1:2C+t+xyK6p1sujqncYO/VnMvPZcBJjNdKKyxbOdAW8o=
 github.com/swaggo/swag v1.6.5/go.mod h1:Y7ZLSS0d0DdxhWGVhQdu+Bu1QhaF5k0RD7FKdiAykeY=
 github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
 github.com/syndtr/goleveldb v1.0.1-0.20190923125748-758128399b1d h1:gZZadD8H+fF+n9CmNhYL1Y0dJB+kLOmKd7FbPJLeGHs=
 github.com/syndtr/goleveldb v1.0.1-0.20190923125748-758128399b1d/go.mod h1:9OrXJhf154huy1nPWmuSrkgjPUtUNhA+Zmy+6AESzuA=
 github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
 github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs=
+github.com/tyler-smith/go-bip39 v1.0.2 h1:+t3w+KwLXO6154GNJY+qUtIxLTmFjfUmpguQT1OlOT8=
 github.com/tyler-smith/go-bip39 v1.0.2/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs=
 github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
 github.com/ugorji/go v1.1.5-pre/go.mod h1:FwP/aQVg39TXzItUBMwnWp9T9gPQnXw4Poh4/oBQZ/0=
+github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo=
 github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
 github.com/ugorji/go/codec v0.0.0-20181022190402-e5e69e061d4f/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
 github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
 github.com/ugorji/go/codec v1.1.5-pre/go.mod h1:tULtS6Gy1AE1yCENaw4Vb//HLH5njI2tfCQDUqRd8fI=
+github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs=
 github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
 github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
 github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
@@ -401,10 +479,14 @@ github.com/valyala/fasthttp v1.6.0/go.mod h1:FstJa9V+Pj9vQ7OJie2qMHdwemEDaDiSdBn
 github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
 github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio=
 github.com/wealdtech/go-ens/v3 v3.1.0/go.mod h1:P2OEBvgkhXLrPzPN+eR5z2/wFIGwHyijTDvpuC1xLlo=
+github.com/wealdtech/go-ens/v3 v3.2.0 h1:bshYk63BUJaIriX3UoAcYKh1tVI85kI1Xbg3jAnM/NM=
 github.com/wealdtech/go-ens/v3 v3.2.0/go.mod h1:P2OEBvgkhXLrPzPN+eR5z2/wFIGwHyijTDvpuC1xLlo=
+github.com/wealdtech/go-multicodec v1.2.0 h1:9AHSxcSE9F9r6ZvQLAO0EXCdM08QfYohaXmW3k6sSh4=
 github.com/wealdtech/go-multicodec v1.2.0/go.mod h1:aedGMaTeYkIqi/KCPre1ho5rTb3hGpu/snBOS3GQLw4=
+github.com/wealdtech/go-slip44 v1.0.0 h1:g0Wi5EufdD/ULZ4hcZKQ3TGlA6FZhGTCkmVzYmf+7Is=
 github.com/wealdtech/go-slip44 v1.0.0/go.mod h1://S3V9M6iN1cCflLXMjJYciRPakCDubG9YpWVyW1AvM=
 github.com/wealdtech/go-string2eth v1.0.0/go.mod h1:UZA/snEybGcD6n+Pl+yoDjmexlEJ6dtoS9myfM83Ol4=
+github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208 h1:1cngl9mPEoITZG8s8cVcUy5CeIBYhEESkOB7m6Gmkrk=
 github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208/go.mod h1:IotVbo4F+mw0EzQ08zFqg7pK3FebNXpaMsRy2RT+Ees=
 github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c=
 github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
@@ -431,6 +513,7 @@ golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8U
 golang.org/x/crypto v0.0.0-20191112222119-e1110fd1c708/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 golang.org/x/crypto v0.0.0-20191205180655-e7c4368fe9dd/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20200128174031-69ecbb4d6d5d h1:9FCpayM9Egr1baVnV1SX0H87m+XB0B8S0hAMi99X/3U=
 golang.org/x/crypto v0.0.0-20200128174031-69ecbb4d6d5d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
 golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
@@ -450,6 +533,7 @@ golang.org/x/net v0.0.0-20190611141213-3f473d35a33a/go.mod h1:z5CRVTTTmAJ677TzLL
 golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297 h1:k7pJ2yAPLPgbskkFdhRCsA77k2fySZ1zf2zCjvQCiIM=
 golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -477,6 +561,7 @@ golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20200122134326-e047566fdf82 h1:ywK/j/KkyTHcdyYSZNXGjMwgmDSfjglYZ3vStQ/gSCU=
 golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
 golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
 golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -505,7 +590,9 @@ gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8
 gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
 gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE=
 gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y=
+gopkg.in/go-playground/validator.v9 v9.29.1 h1:SvGtYmN60a5CVKTOzMSyfzWDeZRxRuGvRQyEAKbw1xc=
 gopkg.in/go-playground/validator.v9 v9.29.1/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ=
+gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno=
 gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
 gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
 gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c=
@@ -521,6 +608,7 @@ gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
 gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
 honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
diff --git a/internal/init.go b/internal/init.go
new file mode 100644
index 0000000..f2d3c06
--- /dev/null
+++ b/internal/init.go
@@ -0,0 +1,66 @@
+package internal
+
+import (
+	"flag"
+	sentrygin "github.com/getsentry/sentry-go/gin"
+	"github.com/gin-gonic/gin"
+	"github.com/spf13/viper"
+	"github.com/trustwallet/blockatlas/config"
+	"github.com/trustwallet/blockatlas/pkg/logger"
+	"github.com/trustwallet/blockatlas/storage"
+	"path/filepath"
+)
+
+func InitAPI(defaultPort, defaultConfigPath string) (string, string, *gin.HandlerFunc) {
+	var (
+		port, confPath string
+		sg             gin.HandlerFunc
+	)
+
+	sg = sentrygin.New(sentrygin.Options{})
+
+	flag.StringVar(&port, "p", defaultPort, "port for api")
+	flag.StringVar(&confPath, "c", defaultConfigPath, "config file for api")
+	flag.Parse()
+
+	confPath, err := filepath.Abs(confPath)
+	if err != nil {
+		logger.Fatal(err)
+	}
+
+	config.LoadConfig(confPath)
+	logger.InitLogger()
+
+	return port, confPath, &sg
+}
+
+func InitAPIWithRedis(defaultPort, defaultConfigPath string) (string, string, *gin.HandlerFunc, *storage.Storage) {
+	var (
+		port, confPath string
+		cache          *storage.Storage
+		sg             gin.HandlerFunc
+	)
+
+	cache = storage.New()
+	sg = sentrygin.New(sentrygin.Options{})
+
+	flag.StringVar(&port, "p", defaultPort, "port for api")
+	flag.StringVar(&confPath, "c", defaultConfigPath, "config file for api")
+	flag.Parse()
+
+	confPath, err := filepath.Abs(confPath)
+	if err != nil {
+		logger.Fatal(err)
+	}
+
+	config.LoadConfig(confPath)
+	logger.InitLogger()
+
+	host := viper.GetString("storage.redis")
+	err = cache.Init(host)
+	if err != nil {
+		logger.Fatal(err)
+	}
+
+	return port, confPath, &sg, cache
+}
diff --git a/internal/shutdown.go b/internal/shutdown.go
new file mode 100644
index 0000000..37f9586
--- /dev/null
+++ b/internal/shutdown.go
@@ -0,0 +1,45 @@
+package internal
+
+import (
+	"context"
+	"github.com/gin-gonic/gin"
+	"github.com/trustwallet/blockatlas/pkg/logger"
+	"net/http"
+	"os"
+	"os/signal"
+	"syscall"
+	"time"
+)
+
+func SetupGracefulShutdown(port string, engine *gin.Engine) {
+	server := &http.Server{
+		Addr:    ":" + port,
+		Handler: engine,
+	}
+	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
+
+	defer cancel()
+	defer func() {
+		if err := server.Shutdown(ctx); err != nil {
+			logger.Fatal("Server Shutdown: ", err)
+		}
+	}()
+
+	signalForExit := make(chan os.Signal, 1)
+	signal.Notify(signalForExit,
+		syscall.SIGHUP,
+		syscall.SIGINT,
+		syscall.SIGTERM,
+		syscall.SIGQUIT)
+
+	go func() {
+		if err := server.ListenAndServe(); err != nil {
+			logger.Fatal("Application failed", err)
+		}
+	}()
+	logger.Info("Running application", logger.Params{"bind": port})
+
+	stop := <-signalForExit
+	logger.Info("Stop signal Received", stop)
+	logger.Info("Waiting for all jobs to stop")
+}
diff --git a/syncmarkets/chart/chart.go b/market/chart/chart.go
similarity index 100%
rename from syncmarkets/chart/chart.go
rename to market/chart/chart.go
diff --git a/syncmarkets/chart/cmc/cmc.go b/market/chart/cmc/cmc.go
similarity index 96%
rename from syncmarkets/chart/cmc/cmc.go
rename to market/chart/cmc/cmc.go
index be07067..e949463 100644
--- a/syncmarkets/chart/cmc/cmc.go
+++ b/market/chart/cmc/cmc.go
@@ -1,10 +1,10 @@
 package cmc
 
 import (
+	"github.com/trustwallet/blockatlas/market/chart"
+	"github.com/trustwallet/blockatlas/market/clients/cmc"
 	"github.com/trustwallet/blockatlas/pkg/blockatlas"
 	"github.com/trustwallet/blockatlas/pkg/errors"
-	"github.com/trustwallet/blockatlas/syncmarkets/chart"
-	"github.com/trustwallet/blockatlas/syncmarkets/clients/cmc"
 	"time"
 )
 
diff --git a/syncmarkets/chart/coingecko/coingecko.go b/market/chart/coingecko/coingecko.go
similarity index 95%
rename from syncmarkets/chart/coingecko/coingecko.go
rename to market/chart/coingecko/coingecko.go
index 937261d..cad5d4d 100644
--- a/syncmarkets/chart/coingecko/coingecko.go
+++ b/market/chart/coingecko/coingecko.go
@@ -2,10 +2,10 @@ package coingecko
 
 import (
 	"github.com/trustwallet/blockatlas/coin"
+	"github.com/trustwallet/blockatlas/market/chart"
+	"github.com/trustwallet/blockatlas/market/clients/coingecko"
 	"github.com/trustwallet/blockatlas/pkg/blockatlas"
 	"github.com/trustwallet/blockatlas/pkg/errors"
-	"github.com/trustwallet/blockatlas/syncmarkets/chart"
-	"github.com/trustwallet/blockatlas/syncmarkets/clients/coingecko"
 	"time"
 )
 
diff --git a/syncmarkets/chart/provider.go b/market/chart/provider.go
similarity index 100%
rename from syncmarkets/chart/provider.go
rename to market/chart/provider.go
diff --git a/syncmarkets/charts.go b/market/charts.go
similarity index 91%
rename from syncmarkets/charts.go
rename to market/charts.go
index 121e18e..cab0408 100644
--- a/syncmarkets/charts.go
+++ b/market/charts.go
@@ -1,13 +1,13 @@
-package syncmarkets
+package market
 
 import (
 	"github.com/spf13/viper"
+	"github.com/trustwallet/blockatlas/market/chart"
+	"github.com/trustwallet/blockatlas/market/chart/cmc"
+	"github.com/trustwallet/blockatlas/market/chart/coingecko"
 	"github.com/trustwallet/blockatlas/pkg/blockatlas"
 	"github.com/trustwallet/blockatlas/pkg/errors"
 	"github.com/trustwallet/blockatlas/pkg/numbers"
-	"github.com/trustwallet/blockatlas/syncmarkets/chart"
-	"github.com/trustwallet/blockatlas/syncmarkets/chart/cmc"
-	"github.com/trustwallet/blockatlas/syncmarkets/chart/coingecko"
 	"math"
 	"sort"
 )
diff --git a/syncmarkets/clients/cmc/cache.go b/market/clients/cmc/cache.go
similarity index 100%
rename from syncmarkets/clients/cmc/cache.go
rename to market/clients/cmc/cache.go
diff --git a/syncmarkets/clients/cmc/cache_test.go b/market/clients/cmc/cache_test.go
similarity index 100%
rename from syncmarkets/clients/cmc/cache_test.go
rename to market/clients/cmc/cache_test.go
diff --git a/syncmarkets/clients/cmc/client.go b/market/clients/cmc/client.go
similarity index 100%
rename from syncmarkets/clients/cmc/client.go
rename to market/clients/cmc/client.go
diff --git a/syncmarkets/clients/cmc/models.go b/market/clients/cmc/models.go
similarity index 100%
rename from syncmarkets/clients/cmc/models.go
rename to market/clients/cmc/models.go
diff --git a/syncmarkets/clients/cmc/webclient.go b/market/clients/cmc/webclient.go
similarity index 100%
rename from syncmarkets/clients/cmc/webclient.go
rename to market/clients/cmc/webclient.go
diff --git a/syncmarkets/clients/cmc/widgetclient.go b/market/clients/cmc/widgetclient.go
similarity index 100%
rename from syncmarkets/clients/cmc/widgetclient.go
rename to market/clients/cmc/widgetclient.go
diff --git a/syncmarkets/clients/coingecko/cache.go b/market/clients/coingecko/cache.go
similarity index 100%
rename from syncmarkets/clients/coingecko/cache.go
rename to market/clients/coingecko/cache.go
diff --git a/syncmarkets/clients/coingecko/cache_test.go b/market/clients/coingecko/cache_test.go
similarity index 100%
rename from syncmarkets/clients/coingecko/cache_test.go
rename to market/clients/coingecko/cache_test.go
diff --git a/syncmarkets/clients/coingecko/client.go b/market/clients/coingecko/client.go
similarity index 97%
rename from syncmarkets/clients/coingecko/client.go
rename to market/clients/coingecko/client.go
index d8774fc..5d71bee 100644
--- a/syncmarkets/clients/coingecko/client.go
+++ b/market/clients/coingecko/client.go
@@ -48,7 +48,7 @@ func (c *Client) FetchLatestRates(coins GeckoCoins, currency string) (prices Coi
 			}
 
 			var cp CoinPrices
-			err := c.Get(&cp, "v3/coins/markets", values)
+			err := c.Get(&cp, "v3/coins/market", values)
 			if err != nil {
 				logger.Error(err)
 				return
diff --git a/syncmarkets/clients/coingecko/client_test.go b/market/clients/coingecko/client_test.go
similarity index 100%
rename from syncmarkets/clients/coingecko/client_test.go
rename to market/clients/coingecko/client_test.go
diff --git a/syncmarkets/clients/coingecko/models.go b/market/clients/coingecko/models.go
similarity index 100%
rename from syncmarkets/clients/coingecko/models.go
rename to market/clients/coingecko/models.go
diff --git a/syncmarkets/clients/compound/client.go b/market/clients/compound/client.go
similarity index 100%
rename from syncmarkets/clients/compound/client.go
rename to market/clients/compound/client.go
diff --git a/syncmarkets/clients/compound/models.go b/market/clients/compound/models.go
similarity index 100%
rename from syncmarkets/clients/compound/models.go
rename to market/clients/compound/models.go
diff --git a/syncmarkets/market.go b/market/market.go
similarity index 83%
rename from syncmarkets/market.go
rename to market/market.go
index 8343e56..7e00db2 100644
--- a/syncmarkets/market.go
+++ b/market/market.go
@@ -1,16 +1,16 @@
-package syncmarkets
+package market
 
 import (
 	"github.com/robfig/cron/v3"
 	"github.com/spf13/viper"
+	"github.com/trustwallet/blockatlas/market/market"
+	"github.com/trustwallet/blockatlas/market/market/cmc"
+	"github.com/trustwallet/blockatlas/market/market/coingecko"
+	"github.com/trustwallet/blockatlas/market/market/compound"
+	"github.com/trustwallet/blockatlas/market/market/dex"
 	"github.com/trustwallet/blockatlas/pkg/errors"
 	"github.com/trustwallet/blockatlas/pkg/logger"
 	"github.com/trustwallet/blockatlas/storage"
-	"github.com/trustwallet/blockatlas/syncmarkets/market"
-	"github.com/trustwallet/blockatlas/syncmarkets/market/cmc"
-	"github.com/trustwallet/blockatlas/syncmarkets/market/coingecko"
-	"github.com/trustwallet/blockatlas/syncmarkets/market/compound"
-	"github.com/trustwallet/blockatlas/syncmarkets/market/dex"
 )
 
 var marketProviders market.Providers
diff --git a/syncmarkets/market/cmc/cmc.go b/market/market/cmc/cmc.go
similarity index 95%
rename from syncmarkets/market/cmc/cmc.go
rename to market/market/cmc/cmc.go
index 67ae4b5..214c447 100644
--- a/syncmarkets/market/cmc/cmc.go
+++ b/market/market/cmc/cmc.go
@@ -1,9 +1,9 @@
 package cmc
 
 import (
+	"github.com/trustwallet/blockatlas/market/clients/cmc"
+	"github.com/trustwallet/blockatlas/market/market"
 	"github.com/trustwallet/blockatlas/pkg/blockatlas"
-	"github.com/trustwallet/blockatlas/syncmarkets/clients/cmc"
-	"github.com/trustwallet/blockatlas/syncmarkets/market"
 )
 
 const (
diff --git a/syncmarkets/market/coingecko/coingecko.go b/market/market/coingecko/coingecko.go
similarity index 94%
rename from syncmarkets/market/coingecko/coingecko.go
rename to market/market/coingecko/coingecko.go
index 0097e1f..6729505 100644
--- a/syncmarkets/market/coingecko/coingecko.go
+++ b/market/market/coingecko/coingecko.go
@@ -1,9 +1,9 @@
 package coingecko
 
 import (
+	"github.com/trustwallet/blockatlas/market/clients/coingecko"
+	"github.com/trustwallet/blockatlas/market/market"
 	"github.com/trustwallet/blockatlas/pkg/blockatlas"
-	"github.com/trustwallet/blockatlas/syncmarkets/clients/coingecko"
-	"github.com/trustwallet/blockatlas/syncmarkets/market"
 	"strings"
 )
 
diff --git a/syncmarkets/market/compound/compound.go b/market/market/compound/compound.go
similarity index 91%
rename from syncmarkets/market/compound/compound.go
rename to market/market/compound/compound.go
index 7a19736..379fa63 100644
--- a/syncmarkets/market/compound/compound.go
+++ b/market/market/compound/compound.go
@@ -2,9 +2,9 @@ package compound
 
 import (
 	"github.com/trustwallet/blockatlas/coin"
+	c "github.com/trustwallet/blockatlas/market/clients/compound"
+	"github.com/trustwallet/blockatlas/market/market"
 	"github.com/trustwallet/blockatlas/pkg/blockatlas"
-	c "github.com/trustwallet/blockatlas/syncmarkets/clients/compound"
-	"github.com/trustwallet/blockatlas/syncmarkets/market"
 	"time"
 )
 
diff --git a/syncmarkets/market/dex/dex.go b/market/market/dex/dex.go
similarity index 97%
rename from syncmarkets/market/dex/dex.go
rename to market/market/dex/dex.go
index 284e706..7b1fc3e 100644
--- a/syncmarkets/market/dex/dex.go
+++ b/market/market/dex/dex.go
@@ -2,9 +2,9 @@ package dex
 
 import (
 	"github.com/trustwallet/blockatlas/coin"
+	"github.com/trustwallet/blockatlas/market/market"
 	"github.com/trustwallet/blockatlas/pkg/blockatlas"
 	"github.com/trustwallet/blockatlas/pkg/errors"
-	"github.com/trustwallet/blockatlas/syncmarkets/market"
 	"math/big"
 	"net/url"
 	"strconv"
diff --git a/syncmarkets/market/dex/dex_test.go b/market/market/dex/dex_test.go
similarity index 100%
rename from syncmarkets/market/dex/dex_test.go
rename to market/market/dex/dex_test.go
diff --git a/syncmarkets/market/dex/models.go b/market/market/dex/models.go
similarity index 100%
rename from syncmarkets/market/dex/models.go
rename to market/market/dex/models.go
diff --git a/syncmarkets/market/market.go b/market/market/market.go
similarity index 100%
rename from syncmarkets/market/market.go
rename to market/market/market.go
diff --git a/syncmarkets/market/provider.go b/market/market/provider.go
similarity index 100%
rename from syncmarkets/market/provider.go
rename to market/market/provider.go
diff --git a/syncmarkets/rate/cmc/cmc.go b/market/rate/cmc/cmc.go
similarity index 90%
rename from syncmarkets/rate/cmc/cmc.go
rename to market/rate/cmc/cmc.go
index fdb480a..7f53f2b 100644
--- a/syncmarkets/rate/cmc/cmc.go
+++ b/market/rate/cmc/cmc.go
@@ -1,9 +1,9 @@
 package cmc
 
 import (
+	"github.com/trustwallet/blockatlas/market/clients/cmc"
+	"github.com/trustwallet/blockatlas/market/rate"
 	"github.com/trustwallet/blockatlas/pkg/blockatlas"
-	"github.com/trustwallet/blockatlas/syncmarkets/clients/cmc"
-	"github.com/trustwallet/blockatlas/syncmarkets/rate"
 	"math/big"
 )
 
diff --git a/syncmarkets/rate/coingecko/coingecko.go b/market/rate/coingecko/coingecko.go
similarity index 89%
rename from syncmarkets/rate/coingecko/coingecko.go
rename to market/rate/coingecko/coingecko.go
index 6628367..25cb8f8 100644
--- a/syncmarkets/rate/coingecko/coingecko.go
+++ b/market/rate/coingecko/coingecko.go
@@ -1,9 +1,9 @@
 package coingecko
 
 import (
+	"github.com/trustwallet/blockatlas/market/clients/coingecko"
+	"github.com/trustwallet/blockatlas/market/rate"
 	"github.com/trustwallet/blockatlas/pkg/blockatlas"
-	"github.com/trustwallet/blockatlas/syncmarkets/clients/coingecko"
-	"github.com/trustwallet/blockatlas/syncmarkets/rate"
 	"strings"
 )
 
diff --git a/syncmarkets/rate/compound/compound.go b/market/rate/compound/compound.go
similarity index 88%
rename from syncmarkets/rate/compound/compound.go
rename to market/rate/compound/compound.go
index 5f80293..a641ea8 100644
--- a/syncmarkets/rate/compound/compound.go
+++ b/market/rate/compound/compound.go
@@ -1,9 +1,9 @@
 package compound
 
 import (
+	c "github.com/trustwallet/blockatlas/market/clients/compound"
+	"github.com/trustwallet/blockatlas/market/rate"
 	"github.com/trustwallet/blockatlas/pkg/blockatlas"
-	c "github.com/trustwallet/blockatlas/syncmarkets/clients/compound"
-	"github.com/trustwallet/blockatlas/syncmarkets/rate"
 	"strings"
 	"time"
 )
diff --git a/syncmarkets/rate/fixer/fixer.go b/market/rate/fixer/fixer.go
similarity index 94%
rename from syncmarkets/rate/fixer/fixer.go
rename to market/rate/fixer/fixer.go
index e5d7359..34a2587 100644
--- a/syncmarkets/rate/fixer/fixer.go
+++ b/market/rate/fixer/fixer.go
@@ -1,8 +1,8 @@
 package fixer
 
 import (
+	"github.com/trustwallet/blockatlas/market/rate"
 	"github.com/trustwallet/blockatlas/pkg/blockatlas"
-	"github.com/trustwallet/blockatlas/syncmarkets/rate"
 	"net/url"
 )
 
diff --git a/syncmarkets/rate/fixer/fixer_test.go b/market/rate/fixer/fixer_test.go
similarity index 100%
rename from syncmarkets/rate/fixer/fixer_test.go
rename to market/rate/fixer/fixer_test.go
diff --git a/syncmarkets/rate/fixer/models.go b/market/rate/fixer/models.go
similarity index 100%
rename from syncmarkets/rate/fixer/models.go
rename to market/rate/fixer/models.go
diff --git a/syncmarkets/rate/provider.go b/market/rate/provider.go
similarity index 100%
rename from syncmarkets/rate/provider.go
rename to market/rate/provider.go
diff --git a/syncmarkets/rate/rate.go b/market/rate/rate.go
similarity index 100%
rename from syncmarkets/rate/rate.go
rename to market/rate/rate.go
diff --git a/syncmarkets/rates.go b/market/rates.go
similarity index 82%
rename from syncmarkets/rates.go
rename to market/rates.go
index ae49bc4..d2b361e 100644
--- a/syncmarkets/rates.go
+++ b/market/rates.go
@@ -1,16 +1,16 @@
-package syncmarkets
+package market
 
 import (
 	"github.com/robfig/cron/v3"
 	"github.com/spf13/viper"
+	"github.com/trustwallet/blockatlas/market/rate"
+	"github.com/trustwallet/blockatlas/market/rate/cmc"
+	"github.com/trustwallet/blockatlas/market/rate/coingecko"
+	"github.com/trustwallet/blockatlas/market/rate/compound"
+	"github.com/trustwallet/blockatlas/market/rate/fixer"
 	"github.com/trustwallet/blockatlas/pkg/errors"
 	"github.com/trustwallet/blockatlas/pkg/logger"
 	"github.com/trustwallet/blockatlas/storage"
-	"github.com/trustwallet/blockatlas/syncmarkets/rate"
-	"github.com/trustwallet/blockatlas/syncmarkets/rate/cmc"
-	"github.com/trustwallet/blockatlas/syncmarkets/rate/coingecko"
-	"github.com/trustwallet/blockatlas/syncmarkets/rate/compound"
-	"github.com/trustwallet/blockatlas/syncmarkets/rate/fixer"
 )
 
 var rateProviders rate.Providers
diff --git a/syncmarkets/worker.go b/market/worker.go
similarity index 93%
rename from syncmarkets/worker.go
rename to market/worker.go
index 23ed506..d14545e 100644
--- a/syncmarkets/worker.go
+++ b/market/worker.go
@@ -1,14 +1,14 @@
-package syncmarkets
+package market
 
 import (
 	"fmt"
 	"github.com/cenkalti/backoff"
 	"github.com/robfig/cron/v3"
+	"github.com/trustwallet/blockatlas/market/market"
+	"github.com/trustwallet/blockatlas/market/rate"
 	"github.com/trustwallet/blockatlas/pkg/errors"
 	"github.com/trustwallet/blockatlas/pkg/logger"
 	"github.com/trustwallet/blockatlas/storage"
-	"github.com/trustwallet/blockatlas/syncmarkets/market"
-	"github.com/trustwallet/blockatlas/syncmarkets/rate"
 	"time"
 )
 
diff --git a/platform/bitcoin/api.go b/platform/bitcoin/api.go
index 92e10d5..1167783 100644
--- a/platform/bitcoin/api.go
+++ b/platform/bitcoin/api.go
@@ -36,7 +36,7 @@ func (p *Platform) ConfigKey() string {
 // @Description Get transactions from xpub address
 // @Accept json
 // @Produce json
-// @Tags platform,tx
+// @Tags Platform-Transactions
 // @Param coin path string true "the coin name" default(bitcoin)
 // @Param xpub path string true "the xpub address" default(zpub6ruK9k6YGm8BRHWvTiQcrEPnFkuRDJhR7mPYzV2LDvjpLa5CuGgrhCYVZjMGcLcFqv9b2WvsFtY2Gb3xq8NVq8qhk9veozrA2W9QaWtihrC)
 // @Success 200 {object} blockatlas.TxPage
diff --git a/platform/registry.go b/platform/registry.go
index 2fc42a5..35a5165 100644
--- a/platform/registry.go
+++ b/platform/registry.go
@@ -2,12 +2,11 @@ package platform
 
 import (
 	"fmt"
-	"github.com/trustwallet/blockatlas/platform/cosmos"
-	"github.com/trustwallet/blockatlas/platform/polkadot"
-
 	"github.com/spf13/viper"
 	"github.com/trustwallet/blockatlas/pkg/blockatlas"
 	"github.com/trustwallet/blockatlas/pkg/logger"
+	"github.com/trustwallet/blockatlas/platform/cosmos"
+	"github.com/trustwallet/blockatlas/platform/polkadot"
 
 	"github.com/trustwallet/blockatlas/coin"
 	"github.com/trustwallet/blockatlas/platform/aeternity"
@@ -34,74 +33,187 @@ import (
 	"github.com/trustwallet/blockatlas/platform/zilliqa"
 )
 
-var platformList = []blockatlas.Platform{
-	&binance.Platform{},
-	&nimiq.Platform{},
-	&ripple.Platform{},
-	&stellar.Platform{CoinIndex: coin.XLM},
-	&stellar.Platform{CoinIndex: coin.KIN},
-	&ethereum.Platform{CoinIndex: coin.ETH},
-	&ethereum.Platform{CoinIndex: coin.ETC},
-	&ethereum.Platform{CoinIndex: coin.POA},
-	&ethereum.Platform{CoinIndex: coin.CLO},
-	&ethereum.Platform{CoinIndex: coin.GO},
-	&ethereum.Platform{CoinIndex: coin.WAN},
-	&ethereum.Platform{CoinIndex: coin.TOMO},
-	&ethereum.Platform{CoinIndex: coin.TT},
-	&cosmos.Platform{CoinIndex: coin.ATOM},
-	&cosmos.Platform{CoinIndex: coin.KAVA},
-	&tezos.Platform{},
-	&aion.Platform{},
-	&icon.Platform{},
-	&iotex.Platform{},
-	&ontology.Platform{},
-	&theta.Platform{},
-	&tron.Platform{},
-	&vechain.Platform{},
-	&zilliqa.Platform{},
-	&waves.Platform{},
-	&aeternity.Platform{},
-	&bitcoin.Platform{CoinIndex: coin.BTC},
-	&bitcoin.Platform{CoinIndex: coin.LTC},
-	&bitcoin.Platform{CoinIndex: coin.BCH},
-	&bitcoin.Platform{CoinIndex: coin.DASH},
-	&bitcoin.Platform{CoinIndex: coin.DOGE},
-	&bitcoin.Platform{CoinIndex: coin.ZEC},
-	&bitcoin.Platform{CoinIndex: coin.XZC},
-	&bitcoin.Platform{CoinIndex: coin.VIA},
-	&bitcoin.Platform{CoinIndex: coin.RVN},
-	&bitcoin.Platform{CoinIndex: coin.QTUM},
-	&bitcoin.Platform{CoinIndex: coin.GRS},
-	&bitcoin.Platform{CoinIndex: coin.ZEL},
-	&bitcoin.Platform{CoinIndex: coin.DCR},
-	&bitcoin.Platform{CoinIndex: coin.DGB},
-	&nebulas.Platform{},
-	&fio.Platform{},
-	&algorand.Platform{},
-	&nano.Platform{},
-	&harmony.Platform{},
-	&polkadot.Platform{CoinIndex: coin.KSM},
-}
+var (
+	allPlatformsList = []blockatlas.Platform{
+		&binance.Platform{},
+		&nimiq.Platform{},
+		&ripple.Platform{},
+		&stellar.Platform{CoinIndex: coin.XLM},
+		&stellar.Platform{CoinIndex: coin.KIN},
+		&ethereum.Platform{CoinIndex: coin.ETH},
+		&ethereum.Platform{CoinIndex: coin.ETC},
+		&ethereum.Platform{CoinIndex: coin.POA},
+		&ethereum.Platform{CoinIndex: coin.CLO},
+		&ethereum.Platform{CoinIndex: coin.GO},
+		&ethereum.Platform{CoinIndex: coin.WAN},
+		&ethereum.Platform{CoinIndex: coin.TOMO},
+		&ethereum.Platform{CoinIndex: coin.TT},
+		&cosmos.Platform{CoinIndex: coin.ATOM},
+		&cosmos.Platform{CoinIndex: coin.KAVA},
+		&tezos.Platform{},
+		&aion.Platform{},
+		&icon.Platform{},
+		&iotex.Platform{},
+		&ontology.Platform{},
+		&theta.Platform{},
+		&tron.Platform{},
+		&vechain.Platform{},
+		&zilliqa.Platform{},
+		&waves.Platform{},
+		&aeternity.Platform{},
+		&bitcoin.Platform{CoinIndex: coin.BTC},
+		&bitcoin.Platform{CoinIndex: coin.LTC},
+		&bitcoin.Platform{CoinIndex: coin.BCH},
+		&bitcoin.Platform{CoinIndex: coin.DASH},
+		&bitcoin.Platform{CoinIndex: coin.DOGE},
+		&bitcoin.Platform{CoinIndex: coin.ZEC},
+		&bitcoin.Platform{CoinIndex: coin.XZC},
+		&bitcoin.Platform{CoinIndex: coin.VIA},
+		&bitcoin.Platform{CoinIndex: coin.RVN},
+		&bitcoin.Platform{CoinIndex: coin.QTUM},
+		&bitcoin.Platform{CoinIndex: coin.GRS},
+		&bitcoin.Platform{CoinIndex: coin.ZEL},
+		&bitcoin.Platform{CoinIndex: coin.DCR},
+		&bitcoin.Platform{CoinIndex: coin.DGB},
+		&nebulas.Platform{},
+		&fio.Platform{},
+		&algorand.Platform{},
+		&nano.Platform{},
+		&harmony.Platform{},
+		&polkadot.Platform{CoinIndex: coin.KSM},
+	}
+
+	// Platforms contains all registered platforms by handle
+	Platforms map[string]blockatlas.Platform
 
-// Platforms contains all registered platforms by handle
-var Platforms map[string]blockatlas.Platform
+	// BlockAPIs contain platforms with block services
+	BlockAPIs map[string]blockatlas.BlockAPI
 
-// BlockAPIs contain platforms with block services
-var BlockAPIs map[string]blockatlas.BlockAPI
+	// StakeAPIs contain platforms with staking services
+	StakeAPIs map[string]blockatlas.StakeAPI
 
-// StakeAPIs contain platforms with staking services
-var StakeAPIs map[string]blockatlas.StakeAPI
+	// CustomAPIs contain platforms with custom HTTP services
+	CustomAPIs map[string]blockatlas.CustomAPI
 
-// CustomAPIs contain platforms with custom HTTP services
-var CustomAPIs map[string]blockatlas.CustomAPI
+	// NamingAPIs contain platforms which support naming services
+	NamingAPIs map[uint64]blockatlas.NamingServiceAPI
 
-// NamingAPIs contain platforms which support naming services
-var NamingAPIs map[uint64]blockatlas.NamingServiceAPI
+	// CollectionAPIs contain platforms which collections services
+	CollectionAPIs map[uint]blockatlas.CollectionAPI
+)
+
+func getPlatform(handle string) blockatlas.Platform {
+	switch handle {
+	case coin.Binance().Handle:
+		return &binance.Platform{}
+	case coin.Nimiq().Handle:
+		return &nimiq.Platform{}
+	case coin.Ripple().Handle:
+		return &ripple.Platform{}
+	case coin.Stellar().Handle:
+		return &stellar.Platform{CoinIndex: coin.XLM}
+	case coin.Kin().Handle:
+		return &stellar.Platform{CoinIndex: coin.KIN}
+	case coin.Ethereum().Handle:
+		return &ethereum.Platform{CoinIndex: coin.ETH}
+	case coin.Classic().Handle:
+		return &ethereum.Platform{CoinIndex: coin.ETC}
+	case coin.Poa().Handle:
+		return &ethereum.Platform{CoinIndex: coin.POA}
+	case coin.Callisto().Handle:
+		return &ethereum.Platform{CoinIndex: coin.CLO}
+	case coin.Gochain().Handle:
+		return &ethereum.Platform{CoinIndex: coin.GO}
+	case coin.Wanchain().Handle:
+		return &ethereum.Platform{CoinIndex: coin.WAN}
+	case coin.Tomochain().Handle:
+		return &ethereum.Platform{CoinIndex: coin.TOMO}
+	case coin.Thundertoken().Handle:
+		return &ethereum.Platform{CoinIndex: coin.TT}
+	case coin.Cosmos().Handle:
+		return &cosmos.Platform{CoinIndex: coin.ATOM}
+	case coin.Kava().Handle:
+		return &cosmos.Platform{CoinIndex: coin.KAVA}
+	case coin.Tezos().Handle:
+		return &tezos.Platform{}
+	case coin.Aion().Handle:
+		return &aion.Platform{}
+	case coin.Icon().Handle:
+		return &icon.Platform{}
+	case coin.Iotex().Handle:
+		return &iotex.Platform{}
+	case coin.Ontology().Handle:
+		return &ontology.Platform{}
+	case coin.Theta().Handle:
+		return &theta.Platform{}
+	case coin.Tron().Handle:
+		return &tron.Platform{}
+	case coin.Vechain().Handle:
+		return &vechain.Platform{}
+	case coin.Zilliqa().Handle:
+		return &zilliqa.Platform{}
+	case coin.Waves().Handle:
+		return &waves.Platform{}
+	case coin.Aeternity().Handle:
+		return &aeternity.Platform{}
+	case coin.Bitcoin().Handle:
+		return &bitcoin.Platform{CoinIndex: coin.BTC}
+	case coin.Litecoin().Handle:
+		return &bitcoin.Platform{CoinIndex: coin.LTC}
+	case coin.Bitcoincash().Handle:
+		return &bitcoin.Platform{CoinIndex: coin.BCH}
+	case coin.Dash().Handle:
+		return &bitcoin.Platform{CoinIndex: coin.DASH}
+	case coin.Doge().Handle:
+		return &bitcoin.Platform{CoinIndex: coin.DOGE}
+	case coin.Zcash().Handle:
+		return &bitcoin.Platform{CoinIndex: coin.ZEC}
+	case coin.Zcoin().Handle:
+		return &bitcoin.Platform{CoinIndex: coin.XZC}
+	case coin.Viacoin().Handle:
+		return &bitcoin.Platform{CoinIndex: coin.VIA}
+	case coin.Ravencoin().Handle:
+		return &bitcoin.Platform{CoinIndex: coin.RVN}
+	case coin.Qtum().Handle:
+		return &bitcoin.Platform{CoinIndex: coin.QTUM}
+	case coin.Groestlcoin().Handle:
+		return &bitcoin.Platform{CoinIndex: coin.GRS}
+	case coin.Zelcash().Handle:
+		return &bitcoin.Platform{CoinIndex: coin.ZEL}
+	case coin.Decred().Handle:
+		return &bitcoin.Platform{CoinIndex: coin.DCR}
+	case coin.Digibyte().Handle:
+		return &bitcoin.Platform{CoinIndex: coin.DGB}
+	case coin.Nebulas().Handle:
+		return &nebulas.Platform{}
+	case coin.Fio().Handle:
+		return &fio.Platform{}
+	case coin.Algorand().Handle:
+		return &algorand.Platform{}
+	case coin.Nano().Handle:
+		return &nano.Platform{}
+	case coin.Harmony().Handle:
+		return &harmony.Platform{}
+	case coin.Kusama().Handle:
+		return &polkadot.Platform{CoinIndex: coin.KSM}
+	default:
+		return nil
+	}
+}
+
+func getActivePlatforms(handle string) []blockatlas.Platform {
+	logger.Info("Loaded with: ", logger.Params{"handle": handle})
+
+	platform := getPlatform(handle)
+	if platform != nil {
+		return []blockatlas.Platform{platform}
+	}
+	return allPlatformsList
+}
 
-// CollectionAPIs contain platforms which collections services
-var CollectionAPIs map[uint]blockatlas.CollectionAPI
+func Init(platformHandle string) {
+	platformList := getActivePlatforms(platformHandle)
 
-func Init() {
 	Platforms = make(map[string]blockatlas.Platform)
 	BlockAPIs = make(map[string]blockatlas.BlockAPI)
 	StakeAPIs = make(map[string]blockatlas.StakeAPI)
diff --git a/run_docker_compose.sh b/run_docker_compose.sh
new file mode 100755
index 0000000..c58b5a4
--- /dev/null
+++ b/run_docker_compose.sh
@@ -0,0 +1,58 @@
+#!/bin/bash
+
+# https://github.com/jasperes/bash-yaml
+
+parse_yaml() {
+    local yaml_file=$1
+    local prefix=$2
+    local s
+    local w
+    local fs 
+
+    s='[[:space:]]*'
+    w='[a-zA-Z0-9_.-]*'
+    fs="$(echo @|tr @ '\034')"
+
+    (
+        sed -e '/- [^\“]'"[^\']"'.*: /s|\([ ]*\)- \([[:space:]]*\)|\1-\'$'\n''  \1\2|g' |
+
+        sed -ne '/^--/s|--||g; s|\"|\\\"|g; s/[[:space:]]*$//g;' \
+            -e "/#.*[\"\']/!s| #.*||g; /^#/s|#.*||g;" \
+            -e "s|^\($s\)\($w\)$s:$s\"\(.*\)\"$s\$|\1$fs\2$fs\3|p" \
+            -e "s|^\($s\)\($w\)${s}[:-]$s\(.*\)$s\$|\1$fs\2$fs\3|p" |
+
+        awk -F"$fs" '{
+            indent = length($1)/2;
+            if (length($2) == 0) { conj[indent]="+";} else {conj[indent]="";}
+            vname[indent] = $2;
+            for (i in vname) {if (i > indent) {delete vname[i]}}
+                if (length($3) > 0) {
+                    vn=""; for (i=0; i<indent; i++) {vn=(vn)(vname[i])("_")}
+                    printf("%s%s%s%s=(\"%s\")\n", "'"$prefix"'",vn, $2, conj[indent-1],$3);
+                }
+            }' |
+
+        sed -e 's/_=/+=/g' |
+
+        awk 'BEGIN {
+                FS="=";
+                OFS="="
+            }
+            /(-|\.).*=/ {
+                gsub("-|\\.", "_", $1)
+            }
+            { print }'
+    ) < "$yaml_file"
+}
+
+create_variables() {
+    local yaml_file="$1"
+    local prefix="$2"
+    eval "$(parse_yaml "$yaml_file" "$prefix")"
+}
+
+create_variables coin/coins.yml
+docker-compose start redis market_api market_observer observer_api
+for val in ${_handle[*]}; do
+   docker-compose run -e ATLAS_PLATFORM=$val platform_observer
+done


Test patch:
diff --git a/syncmarkets/chart/cmc/cmc_test.go b/market/chart/cmc/cmc_test.go
similarity index 98%
rename from syncmarkets/chart/cmc/cmc_test.go
rename to market/chart/cmc/cmc_test.go
index 4d58485..e97e047 100644
--- a/syncmarkets/chart/cmc/cmc_test.go
+++ b/market/chart/cmc/cmc_test.go
@@ -2,8 +2,8 @@ package cmc
 
 import (
 	"github.com/stretchr/testify/assert"
+	"github.com/trustwallet/blockatlas/market/clients/cmc"
 	"github.com/trustwallet/blockatlas/pkg/blockatlas"
-	"github.com/trustwallet/blockatlas/syncmarkets/clients/cmc"
 	"reflect"
 	"sort"
 	"testing"
diff --git a/syncmarkets/chart/coingecko/coingecko_test.go b/market/chart/coingecko/coingecko_test.go
similarity index 96%
rename from syncmarkets/chart/coingecko/coingecko_test.go
rename to market/chart/coingecko/coingecko_test.go
index 26f6f4e..f7a845f 100644
--- a/syncmarkets/chart/coingecko/coingecko_test.go
+++ b/market/chart/coingecko/coingecko_test.go
@@ -2,8 +2,8 @@ package coingecko
 
 import (
 	"github.com/stretchr/testify/assert"
+	"github.com/trustwallet/blockatlas/market/clients/coingecko"
 	"github.com/trustwallet/blockatlas/pkg/blockatlas"
-	"github.com/trustwallet/blockatlas/syncmarkets/clients/coingecko"
 	"reflect"
 	"testing"
 	"time"
diff --git a/syncmarkets/charts_test.go b/market/charts_test.go
similarity index 99%
rename from syncmarkets/charts_test.go
rename to market/charts_test.go
index 318969c..f4bdf7a 100644
--- a/syncmarkets/charts_test.go
+++ b/market/charts_test.go
@@ -1,4 +1,4 @@
-package syncmarkets
+package market
 
 import (
 	"github.com/stretchr/testify/assert"
diff --git a/syncmarkets/market/cmc/cmc_test.go b/market/market/cmc/cmc_test.go
similarity index 98%
rename from syncmarkets/market/cmc/cmc_test.go
rename to market/market/cmc/cmc_test.go
index 1d57c68..1e90b19 100644
--- a/syncmarkets/market/cmc/cmc_test.go
+++ b/market/market/cmc/cmc_test.go
@@ -2,8 +2,8 @@ package cmc
 
 import (
 	"github.com/stretchr/testify/assert"
+	"github.com/trustwallet/blockatlas/market/clients/cmc"
 	"github.com/trustwallet/blockatlas/pkg/blockatlas"
-	"github.com/trustwallet/blockatlas/syncmarkets/clients/cmc"
 	"sort"
 	"testing"
 	"time"
diff --git a/syncmarkets/market/coingecko/coingecko_test.go b/market/market/coingecko/coingecko_test.go
similarity index 97%
rename from syncmarkets/market/coingecko/coingecko_test.go
rename to market/market/coingecko/coingecko_test.go
index 55eb6c3..3c3a20c 100644
--- a/syncmarkets/market/coingecko/coingecko_test.go
+++ b/market/market/coingecko/coingecko_test.go
@@ -2,8 +2,8 @@ package coingecko
 
 import (
 	"github.com/stretchr/testify/assert"
+	"github.com/trustwallet/blockatlas/market/clients/coingecko"
 	"github.com/trustwallet/blockatlas/pkg/blockatlas"
-	"github.com/trustwallet/blockatlas/syncmarkets/clients/coingecko"
 	"sort"
 	"testing"
 	"time"
diff --git a/syncmarkets/market/compound/compound_test.go b/market/market/compound/compound_test.go
similarity index 96%
rename from syncmarkets/market/compound/compound_test.go
rename to market/market/compound/compound_test.go
index bffdf29..15bc971 100644
--- a/syncmarkets/market/compound/compound_test.go
+++ b/market/market/compound/compound_test.go
@@ -3,8 +3,8 @@ package compound
 import (
 	"github.com/stretchr/testify/assert"
 	"github.com/trustwallet/blockatlas/coin"
+	"github.com/trustwallet/blockatlas/market/clients/compound"
 	"github.com/trustwallet/blockatlas/pkg/blockatlas"
-	"github.com/trustwallet/blockatlas/syncmarkets/clients/compound"
 	"sort"
 	"testing"
 	"time"
diff --git a/syncmarkets/rate/cmc/cmc_test.go b/market/rate/cmc/cmc_test.go
similarity index 97%
rename from syncmarkets/rate/cmc/cmc_test.go
rename to market/rate/cmc/cmc_test.go
index 4c192a9..b060caa 100644
--- a/syncmarkets/rate/cmc/cmc_test.go
+++ b/market/rate/cmc/cmc_test.go
@@ -2,8 +2,8 @@ package cmc
 
 import (
 	"github.com/stretchr/testify/assert"
+	"github.com/trustwallet/blockatlas/market/clients/cmc"
 	"github.com/trustwallet/blockatlas/pkg/blockatlas"
-	"github.com/trustwallet/blockatlas/syncmarkets/clients/cmc"
 	"math/big"
 	"sort"
 	"testing"
diff --git a/syncmarkets/rate/coingecko/coingecko_test.go b/market/rate/coingecko/coingecko_test.go
similarity index 96%
rename from syncmarkets/rate/coingecko/coingecko_test.go
rename to market/rate/coingecko/coingecko_test.go
index d2174f7..3757e24 100644
--- a/syncmarkets/rate/coingecko/coingecko_test.go
+++ b/market/rate/coingecko/coingecko_test.go
@@ -2,8 +2,8 @@ package coingecko
 
 import (
 	"github.com/stretchr/testify/assert"
+	"github.com/trustwallet/blockatlas/market/clients/coingecko"
 	"github.com/trustwallet/blockatlas/pkg/blockatlas"
-	"github.com/trustwallet/blockatlas/syncmarkets/clients/coingecko"
 	"sort"
 	"testing"
 	"time"
diff --git a/syncmarkets/rate/compound/compound_test.go b/market/rate/compound/compound_test.go
similarity index 96%
rename from syncmarkets/rate/compound/compound_test.go
rename to market/rate/compound/compound_test.go
index cdb1460..430c823 100644
--- a/syncmarkets/rate/compound/compound_test.go
+++ b/market/rate/compound/compound_test.go
@@ -2,8 +2,8 @@ package compound
 
 import (
 	"github.com/stretchr/testify/assert"
+	c "github.com/trustwallet/blockatlas/market/clients/compound"
 	"github.com/trustwallet/blockatlas/pkg/blockatlas"
-	c "github.com/trustwallet/blockatlas/syncmarkets/clients/compound"
 	"sort"
 	"testing"
 	"time"
diff --git a/pkg/tests/functional/functional_test.go b/pkg/tests/functional/functional_test.go
index f93c226..c7126ec 100755
--- a/pkg/tests/functional/functional_test.go
+++ b/pkg/tests/functional/functional_test.go
@@ -30,7 +30,7 @@ func TestApis(t *testing.T) {
 	config.LoadConfig(os.Getenv("TEST_CONFIG"))
 
 	logger.InitLogger()
-	platform.Init()
+	platform.Init(viper.GetString("platform"))
 	cache := storage.New()
 	sg := sentrygin.New(sentrygin.Options{})
 	p := ":8420"
diff --git a/pkg/tests/integration/integration_test.go b/pkg/tests/integration/integration_test.go
index afbca8f..858ccd7 100755
--- a/pkg/tests/integration/integration_test.go
+++ b/pkg/tests/integration/integration_test.go
@@ -3,6 +3,7 @@
 package integration
 
 import (
+	"github.com/spf13/viper"
 	"github.com/trustwallet/blockatlas/config"
 	"github.com/trustwallet/blockatlas/pkg/tests/integration/bitcoin"
 	"github.com/trustwallet/blockatlas/pkg/tests/integration/domains"
@@ -19,7 +20,7 @@ func Test(t *testing.T) {
 	} else {
 		config.LoadConfig(configPath)
 	}
-	platform.Init()
+	platform.Init(viper.GetString("platform"))
 
 	// Add your integration tests here
 	ontology.TestOntology(t)