Repository: trustwallet/blockatlas
Pull request #1275 (2020-11-14 06:08:12)

Add Heroku support

codecov[bot]: # [Codecov](https://codecov.io/gh/trustwallet/blockatlas/pull/1275?src=pr&el=h1) Report
> Merging [#1275](https://codecov.io/gh/trustwallet/blockatlas/pull/1275?src=pr&el=desc) (ccb8d18) into [master](https://codecov.io/gh/trustwallet/blockatlas/commit/66f3acfdc97916256304bee39051673627cbbf5d?el=desc) (66f3acf) will **increase** coverage by `0%`.
> The diff coverage is `100%`.

[![Impacted file tree graph](https://codecov.io/gh/trustwallet/blockatlas/pull/1275/graphs/tree.svg?width=650&height=150&src=pr&token=jnrjoEQAqv)](https://codecov.io/gh/trustwallet/blockatlas/pull/1275?src=pr&el=tree)

```diff
@@          Coverage Diff           @@
##           master   #1275   +/-   ##
======================================
  Coverage      42%     42%           
======================================
  Files         147     147           
  Lines        4589    4593    +4     
======================================
+ Hits         1948    1952    +4     
  Misses       2471    2471           
  Partials      170     170           
```


| [Impacted Files](https://codecov.io/gh/trustwallet/blockatlas/pull/1275?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [pkg/blockatlas/tx.go](https://codecov.io/gh/trustwallet/blockatlas/pull/1275/diff?src=pr&el=tree#diff-cGtnL2Jsb2NrYXRsYXMvdHguZ28=) | `48% <100%> (+<1%)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/trustwallet/blockatlas/pull/1275?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/trustwallet/blockatlas/pull/1275?src=pr&el=footer). Last update [66f3acf...875a4c7](https://codecov.io/gh/trustwallet/blockatlas/pull/1275?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).


Patch:
diff --git a/Procfile b/Procfile
index 891cdb3..8f691ac 100644
--- a/Procfile
+++ b/Procfile
@@ -1,1 +1,3 @@
-web: ATLAS_POSTGRES_READ_URL=$ATLAS_POSTGRES_URL bin/api -c $HOME/config.yml -p $PORT
+web: bin/api -c $HOME/config.yml -p $PORT
+consumer: bin/consumer -c $HOME/config.yml
+parser: bin/parser -c $HOME/config.yml
diff --git a/cmd/api/main.go b/cmd/api/main.go
index 58ba1da..a513bc2 100644
--- a/cmd/api/main.go
+++ b/cmd/api/main.go
@@ -2,6 +2,8 @@ package main
 
 import (
 	"context"
+	"time"
+
 	"github.com/gin-gonic/gin"
 	log "github.com/sirupsen/logrus"
 	"github.com/trustwallet/blockatlas/api"
@@ -11,10 +13,8 @@ import (
 	"github.com/trustwallet/blockatlas/internal"
 	"github.com/trustwallet/blockatlas/mq"
 	"github.com/trustwallet/blockatlas/platform"
-	"github.com/trustwallet/blockatlas/services/spamfilter"
 	"github.com/trustwallet/blockatlas/services/tokenindexer"
 	"github.com/trustwallet/blockatlas/services/tokensearcher"
-	"time"
 )
 
 const (
@@ -40,7 +40,6 @@ func init() {
 
 	engine = internal.InitEngine(config.Default.Gin.Mode)
 	platform.Init(config.Default.Platform)
-	spamfilter.SpamList = config.Default.SpamWords
 
 	var err error
 	database, err = db.New(config.Default.Postgres.URL, config.Default.Postgres.Read.URL,
diff --git a/cmd/consumer/main.go b/cmd/consumer/main.go
index 00415dd..e965728 100644
--- a/cmd/consumer/main.go
+++ b/cmd/consumer/main.go
@@ -2,12 +2,14 @@ package main
 
 import (
 	"context"
-	"github.com/trustwallet/blockatlas/config"
+	"time"
+
 	"github.com/trustwallet/blockatlas/services/notifier"
+
+	"github.com/trustwallet/blockatlas/config"
 	"github.com/trustwallet/blockatlas/services/subscriber"
 	"github.com/trustwallet/blockatlas/services/tokenindexer"
 	"github.com/trustwallet/blockatlas/services/tokensearcher"
-	"time"
 
 	log "github.com/sirupsen/logrus"
 	"github.com/trustwallet/blockatlas/db"
@@ -40,7 +42,7 @@ func init() {
 	database, err = db.New(config.Default.Postgres.URL, config.Default.Postgres.Read.URL,
 		config.Default.Postgres.Log)
 	if err != nil {
-		log.Fatal(err)
+		log.Fatal("Postgres init: ", err)
 	}
 	go database.RestoreConnectionWorker(ctx, time.Second*10, config.Default.Postgres.URL)
 
@@ -50,30 +52,29 @@ func init() {
 func main() {
 	defer mq.Close()
 
-	if err := mq.RawTransactionsTokenIndexer.Declare(); err != nil {
-		log.Fatal(err)
-	}
-	if err := mq.RawTransactions.Declare(); err != nil {
-		log.Fatal(err)
+	queues := []mq.Queue{
+		mq.TxNotifications,
+		mq.RawTransactionsTokenIndexer,
+		mq.RawTransactions,
+		mq.RawTransactionsSearcher,
+		mq.Subscriptions,
+		mq.TokensRegistration,
 	}
-	if err := mq.TxNotifications.Declare(); err != nil {
-		log.Fatal(err)
-	}
-	if err := mq.RawTransactionsSearcher.Declare(); err != nil {
-		log.Fatal(err)
-	}
-	if err := mq.Subscriptions.Declare(); err != nil {
-		log.Fatal(err)
-	}
-	if err := mq.TokensRegistration.Declare(); err != nil {
-		log.Fatal(err)
+
+	for _, queue := range queues {
+		err := queue.Declare()
+		if err != nil {
+			log.Fatal("Declare ", queue, err)
+		}
 	}
 
-	go mq.RawTransactionsTokenIndexer.RunConsumerWithCancelAndDbConnConcurrent(tokenindexer.RunTokenIndexer, database, ctx)
-	go mq.RawTransactions.RunConsumerWithCancelAndDbConnConcurrent(notifier.RunNotifier, database, ctx)
-	go mq.RawTransactionsSearcher.RunConsumerWithCancelAndDbConnConcurrent(tokensearcher.Run, database, ctx)
-	go mq.Subscriptions.RunConsumerWithCancelAndDbConnConcurrent(subscriber.RunTransactionsSubscriber, database, ctx)
-	go mq.TokensRegistration.RunConsumerWithCancelAndDbConnConcurrent(subscriber.RunTokensSubscriber, database, ctx)
+	go mq.RawTransactions.RunConsumerWithCancelAndDbConn(notifier.RunNotifier, database, ctx)
+
+	go mq.RawTransactionsTokenIndexer.RunConsumerWithCancelAndDbConn(tokenindexer.RunTokenIndexer, database, ctx)
+	go mq.RawTransactionsSearcher.RunConsumerWithCancelAndDbConn(tokensearcher.Run, database, ctx)
+
+	go mq.Subscriptions.RunConsumerWithCancelAndDbConn(subscriber.RunTransactionsSubscriber, database, ctx)
+	go mq.TokensRegistration.RunConsumerWithCancelAndDbConn(subscriber.RunTokensSubscriber, database, ctx)
 
 	go mq.FatalWorker(time.Second * 10)
 
diff --git a/cmd/parser/main.go b/cmd/parser/main.go
index 7281a7c..216642b 100644
--- a/cmd/parser/main.go
+++ b/cmd/parser/main.go
@@ -3,14 +3,14 @@ package main
 import (
 	"context"
 	"fmt"
-	"github.com/trustwallet/blockatlas/config"
-	"github.com/trustwallet/blockatlas/services/spamfilter"
 	"os"
 	"os/signal"
 	"sync"
 	"syscall"
 	"time"
 
+	"github.com/trustwallet/blockatlas/config"
+
 	log "github.com/sirupsen/logrus"
 	"github.com/trustwallet/blockatlas/db"
 	"github.com/trustwallet/blockatlas/internal"
@@ -41,7 +41,6 @@ func init() {
 	)
 
 	platform.Init(config.Default.Platform)
-	spamfilter.SpamList = config.Default.SpamWords
 
 	if err := mq.RawTransactions.Declare(); err != nil {
 		log.Fatal(err)
@@ -104,10 +103,10 @@ func main() {
 		coinCancel[coin.Handle] = cancel
 
 		params := parser.Params{
-			Ctx: ctx,
-			Api: api,
-			Queue: []mq.Queue{
-				mq.RawTransactions,
+			Ctx:               ctx,
+			Api:               api,
+			TransactionsQueue: mq.RawTransactions,
+			TokenTransactionsQueue: []mq.Queue{
 				mq.RawTransactionsSearcher,
 				mq.RawTransactionsTokenIndexer,
 			},
@@ -123,6 +122,7 @@ func main() {
 		go parser.RunParser(params)
 
 		log.WithFields(log.Fields{
+			"coin":                     api.Coin().Handle,
 			"interval":                 pollInterval,
 			"backlog":                  backlogCount,
 			"Max backlog":              maxBackLogBlocks,
diff --git a/config.yml b/config.yml
index e9e91b9..9a67366 100644
--- a/config.yml
+++ b/config.yml
@@ -8,8 +8,6 @@ gin:
 # You can see all the coin handles at coins/coins.yml file
 platform: [ all ]
 
-spam_words: [ "airdrop","www", "http" ]
-
 # The transaction watcher
 observer:
   # Don't request blocks older than this
@@ -40,7 +38,7 @@ postgres:
 # [BNB] Binance DEX: https://www.binance.org/
 binance:
   api: https://dex.binance.org
-  explorer: https://explorer.binance.org
+  # key: ""
 
 # [NIM] Nimiq: https://nimiq.com
 nimiq:
@@ -207,7 +205,7 @@ harmony:
   api: https://api.s0.t.hmny.io
 
 kava:
-  api: https://data.kava.io
+  api: https://kava.data.kava.io
 
 kusama:
   api: https://kusama.subscan.io/api
diff --git a/config/configuration.go b/config/configuration.go
index 40fb1d2..36efd8e 100755
--- a/config/configuration.go
+++ b/config/configuration.go
@@ -1,11 +1,12 @@
 package config
 
 import (
-	log "github.com/sirupsen/logrus"
-	"github.com/spf13/viper"
 	"reflect"
 	"strings"
 	"time"
+
+	log "github.com/sirupsen/logrus"
+	"github.com/spf13/viper"
 )
 
 type Configuration struct {
@@ -15,7 +16,6 @@ type Configuration struct {
 	} `mapstructure:"gin"`
 	Platform   []string `mapstructure:"platform"`
 	RestAPI    string   `mapstructure:"rest_api"`
-	SpamWords  []string `mapstructure:"spam_words"`
 	Subscriber string   `mapstructure:"subscriber"`
 	Observer   struct {
 		Backlog                     time.Duration `mapstructure:"backlog"`
@@ -49,8 +49,8 @@ type Configuration struct {
 		RPC            string `mapstructure:"rpc"`
 	} `mapstructure:"ethereum"`
 	Binance struct {
-		API      string `mapstructure:"api"`
-		Explorer string `mapstructure:"explorer"`
+		API string `mapstructure:"api"`
+		Key string `mapstructure:"key"`
 	} `mapstructure:"binance"`
 	Ripple struct {
 		API string `mapstructure:"api"`
diff --git a/configmock.yml b/configmock.yml
index 47e22bc..cbddd73 100644
--- a/configmock.yml
+++ b/configmock.yml
@@ -7,8 +7,6 @@ gin:
 # You can see all the coin handles at coins/coins.yml file
 platform: all
 
-spam_words: [ "airdrop","www", "http" ]
-
 # The transaction watcher
 observer:
   backlog: 3h
diff --git a/go.mod b/go.mod
index 4a0142d..61593b6 100644
--- a/go.mod
+++ b/go.mod
@@ -46,8 +46,8 @@ require (
 	golang.org/x/net v0.0.0-20200506145744-7e3656a0809f // indirect
 	golang.org/x/tools v0.0.0-20200513175351-0951661448da // indirect
 	gopkg.in/yaml.v2 v2.3.0
-	gorm.io/driver/postgres v1.0.0
-	gorm.io/gorm v1.20.0
+	gorm.io/driver/postgres v1.0.5
+	gorm.io/gorm v1.20.6
 	gorm.io/plugin/dbresolver v1.0.0
 	gotest.tools v2.2.0+incompatible // indirect
 	howett.net/plist v0.0.0-20200419221736-3b63eb3a43b5 // indirect
diff --git a/go.sum b/go.sum
index 7f2ef13..fc68381 100644
--- a/go.sum
+++ b/go.sum
@@ -229,8 +229,8 @@ github.com/jackc/pgconn v0.0.0-20190831204454-2fabfa3c18b7/go.mod h1:ZJKsE/KZfsU
 github.com/jackc/pgconn v1.4.0/go.mod h1:Y2O3ZDF0q4mMacyWV3AstPJpeHXWGEetiFttmq5lahk=
 github.com/jackc/pgconn v1.5.0/go.mod h1:QeD3lBfpTFe8WUnPZWN5KY/mB8FGMIYRdd8P8Jr0fAI=
 github.com/jackc/pgconn v1.5.1-0.20200601181101-fa742c524853/go.mod h1:QeD3lBfpTFe8WUnPZWN5KY/mB8FGMIYRdd8P8Jr0fAI=
-github.com/jackc/pgconn v1.6.4 h1:S7T6cx5o2OqmxdHaXLH1ZeD1SbI8jBznyYE9Ec0RCQ8=
-github.com/jackc/pgconn v1.6.4/go.mod h1:w2pne1C2tZgP+TvjqLpOigGzNqjBgQW9dUw/4Chex78=
+github.com/jackc/pgconn v1.7.0 h1:pwjzcYyfmz/HQOQlENvG1OcDqauTGaqlVahq934F0/U=
+github.com/jackc/pgconn v1.7.0/go.mod h1:sF/lPpNEMEOp+IYhyQGdAvrG20gWf6A1tKlr0v7JMeA=
 github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE=
 github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8=
 github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2 h1:JVX6jT/XfzNqIjye4717ITLaNwV9mWbJx0dLCpcRzdA=
@@ -244,8 +244,8 @@ github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190609003834-432c2951c711/go.mod
 github.com/jackc/pgproto3/v2 v2.0.0-rc3/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM=
 github.com/jackc/pgproto3/v2 v2.0.0-rc3.0.20190831210041-4c03ce451f29/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM=
 github.com/jackc/pgproto3/v2 v2.0.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
-github.com/jackc/pgproto3/v2 v2.0.2 h1:q1Hsy66zh4vuNsajBUF2PNqfAMMfxU5mk594lPE9vjY=
-github.com/jackc/pgproto3/v2 v2.0.2/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
+github.com/jackc/pgproto3/v2 v2.0.5 h1:NUbEWPmCQZbMmYlTjVoNPhc0CfnYyz2bfUAh6A5ZVJM=
+github.com/jackc/pgproto3/v2 v2.0.5/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
 github.com/jackc/pgservicefile v0.0.0-20200307190119-3430c5407db8/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E=
 github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b h1:C8S2+VttkHFdOOCXJe+YGfa4vHYwlt4Zx+IVXQ97jYg=
 github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E=
@@ -255,20 +255,21 @@ github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrU
 github.com/jackc/pgtype v1.2.0/go.mod h1:5m2OfMh1wTK7x+Fk952IDmI4nw3nPrvtQdM0ZT4WpC0=
 github.com/jackc/pgtype v1.3.1-0.20200510190516-8cd94a14c75a/go.mod h1:vaogEUkALtxZMCH411K+tKzNpwzCKU+AnPzBKZ+I+Po=
 github.com/jackc/pgtype v1.3.1-0.20200606141011-f6355165a91c/go.mod h1:cvk9Bgu/VzJ9/lxTO5R5sf80p0DiucVtN7ZxvaC4GmQ=
-github.com/jackc/pgtype v1.4.2 h1:t+6LWm5eWPLX1H5Se702JSBcirq6uWa4jiG4wV1rAWY=
-github.com/jackc/pgtype v1.4.2/go.mod h1:JCULISAZBFGrHaOXIIFiyfzW5VY0GRitRr8NeJsrdig=
+github.com/jackc/pgtype v1.5.0 h1:jzBqRk2HFG2CV4AIwgCI2PwTgm6UUoCAK2ofHHRirtc=
+github.com/jackc/pgtype v1.5.0/go.mod h1:JCULISAZBFGrHaOXIIFiyfzW5VY0GRitRr8NeJsrdig=
 github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y=
 github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM=
 github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc=
 github.com/jackc/pgx/v4 v4.5.0/go.mod h1:EpAKPLdnTorwmPUUsqrPxy5fphV18j9q3wrfRXgo+kA=
 github.com/jackc/pgx/v4 v4.6.1-0.20200510190926-94ba730bb1e9/go.mod h1:t3/cdRQl6fOLDxqtlyhe9UWgfIi9R8+8v8GKV5TRA/o=
 github.com/jackc/pgx/v4 v4.6.1-0.20200606145419-4e5062306904/go.mod h1:ZDaNWkt9sW1JMiNn0kdYBaLelIhw7Pg4qd+Vk6tw7Hg=
-github.com/jackc/pgx/v4 v4.8.1 h1:SUbCLP2pXvf/Sr/25KsuI4aTxiFYIvpfk4l6aTSdyCw=
-github.com/jackc/pgx/v4 v4.8.1/go.mod h1:4HOLxrl8wToZJReD04/yB20GDwf4KBYETvlHciCnwW0=
+github.com/jackc/pgx/v4 v4.9.0 h1:6STjDqppM2ROy5p1wNDcsC7zJTjSHeuCsguZmXyzx7c=
+github.com/jackc/pgx/v4 v4.9.0/go.mod h1:MNGWmViCgqbZck9ujOOBN63gK9XVGILXWCvKLGKmnms=
 github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
 github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
 github.com/jackc/puddle v1.1.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
 github.com/jackc/puddle v1.1.1/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
+github.com/jackc/puddle v1.1.2/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
 github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
 github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
 github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
@@ -704,11 +705,14 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie
 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gorm.io/driver/mysql v1.0.1 h1:omJoilUzyrAp0xNoio88lGJCroGdIOen9hq2A/+3ifw=
 gorm.io/driver/mysql v1.0.1/go.mod h1:KtqSthtg55lFp3S5kUXqlGaelnWpKitn4k1xZTnoiPw=
-gorm.io/driver/postgres v1.0.0 h1:Yh4jyFQ0a7F+JPU0Gtiam/eKmpT/XFc1FKxotGqc6FM=
-gorm.io/driver/postgres v1.0.0/go.mod h1:wtMFcOzmuA5QigNsgEIb7O5lhvH1tHAF1RbWmLWV4to=
+gorm.io/driver/postgres v1.0.5 h1:raX6ezL/ciUmaYTvOq48jq1GE95aMC0CmxQYbxQ4Ufw=
+gorm.io/driver/postgres v1.0.5/go.mod h1:qrD92UurYzNctBMVCJ8C3VQEjffEuphycXtxOudXNCA=
 gorm.io/gorm v1.9.19/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw=
 gorm.io/gorm v1.20.0 h1:qfIlyaZvrF7kMWY3jBdEBXkXJ2M5MFYMTppjILxS3fQ=
 gorm.io/gorm v1.20.0/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw=
+gorm.io/gorm v1.20.4/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw=
+gorm.io/gorm v1.20.6 h1:qa7tC1WcU+DBI/ZKMxvXy1FcrlGsvxlaKufHrT2qQ08=
+gorm.io/gorm v1.20.6/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw=
 gorm.io/plugin/dbresolver v1.0.0 h1:fHIWRRkoDmXkBPYyg9GMmLugcM9fcbZiG0Zy/cwiPlM=
 gorm.io/plugin/dbresolver v1.0.0/go.mod h1:sK1Alv120lfrjRQXrzyAw4ssxDPJjamm2cbBOZBHM68=
 gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
diff --git a/mq/mq.go b/mq/mq.go
index a3de94b..cb20e90 100644
--- a/mq/mq.go
+++ b/mq/mq.go
@@ -2,10 +2,11 @@ package mq
 
 import (
 	"context"
+	"time"
+
 	log "github.com/sirupsen/logrus"
 	"github.com/streadway/amqp"
 	"github.com/trustwallet/blockatlas/db"
-	"time"
 )
 
 var (
@@ -22,12 +23,18 @@ type (
 )
 
 const (
-	TxNotifications             Queue = "txNotifications"
-	Subscriptions               Queue = "subscriptions"
-	RawTransactions             Queue = "rawTransactions"
-	RawTransactionsSearcher     Queue = "rawTransactionsSearcher"
+	// End consumer of published transactions. Not consumed on blockatlas
+	TxNotifications Queue = "txNotifications"
+	// Address:coin subscriptions
+	Subscriptions Queue = "subscriptions"
+	// Transactions to process, if match subscriptions, pushed to TxNotifications
+	RawTransactions Queue = "rawTransactions"
+	// Token indexer for finding asset association with an address
+	RawTransactionsSearcher Queue = "rawTransactionsSearcher"
+	// Token indexer for finding new assets
 	RawTransactionsTokenIndexer Queue = "rawTransactionsTokenIndexer"
-	TokensRegistration          Queue = "tokensRegistration"
+	// Register new addresses to observers for token transfers
+	TokensRegistration Queue = "tokensRegistration"
 )
 
 func Init(uri string) (err error) {
@@ -99,7 +106,7 @@ func (q Queue) GetMessageChannel() MessageChannel {
 		nil,
 	)
 	if err != nil {
-		log.Fatal("MQ issue " + err.Error())
+		log.Fatal("GetMessageChannel MQ issue "+err.Error(), string(q))
 	}
 
 	err = amqpChan.Qos(
diff --git a/pkg/blockatlas/tx.go b/pkg/blockatlas/tx.go
index 40a8c49..9fdbcde 100644
--- a/pkg/blockatlas/tx.go
+++ b/pkg/blockatlas/tx.go
@@ -203,10 +203,10 @@ type (
 	Txs []Tx
 )
 
-func (t Txs) FilterUniqueID() Txs {
+func (txs Txs) FilterUniqueID() Txs {
 	keys := make(map[string]bool)
 	list := make(Txs, 0)
-	for _, entry := range t {
+	for _, entry := range txs {
 		if _, value := keys[entry.ID]; !value {
 			keys[entry.ID] = true
 			list = append(list, entry)
@@ -226,6 +226,18 @@ func (txs TxPage) FilterTransactionsByMemo() TxPage {
 	return result
 }
 
+func (txs Txs) FilterTransactionsByType(types []TransactionType) Txs {
+	result := make(Txs, 0)
+	for _, tx := range txs {
+		for _, t := range types {
+			if tx.Type == t {
+				result = append(result, tx)
+			}
+		}
+	}
+	return result
+}
+
 func AllowMemo(memo string) bool {
 	// only allows numeric values
 	_, err := strconv.ParseFloat(memo, 64)
@@ -267,11 +279,11 @@ func (txs TxPage) FilterTransactionsByToken(token string) TxPage {
 	return result
 }
 
-func (t Txs) SortByDate() Txs {
-	sort.Slice(t, func(i, j int) bool {
-		return t[i].Date > t[j].Date
+func (txs Txs) SortByDate() Txs {
+	sort.Slice(txs, func(i, j int) bool {
+		return txs[i].Date > txs[j].Date
 	})
-	return t
+	return txs
 }
 
 func (t *Tx) GetUtxoAddresses() (addresses []string) {
diff --git a/platform/binance/base.go b/platform/binance/base.go
index e39ec58..f49c59b 100644
--- a/platform/binance/base.go
+++ b/platform/binance/base.go
@@ -8,9 +8,9 @@ type Platform struct {
 	client Client
 }
 
-func Init(api string) *Platform {
+func Init(api, apiKey string) *Platform {
 	p := Platform{
-		client: InitClient(api),
+		client: InitClient(api, apiKey),
 	}
 	return &p
 }
diff --git a/platform/binance/client.go b/platform/binance/client.go
index f4f09e2..eae60f6 100644
--- a/platform/binance/client.go
+++ b/platform/binance/client.go
@@ -2,26 +2,37 @@ package binance
 
 import (
 	"fmt"
+	"net/http"
+	"net/url"
+	"strconv"
+	"time"
+
 	"github.com/imroc/req"
 	"github.com/patrickmn/go-cache"
 	log "github.com/sirupsen/logrus"
 	"github.com/trustwallet/blockatlas/pkg/blockatlas"
-	"net/url"
-	"strconv"
-	"time"
 )
 
 type Client struct {
 	*cache.Cache
-	url string
+	url    string
+	apiKey string
 }
 
-func InitClient(url string) Client {
-	return Client{url: url, Cache: cache.New(5*time.Minute, 10*time.Minute)}
+func InitClient(url, apiKey string) Client {
+	return Client{url: url, apiKey: apiKey, Cache: cache.New(5*time.Minute, 10*time.Minute)}
+}
+
+func (c Client) Get(path string, params interface{}) (*req.Resp, error) {
+	header := make(http.Header)
+	if c.apiKey != "" {
+		header.Set("apikey", c.apiKey)
+	}
+	return req.Get(c.url+path, header, params)
 }
 
 func (c Client) FetchLatestBlockNumber() (int64, error) {
-	resp, err := req.Get(c.url+"/api/v1/node-info", nil)
+	resp, err := c.Get("/api/v1/node-info", nil)
 	if err != nil {
 		return 0, err
 	}
@@ -35,7 +46,7 @@ func (c Client) FetchLatestBlockNumber() (int64, error) {
 }
 
 func (c Client) FetchTransactionsInBlock(blockNumber int64) (TransactionsInBlockResponse, error) {
-	resp, err := req.Get(c.url+fmt.Sprintf("/api/v2/transactions-in-block/%d", blockNumber), nil)
+	resp, err := c.Get(fmt.Sprintf("/api/v2/transactions-in-block/%d", blockNumber), nil)
 	if err != nil {
 		return TransactionsInBlockResponse{}, err
 	}
@@ -52,7 +63,7 @@ func (c Client) FetchTransactionsByAddressAndTokenID(address, tokenID string) ([
 	startTime := strconv.Itoa(int(time.Now().AddDate(0, -3, 0).Unix() * 1000))
 	limit := strconv.Itoa(blockatlas.TxPerPage)
 	params := url.Values{"address": {address}, "txAsset": {tokenID}, "startTime": {startTime}, "limit": {limit}}
-	resp, err := req.Get(c.url+"/api/v1/transactions", params)
+	resp, err := c.Get("/api/v1/transactions", params)
 	if err != nil {
 		return nil, err
 	}
@@ -66,7 +77,7 @@ func (c Client) FetchTransactionsByAddressAndTokenID(address, tokenID string) ([
 }
 
 func (c Client) FetchAccountMeta(address string) (AccountMeta, error) {
-	resp, err := req.Get(c.url+fmt.Sprintf("/api/v1/account/%s", address), nil)
+	resp, err := c.Get(fmt.Sprintf("/api/v1/account/%s", address), nil)
 	if err != nil {
 		return AccountMeta{}, err
 	}
@@ -86,7 +97,7 @@ func (c Client) FetchTokens() (Tokens, error) {
 	}
 	result := new(Tokens)
 	query := url.Values{"limit": {tokensLimit}}
-	resp, err := req.Get(c.url+"/api/v1/tokens", query)
+	resp, err := c.Get("/api/v1/tokens", query)
 	if err != nil {
 		return nil, err
 	}
diff --git a/platform/platform.go b/platform/platform.go
index adc7921..066042c 100644
--- a/platform/platform.go
+++ b/platform/platform.go
@@ -65,7 +65,7 @@ func getAllHandlers() blockatlas.Platforms {
 		coin.Aeternity().Handle:    aeternity.Init(config.Default.Aeternity.API),
 		coin.Solana().Handle:       solana.Init(config.Default.Solana.API),
 		coin.Tezos().Handle:        tezos.Init(config.Default.Tezos.API, config.Default.Tezos.RPC),
-		coin.Binance().Handle:      binance.Init(config.Default.Binance.API),
+		coin.Binance().Handle:      binance.Init(config.Default.Binance.API, config.Default.Binance.Key),
 		coin.Zilliqa().Handle:      zilliqa.Init(config.Default.Zilliqa.API, config.Default.Zilliqa.Key, config.Default.Zilliqa.RPC),
 		coin.Kusama().Handle:       polkadot.Init(coin.KSM, config.Default.Kusama.API),
 		coin.Polkadot().Handle:     polkadot.Init(coin.DOT, config.Default.Polkadot.API),
diff --git a/services/notifier/delivery.go b/services/notifier/delivery.go
index 04d3ced..c5bd6d5 100644
--- a/services/notifier/delivery.go
+++ b/services/notifier/delivery.go
@@ -4,6 +4,9 @@ import (
 	"context"
 	"encoding/json"
 	"errors"
+
+	"github.com/trustwallet/golibs/coin"
+
 	log "github.com/sirupsen/logrus"
 	"github.com/streadway/amqp"
 	"github.com/trustwallet/blockatlas/mq"
@@ -21,11 +24,12 @@ func GetTransactionsFromDelivery(delivery amqp.Delivery, service string, ctx con
 		return nil, err
 	}
 
-	log.WithFields(log.Fields{"service": service, "txs": len(txs), "coin": txs[0].Coin}).Info("Consumed")
-
 	if len(txs) == 0 {
 		return nil, errors.New("empty txs list")
 	}
+
+	log.WithFields(log.Fields{"service": service, "txs": len(txs), "coin": coin.Coins[txs[0].Coin].Handle}).Info("Consumed")
+
 	return txs, nil
 }
 
@@ -35,11 +39,11 @@ func publishNotificationBatch(batch []TransactionNotification, ctx context.Conte
 
 	raw, err := json.Marshal(batch)
 	if err != nil {
-		log.Fatal(err)
+		log.Fatal("publishNotificationBatch marshal: ", err)
 	}
 	err = mq.TxNotifications.Publish(raw)
 	if err != nil {
-		log.Fatal(err)
+		log.Fatal("publishNotificationBatch publish:", err)
 	}
 
 	log.WithFields(log.Fields{"service": Notifier, "txs": len(batch)}).Info("Txs batch dispatched")
diff --git a/services/parser/parser.go b/services/parser/parser.go
index 1cc5256..6fcaef3 100644
--- a/services/parser/parser.go
+++ b/services/parser/parser.go
@@ -25,7 +25,8 @@ type (
 	Params struct {
 		Ctx                                       context.Context
 		Api                                       blockatlas.BlockAPI
-		Queue                                     []mq.Queue
+		TransactionsQueue                         mq.Queue
+		TokenTransactionsQueue                    []mq.Queue
 		ParsingBlocksInterval, FetchBlocksTimeout time.Duration
 		BacklogCount                              int
 		MaxBacklogBlocks                          int64
@@ -39,11 +40,6 @@ type (
 	stop struct {
 		error
 	}
-
-	transactionsBatch struct {
-		sync.Mutex
-		blockatlas.Txs
-	}
 )
 
 const MinTxsBatchLimit = 500
@@ -79,7 +75,7 @@ func parse(params Params) {
 
 	lastParsedBlock, currentBlock, err := GetBlocksIntervalToFetch(params, ctx)
 	if err != nil || lastParsedBlock > currentBlock {
-		log.WithFields(log.Fields{"coin": params.Api.Coin().Handle}).Error(err)
+		log.WithFields(log.Fields{"operation": "fetch GetBlocksIntervalToFetch", "coin": params.Api.Coin().Handle}).Error(err)
 		time.Sleep(params.ParsingBlocksInterval)
 		return
 	}
@@ -88,17 +84,17 @@ func parse(params Params) {
 
 	err = SaveLastParsedBlock(params, blocks, ctx)
 	if err != nil {
-		log.WithFields(log.Fields{"coin": params.Api.Coin().Handle}).Error(err)
+		log.WithFields(log.Fields{"operation": "run SaveLastParsedBlock", "coin": params.Api.Coin().Handle}).Error(err)
 		time.Sleep(params.ParsingBlocksInterval)
 		return
 	}
 
-	txs := ConvertToBatch(blocks, ctx)
+	txs := ConvertToBatch(blocks)
 	txs = blockatlas.Txs(blockatlas.TxPage(txs).FilterTransactionsByMemo())
 
 	PublishTransactionsBatch(params, txs, ctx)
 
-	log.Info("End of parse step")
+	log.WithFields(log.Fields{"coin": params.Api.Coin().Handle}).Info("End of parse step")
 }
 
 func GetBlocksIntervalToFetch(params Params, ctx context.Context) (int64, int64, error) {
@@ -130,7 +126,7 @@ func FetchBlocks(params Params, lastParsedBlock, currentBlock int64, ctx context
 	defer span.End()
 
 	if lastParsedBlock == currentBlock {
-		log.WithFields(log.Fields{"last": lastParsedBlock, "coin": params.Api.Coin().ID, "time": time.Now().Unix()}).
+		log.WithFields(log.Fields{"last": lastParsedBlock, "coin": params.Api.Coin().Handle, "time": time.Now().Unix()}).
 			Info("No new blocks")
 		return nil
 	}
@@ -173,7 +169,7 @@ func FetchBlocks(params Params, lastParsedBlock, currentBlock int64, ctx context
 		for err := range errorsChan {
 			errorsList = append(errorsList, err)
 		}
-		log.WithFields(log.Fields{"count": len(errorsList), "blocks": errorsList}).Error("Fetch blocks errors")
+		log.WithFields(log.Fields{"coin": params.Api.Coin().Handle, "count": len(errorsList), "blocks": errorsList}).Error("Fetch blocks errors")
 	}
 
 	blocksList := make([]blockatlas.Block, 0, len(blocksChan))
@@ -181,7 +177,7 @@ func FetchBlocks(params Params, lastParsedBlock, currentBlock int64, ctx context
 		blocksList = append(blocksList, block)
 	}
 
-	log.WithFields(log.Fields{"from": lastParsedBlock, "to": currentBlock, "total": totalCount}).
+	log.WithFields(log.Fields{"from": lastParsedBlock, "to": currentBlock, "total": totalCount, "coin": params.Api.Coin().Handle}).
 		Info("Fetched blocks batch")
 	return blocksList
 }
@@ -227,36 +223,18 @@ func SaveLastParsedBlock(params Params, blocks []blockatlas.Block, ctx context.C
 	return nil
 }
 
-func ConvertToBatch(blocks []blockatlas.Block, ctx context.Context) blockatlas.Txs {
-	span, ctx := apm.StartSpan(ctx, "ConvertToBatch", "app")
-	defer span.End()
+func ConvertToBatch(blocks []blockatlas.Block) blockatlas.Txs {
 	if len(blocks) == 0 {
 		return nil
 	}
 
-	var (
-		txsBatch transactionsBatch
-		wg       sync.WaitGroup
-	)
+	var txs []blockatlas.Tx
 
 	for _, block := range blocks {
-		wg.Add(1)
-		go func(block blockatlas.Block, wg *sync.WaitGroup) {
-			defer wg.Done()
-			txsBatch.fillBatch(block.Txs, ctx)
-		}(block, &wg)
+		txs = append(txs, block.Txs...)
 	}
-	wg.Wait()
 
-	if len(txsBatch.Txs) == 0 {
-		log.WithFields(log.Fields{"blocks": len(blocks)}).
-			Info("Blocks converted to transactions batch, there is no transactions")
-		return nil
-	}
-
-	log.WithFields(log.Fields{"blocks": len(blocks), "txs": len(txsBatch.Txs)}).
-		Info("Blocks converted to transactions batch")
-	return txsBatch.Txs
+	return txs
 }
 
 func PublishTransactionsBatch(params Params, txs blockatlas.Txs, ctx context.Context) {
@@ -300,14 +278,40 @@ func publish(params Params, txs blockatlas.Txs, ctx context.Context) {
 
 	body, err := json.Marshal(txs)
 	if err != nil {
-		log.WithFields(log.Fields{"coin": params.Api.Coin().Handle}).Error(err)
+		log.WithFields(log.Fields{"operation": "publish marshal", "coin": params.Api.Coin().Handle}).Error(err)
 		return
 	}
-	for _, q := range params.Queue {
-		err = q.Publish(body)
-		if err != nil {
-			log.WithFields(log.Fields{"coin": params.Api.Coin().Handle}).Error(err)
-			return
+
+	// Notify transactions queue
+	err = params.TransactionsQueue.Publish(body)
+	if err != nil {
+		log.WithFields(log.Fields{"operation": "publish transactionsQueue", "coin": params.Api.Coin().Handle}).Error(err)
+		return
+	}
+
+	// Notify token transfers queue, if conforms to TokensAPI protocol
+	tokenTransfers := txs.FilterTransactionsByType([]blockatlas.TransactionType{
+		blockatlas.TxTokenTransfer,
+		blockatlas.TxNativeTokenTransfer,
+	})
+
+	if len(tokenTransfers) == 0 {
+		return
+	}
+
+	tokenTransfersBody, err := json.Marshal(tokenTransfers)
+	if err != nil {
+		log.WithFields(log.Fields{"operation": "marshal tokenTransfers", "coin": params.Api.Coin().Handle}).Error(err)
+		return
+	}
+
+	if _, ok := params.Api.(blockatlas.TokensAPI); ok {
+		for _, q := range params.TokenTransactionsQueue {
+			err = q.Publish(tokenTransfersBody)
+			if err != nil {
+				log.WithFields(log.Fields{"coin": params.Api.Coin().Handle}).Error(err)
+				return
+			}
 		}
 	}
 }
@@ -327,7 +331,7 @@ func getBlockByNumberWithRetry(attempts int, sleep time.Duration, getBlockByNumb
 			sleep = sleep + jitter/2
 
 			log.WithFields(log.Fields{"number": n, "attempts": attempts, "sleep": sleep.String(), "symbol": symbol}).
-				Info("retry GetBlockByNumber")
+				Warn("retry GetBlockByNumber")
 
 			time.Sleep(sleep)
 			return getBlockByNumberWithRetry(attempts, sleep*2, getBlockByNumber, n, symbol, ctx)
@@ -335,14 +339,3 @@ func getBlockByNumberWithRetry(attempts int, sleep time.Duration, getBlockByNumb
 	}
 	return r, err
 }
-
-func (t *transactionsBatch) fillBatch(transactions []blockatlas.Tx, ctx context.Context) {
-	span, _ := apm.StartSpan(ctx, "fillBatch", "app")
-	defer span.End()
-	t.Lock()
-	defer t.Unlock()
-	if len(transactions) == 0 {
-		return
-	}
-	t.Txs = append(t.Txs, transactions...)
-}
diff --git a/services/spamfilter/spamfilter.go b/services/spamfilter/spamfilter.go
deleted file mode 100644
index 2bfa2fb..0000000
--- a/services/spamfilter/spamfilter.go
+++ /dev/null
@@ -1,30 +0,0 @@
-package spamfilter
-
-import (
-	"regexp"
-	"strings"
-)
-
-const URLRegex = `[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)`
-
-var (
-	SpamList       []string
-	compiledRegexp = regexp.MustCompile(URLRegex)
-)
-
-func ContainsSpam(name string) bool {
-	if isURL(name) {
-		return true
-	}
-	lowerCaseName := strings.ToLower(name)
-	for _, word := range SpamList {
-		if strings.Contains(lowerCaseName, word) {
-			return true
-		}
-	}
-	return false
-}
-
-func isURL(host string) bool {
-	return compiledRegexp.MatchString(host)
-}


Test patch:
diff --git a/pkg/blockatlas/tx_test.go b/pkg/blockatlas/tx_test.go
index 4fd7244..cc40e50 100644
--- a/pkg/blockatlas/tx_test.go
+++ b/pkg/blockatlas/tx_test.go
@@ -2,13 +2,14 @@ package blockatlas
 
 import (
 	"encoding/json"
+	"reflect"
+	"sort"
+	"testing"
+
 	mapset "github.com/deckarep/golang-set"
 	"github.com/stretchr/testify/assert"
 	"github.com/trustwallet/golibs/coin"
 	"github.com/trustwallet/golibs/tokentype"
-	"reflect"
-	"sort"
-	"testing"
 )
 
 var transferDst1 = Tx{
@@ -721,3 +722,39 @@ func TestTxPage_FilterTransactionsByMemo(t *testing.T) {
 		})
 	}
 }
+
+func TestTxs_FilterTransactionsByType(t *testing.T) {
+	type args struct {
+		types []TransactionType
+	}
+	tests := []struct {
+		name string
+		txs  Txs
+		args args
+		want Txs
+	}{
+		{
+			"Token Transfers",
+			Txs{
+				Tx{Type: TxTransfer},
+				Tx{Type: TxContractCall},
+				Tx{Type: TxNativeTokenTransfer},
+				Tx{Type: TxTokenTransfer},
+			},
+			args{
+				[]TransactionType{TxNativeTokenTransfer, TxTokenTransfer},
+			},
+			Txs{
+				Tx{Type: TxNativeTokenTransfer},
+				Tx{Type: TxTokenTransfer},
+			},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			if got := tt.txs.FilterTransactionsByType(tt.args.types); !reflect.DeepEqual(got, tt.want) {
+				t.Errorf("FilterTransactionsByType() = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}
diff --git a/platform/binance/block_test.go b/platform/binance/block_test.go
index 5fcc19b..5a496ce 100644
--- a/platform/binance/block_test.go
+++ b/platform/binance/block_test.go
@@ -2,15 +2,16 @@ package binance
 
 import (
 	"encoding/json"
-	"github.com/stretchr/testify/assert"
 	"net/http/httptest"
 	"testing"
+
+	"github.com/stretchr/testify/assert"
 )
 
 func TestPlatform_CurrentBlockNumber(t *testing.T) {
 	server := httptest.NewServer(createMockedAPI())
 	defer server.Close()
-	p := Init(server.URL)
+	p := Init(server.URL, "")
 	number, err := p.CurrentBlockNumber()
 	assert.Nil(t, err)
 	assert.Equal(t, int64(104867535), number)
@@ -19,7 +20,7 @@ func TestPlatform_CurrentBlockNumber(t *testing.T) {
 func TestPlatform_GetBlockByNumber(t *testing.T) {
 	server := httptest.NewServer(createMockedAPI())
 	defer server.Close()
-	p := Init(server.URL)
+	p := Init(server.URL, "")
 	block, err := p.GetBlockByNumber(104867508)
 	assert.Nil(t, err)
 	res, err := json.Marshal(block)
diff --git a/platform/binance/token_test.go b/platform/binance/token_test.go
index e01c206..7950dbf 100644
--- a/platform/binance/token_test.go
+++ b/platform/binance/token_test.go
@@ -2,15 +2,16 @@ package binance
 
 import (
 	"encoding/json"
-	"github.com/stretchr/testify/assert"
 	"net/http/httptest"
 	"testing"
+
+	"github.com/stretchr/testify/assert"
 )
 
 func TestPlatform_GetTokenListByAddress(t *testing.T) {
 	server := httptest.NewServer(createMockedAPI())
 	defer server.Close()
-	p := Init(server.URL)
+	p := Init(server.URL, "")
 
 	tokens, err := p.GetTokenListByAddress("bnb1w7puzjxu05ktc5zvpnzkndt6tyl720nsutzvpg")
 	assert.Nil(t, err)
diff --git a/platform/binance/transaction_test.go b/platform/binance/transaction_test.go
index f3b9af8..3bafcfb 100644
--- a/platform/binance/transaction_test.go
+++ b/platform/binance/transaction_test.go
@@ -2,15 +2,16 @@ package binance
 
 import (
 	"encoding/json"
-	"github.com/stretchr/testify/assert"
 	"net/http/httptest"
 	"testing"
+
+	"github.com/stretchr/testify/assert"
 )
 
 func TestPlatform_GetTxsByAddress(t *testing.T) {
 	server := httptest.NewServer(createMockedAPI())
 	defer server.Close()
-	p := Init(server.URL)
+	p := Init(server.URL, "")
 	txs, err := p.GetTxsByAddress("bnb136ns6lfw4zs5hg4n85vdthaad7hq5m4gtkgf23")
 	assert.Nil(t, err)
 	res, err := json.Marshal(txs)
@@ -21,7 +22,7 @@ func TestPlatform_GetTxsByAddress(t *testing.T) {
 func TestPlatform_GetTokenTxsByAddress(t *testing.T) {
 	server := httptest.NewServer(createMockedAPI())
 	defer server.Close()
-	p := Init(server.URL)
+	p := Init(server.URL, "")
 	txs, err := p.GetTokenTxsByAddress("bnb1w7puzjxu05ktc5zvpnzkndt6tyl720nsutzvpg", "AVA-645")
 	assert.Nil(t, err)
 	res, err := json.Marshal(txs)
diff --git a/services/parser/parser_test.go b/services/parser/parser_test.go
index 60f81d7..ac6ecdf 100644
--- a/services/parser/parser_test.go
+++ b/services/parser/parser_test.go
@@ -3,13 +3,14 @@ package parser
 import (
 	"context"
 	"errors"
+	"reflect"
+	"testing"
+	"time"
+
 	"github.com/stretchr/testify/assert"
 	"github.com/trustwallet/blockatlas/mq"
 	"github.com/trustwallet/blockatlas/pkg/blockatlas"
 	"github.com/trustwallet/golibs/coin"
-	"sync"
-	"testing"
-	"time"
 )
 
 var (
@@ -44,47 +45,22 @@ var (
 
 func TestFetchBlocks(t *testing.T) {
 	params := Params{
-		Ctx:                   nil,
-		Api:                   getMockedBlockAPI(),
-		Queue:                 []mq.Queue{""},
-		ParsingBlocksInterval: 0,
-		FetchBlocksTimeout:    0,
-		BacklogCount:          0,
-		MaxBacklogBlocks:      0,
-		StopChannel:           nil,
-		TxBatchLimit:          0,
-		Database:              nil,
+		Ctx:                    nil,
+		Api:                    getMockedBlockAPI(),
+		TransactionsQueue:      "",
+		TokenTransactionsQueue: []mq.Queue{""},
+		ParsingBlocksInterval:  0,
+		FetchBlocksTimeout:     0,
+		BacklogCount:           0,
+		MaxBacklogBlocks:       0,
+		StopChannel:            nil,
+		TxBatchLimit:           0,
+		Database:               nil,
 	}
 	blocks := FetchBlocks(params, 0, 100, context.Background())
 	assert.Equal(t, len(blocks), 100)
 }
 
-func TestParser_ConvertToBatch(t *testing.T) {
-	blocks := []blockatlas.Block{block, block, block, block}
-	txs := ConvertToBatch(blocks, context.Background())
-	assert.Equal(t, 4, len(txs))
-
-	empty := []blockatlas.Block{}
-	txsEmpty := ConvertToBatch(empty, context.Background())
-	assert.Equal(t, 0, len(txsEmpty))
-}
-
-func TestParser_add(t *testing.T) {
-	blocks := []blockatlas.Block{block, block, block, block}
-	txs := ConvertToBatch(blocks, context.Background())
-
-	batch := transactionsBatch{
-		Mutex: sync.Mutex{},
-		Txs:   txs,
-	}
-
-	batch.fillBatch(txs, context.Background())
-	assert.Equal(t, 8, len(batch.Txs))
-
-	batch.fillBatch(nil, context.Background())
-	assert.Equal(t, 8, len(batch.Txs))
-}
-
 func TestParser_getBlockByNumberWithRetry(t *testing.T) {
 	block, err := getBlockByNumberWithRetry(3, time.Millisecond*1, getBlock, 1, "", context.Background())
 	if err != nil {
@@ -222,3 +198,32 @@ func TestGetInterval(t *testing.T) {
 		})
 	}
 }
+
+func TestConvertToBatch(t *testing.T) {
+	type args struct {
+		blocks []blockatlas.Block
+	}
+	tests := []struct {
+		name string
+		args args
+		want blockatlas.Txs
+	}{
+		{
+			"Convert to batch",
+			args{
+				[]blockatlas.Block{
+					block,
+					block,
+				},
+			},
+			append(block.Txs, block.Txs...),
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			if got := ConvertToBatch(tt.args.blocks); !reflect.DeepEqual(got, tt.want) {
+				t.Errorf("ConvertToBatch() = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}
diff --git a/services/spamfilter/spamfilter_test.go b/services/spamfilter/spamfilter_test.go
deleted file mode 100644
index c3814e9..0000000
--- a/services/spamfilter/spamfilter_test.go
+++ /dev/null
@@ -1,13 +0,0 @@
-package spamfilter
-
-import (
-	"github.com/stretchr/testify/assert"
-	"testing"
-)
-
-func Test_isURL(t *testing.T) {
-	assert.True(t, isURL("http://www.trust.com"))
-	assert.True(t, isURL("www.trust.com"))
-	assert.True(t, isURL("trust.com"))
-	assert.True(t, isURL("saa,c trust.com"))
-}
diff --git a/tests/integration/db_test/tokenindexer_test.go b/tests/integration/db_test/tokenindexer_test.go
index d32482c..a9d45cd 100644
--- a/tests/integration/db_test/tokenindexer_test.go
+++ b/tests/integration/db_test/tokenindexer_test.go
@@ -5,7 +5,6 @@ package db_test
 import (
 	"context"
 	gocache "github.com/patrickmn/go-cache"
-	log "github.com/sirupsen/logrus"
 	assert "github.com/stretchr/testify/assert"
 	"github.com/trustwallet/blockatlas/db/models"
 	"github.com/trustwallet/blockatlas/tests/integration/setup"
@@ -202,9 +201,6 @@ func Test_AddNewAssets(t *testing.T) {
 			sort.Slice(assets, func(i, j int) bool {
 				return len(assets[i].Name) > len(assets[j].Name)
 			})
-			log.Info(tt.WantedAssets)
-			log.Info("----------------------")
-			log.Info(assets)
 			for i, a := range assets {
 				assert.Equal(t, tt.WantedAssets[i].Asset, a.Asset)
 				assert.Equal(t, tt.WantedAssets[i].Name, a.Name)
diff --git a/tests/integration/observer_test/full_flow_test.go b/tests/integration/observer_test/full_flow_test.go
index bc7190a..7acc077 100644
--- a/tests/integration/observer_test/full_flow_test.go
+++ b/tests/integration/observer_test/full_flow_test.go
@@ -34,7 +34,7 @@ func TestFullFlow(t *testing.T) {
 	params := setupParserFull(stopChan)
 	params.Database = database
 	params.Ctx = ctx
-	params.Queue = []mq.Queue{mq.RawTransactions}
+	params.TransactionsQueue = mq.RawTransactions
 
 	go parser.RunParser(params)
 	time.Sleep(time.Second * 2)
diff --git a/tests/integration/observer_test/observer_test.go b/tests/integration/observer_test/observer_test.go
index cdaba9d..a2a851c 100644
--- a/tests/integration/observer_test/observer_test.go
+++ b/tests/integration/observer_test/observer_test.go
@@ -3,12 +3,13 @@
 package observer_test
 
 import (
-	"github.com/trustwallet/blockatlas/db"
-	"github.com/trustwallet/blockatlas/mq"
-	"github.com/trustwallet/blockatlas/tests/integration/setup"
 	"log"
 	"os"
 	"testing"
+
+	"github.com/trustwallet/blockatlas/db"
+	"github.com/trustwallet/blockatlas/mq"
+	"github.com/trustwallet/blockatlas/tests/integration/setup"
 )
 
 var (
diff --git a/tests/integration/observer_test/parser_test.go b/tests/integration/observer_test/parser_test.go
index 795bc0b..3ef3f37 100644
--- a/tests/integration/observer_test/parser_test.go
+++ b/tests/integration/observer_test/parser_test.go
@@ -27,7 +27,7 @@ func TestParserFetchAndPublishBlock_NormalCase(t *testing.T) {
 	ctx, cancel := context.WithCancel(context.Background())
 
 	params.Ctx = ctx
-	params.Queue = []mq.Queue{mq.RawTransactions}
+	params.TransactionsQueue = mq.RawTransactions
 
 	go parser.RunParser(params)