Repository: trustwallet/blockatlas
Pull request #1010 (2020-04-04 19:56:19)

Migrate Binance platform to use only DEX Explorer API for transactions and RPC fo the rest calls
`Updated on May 8`
`Before merge`
Update env vars:
`binance.api` => `https://dex.binance.org/api`
`binance.dex` => `binance.explorer` => https://explorer.binance.org/api


Closes https://github.com/trustwallet/blockatlas/issues/1003

Removed code and tests related to unsupported by client type of transactions like `NEW_ORDER`, `CANCEL_ORDER`

TODO
- [x] Use RPC transactions hash endpoint to pull multi-send transfers, this fixed issue when address in multisend was not proceed as a result transfer was not returned.
- [x] Add test to model functions
- [x] Clean code

Fixed:
- [x] Missing transfers in multisend transaction, if requested address was deep in response that was not paginated by default, but assumed all multisend transfers returned in request to explorer.

As was tested RPC is not stable to return address transfers, and for now keep to use Explorer for `transactions only`
Example RPC: https://dex.binance.org/api/v1/transactions?address=bnb14cjy0yl23xkf0hnw3ql295v8nghqstvlzkvqpl&txType=TRANSFER
Example Explorer: https://explorer.binance.org/api/v1/txs?address=bnb14cjy0yl23xkf0hnw3ql295v8nghqstvlzkvqpl&page=1&rows=25&txType=TRANSFER

todo[bot]: ## create and use cache instead query tokens list every time

https://github.com/trustwallet/blockatlas/blob/b49a7da9436114a9d1238f745c90ff28efbc415d/platform/binance/token.go#L39-L44

---

###### This comment was generated by [todo](https://todo.jasonet.co) based on a `TODO` comment in b49a7da9436114a9d1238f745c90ff28efbc415d in #1010. cc @trustwallet.
todo[bot]: ## check for error

https://github.com/trustwallet/blockatlas/blob/a3b17c037056f10b30e4992016641ab7a1552b6c/platform/binance/transaction.go#L68-L73

---

###### This comment was generated by [todo](https://todo.jasonet.co) based on a `TODO` comment in a3b17c037056f10b30e4992016641ab7a1552b6c in #1010. cc @trustwallet.
EnoRage: > Switching from explorer RPC to DEX RPC brings a few disadvantages:
> 
> No direct way to return address transactions including multi-send, but block transactions api supports multi-send (possible talks to Binance to include multi-send)

Is there any other issue? @kolya182 

Is it critical @vikmeup 
vikmeup: @EnoRage should be ok as long as we notify when receiving new transaction in the block and support for multi send will be added later for transactions API
todo[bot]: ## create and use cache instead query tokens list every time

https://github.com/trustwallet/blockatlas/blob/56e4fc7eb4fadb713bf38b0b7bd1546ddb67057a/platform/binance/token.go#L39-L44

---

###### This comment was generated by [todo](https://todo.jasonet.co) based on a `TODO` comment in 56e4fc7eb4fadb713bf38b0b7bd1546ddb67057a in #1010. cc @trustwallet.
todo[bot]: ## create and use cache instead query tokens list every time

https://github.com/trustwallet/blockatlas/blob/d13012140d2e53b8b6c603087737823bf7b774ce/platform/binance/token.go#L39-L44

---

###### This comment was generated by [todo](https://todo.jasonet.co) based on a `TODO` comment in d13012140d2e53b8b6c603087737823bf7b774ce in #1010. cc @trustwallet.
EnoRage: NRY

codecov[bot]: # [Codecov](https://codecov.io/gh/trustwallet/blockatlas/pull/1010?src=pr&el=h1) Report
> :exclamation: No coverage uploaded for pull request base (`master@dffc35b`). [Click here to learn what that means](https://docs.codecov.io/docs/error-reference#section-missing-base-commit).
> The diff coverage is `n/a`.

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

```diff
@@           Coverage Diff            @@
##             master   #1010   +/-   ##
========================================
  Coverage          ?     35%           
========================================
  Files             ?     155           
  Lines             ?    5373           
  Branches          ?       0           
========================================
  Hits              ?    1889           
  Misses            ?    3353           
  Partials          ?     131           
```



------

[Continue to review full report at Codecov](https://codecov.io/gh/trustwallet/blockatlas/pull/1010?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/1010?src=pr&el=footer). Last update [dffc35b...46e7ec5](https://codecov.io/gh/trustwallet/blockatlas/pull/1010?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).

EnoRage: @kolya182 
Find an issue with v2/tokens

http://localhost:8420/v2/binance/tokens/bnb1sj4hr4ll94xsmpuf9s296ufszahg0gsxdjn7d5
https://explorer.binance.org/address/bnb1sj4hr4ll94xsmpuf9s296ufszahg0gsxdjn7d5

http://localhost:8420/v2/binance/tokens/bnb10uetf9rxqxxkc67xf6799pl82gdd2gshwcqnuy
https://explorer.binance.org/address/bnb10uetf9rxqxxkc67xf6799pl82gdd2gshwcqnuy

More examples:
/v2/binance/tokens/bnb1y2akqpljrxmnxmz4qx2s8p7fnvh3euput504w0
/v2/binance/tokens/bnb17h49lval8vu23hrrmjjg64tdwcnl03v4tqepcf
/v2/binance/tokens/bnb1pzs4ugyuhtdg00fpj2waqtrppwa7wm7h83lgzk
/v2/binance/tokens/bnb1ujtqf69mctgcan3l3fgw5pgtxy7a9lqlep6cx8
EnoRage:  @catenocrypt can you please help to fix mocked test? I cannot understand why do we need 
	@$(MAKE) newman-run test=mock-healthcheck host=http://localhost:8437
and empty files
todo[bot]: ## status

https://github.com/trustwallet/blockatlas/blob/e0c4d33d7f1d72158918c6d44faaeccca2355ac4/platform/binance/transaction.go#L83-L88

---

###### This comment was generated by [todo](https://todo.jasonet.co) based on a `TODO` comment in e0c4d33d7f1d72158918c6d44faaeccca2355ac4 in #1010. cc @trustwallet.
todo[bot]: ## add name

https://github.com/trustwallet/blockatlas/blob/e0c4d33d7f1d72158918c6d44faaeccca2355ac4/platform/binance/transaction.go#L126-L131

---

###### This comment was generated by [todo](https://todo.jasonet.co) based on a `TODO` comment in e0c4d33d7f1d72158918c6d44faaeccca2355ac4 in #1010. cc @trustwallet.
catenocrypt: Usage of API, DEX, and RPC should be clarified, it's a total mess now.  3 names used for 2 things, in conflicting way:
```
		rpcClient: Client{blockatlas.InitClient(api)},
		dexClient: DexClient{blockatlas.InitClient(dex)},
```
Here RPC goes with API

```
  api: https://dex.binance.org/api
  dex: https://explorer.binance.org/api
```
Here dex goes with api.


kolya182: @prazd @catenocrypt I made changes based on your suggestions.
@catenocrypt I agree that naming  `rpc` `api` `dex` is confusing. I made simple change for binance platform for `dex` => `explorer` (not touching api which is should be common for all platforms in current implementation, other way it will not start). Lets discuss how we can improve it in next PR's
EnoRage: It is not ready. 

We need to change normalization methods. It is not a good way to:
1) Fetch data to struct A
2) Modify struct A 
3) Normalize it to struct B
4) Normalize it to struct C

It is important to keep as much as possible normalizations.

We need to cover all the client methods as well as normalization methods for different cases + negative cases.

We already found some errors that were not tracked by tests at all or test was incorrect (excepted data was wrong)

I will start to refactor it. I will need some help with tests
EnoRage: @kolya182 can you please cover it with tests and finish before making another commits to atlas, please?
EnoRage: ![Screenshot 2020-05-14 at 22 49 45](https://user-images.githubusercontent.com/22479658/81979217-43042680-9635-11ea-8e9c-9227fa3d67ac.png)
parser issue with metadata
kolya182: > ![Screenshot 2020-05-14 at 22 49 45](https://user-images.githubusercontent.com/22479658/81979217-43042680-9635-11ea-8e9c-9227fa3d67ac.png)
> parser issue with metadata

Can you indignity exact block where it happened ?
kolya182: > It is not ready.
> 
> We need to change normalization methods. It is not a good way to:
> 
> 1. Fetch data to struct A
> 2. Modify struct A
> 3. Normalize it to struct B
> 4. Normalize it to struct C
> 
> It is important to keep as much as possible normalizations.
> 
> We need to cover all the client methods as well as normalization methods for different cases + negative cases.
> 
> We already found some errors that were not tracked by tests at all or test was incorrect (excepted data was wrong)
> 
> I will start to refactor it. I will need some help with tests

Can you be more specific  on `some errors` ?

Patch:
diff --git a/.codacy.yml b/.codacy.yml
deleted file mode 100644
index 4b6a06d..0000000
--- a/.codacy.yml
+++ /dev/null
@@ -1,3 +0,0 @@
----
-exclude_paths:
-  - 'mock/ext-api-dyson/**'
diff --git a/coin/coins.go b/coin/coins.go
index dcebc47..88e22e6 100644
--- a/coin/coins.go
+++ b/coin/coins.go
@@ -1,6 +1,6 @@
 // Code generated by go generate; DO NOT EDIT.
 // This file was generated by robots at
-// 2020-03-19 12:32:14.57052 -0600 MDT m=&#43;0.001450289
+// 2020-05-15 00:06:57.247245 &#43;0300 MSK m=&#43;0.001827650
 // using data from coins.yml
 package coin
 
@@ -243,7 +243,7 @@ var Coins = map[uint]Coin{
 		Name:             "BNB",
 		Decimals:         8,
 		BlockTime:        4000,
-		MinConfirmations: 0,
+		MinConfirmations: 2,
 		SampleAddr:       "tbnb1fhr04azuhcj0dulm7ka40y0cqjlafwae9k9gk2",
 	},
 	VET: {
@@ -557,7 +557,6 @@ var Coins = map[uint]Coin{
 		SampleAddr:       "NEAR6Y66fCzeKqWiwxoPox5oGeDN9VhNCu7CEQ9M86iniqoN9vg2X",
 	},
 }
-
 func Ethereum() Coin {
 	return Coins[ETH]
 }
@@ -702,3 +701,4 @@ func Solana() Coin {
 func Near() Coin {
 	return Coins[NEAR]
 }
+
diff --git a/coin/coins.yml b/coin/coins.yml
index 4379fd1..f1bc5b9 100644
--- a/coin/coins.yml
+++ b/coin/coins.yml
@@ -130,6 +130,7 @@
   name: BNB
   decimals: 8
   blockTime: 4000
+  minConfirmations: 2
   sampleAddress: 'tbnb1fhr04azuhcj0dulm7ka40y0cqjlafwae9k9gk2'
 
 - id: 818
diff --git a/config.yml b/config.yml
index 0cef731..4b4ef8c 100644
--- a/config.yml
+++ b/config.yml
@@ -37,11 +37,10 @@ observer:
 postgres:
   uri: postgresql://user:pass@localhost/my_db?sslmode=disable
 
-# [BNB] Binance DEX: https://wallet.binance.org
-#       Binance Chain: https://explorer.binance.org
+# [BNB] Binance DEX: https://www.binance.org/
 binance:
-  api: https://explorer.binance.org/api/v1
-  dex: https://dex.binance.org/api
+  api: https://dex.binance.org/api
+  explorer: https://explorer.binance.org/api
 
 # [NIM] Nimiq: https://nimiq.com
 #nimiq:
diff --git a/configmock.yml b/configmock.yml
index 757655f..95b934c 100644
--- a/configmock.yml
+++ b/configmock.yml
@@ -33,8 +33,8 @@ postgres:
 # [BNB] Binance DEX: https://wallet.binance.org
 #       Binance Chain: https://explorer.binance.org
 binance:
-  api: http://localhost:3347/binance-api/v1
-  dex: http://localhost:3347/binance-dex
+  api: https://dex.binance.org/api
+  explorer: http://localhost:3347/binance-explorer/api
 
 # [NIM] Nimiq: https://nimiq.com
 nimiq:
diff --git a/mock/ext-api-dyson/get/binance-api-tx.js b/mock/ext-api-dyson/get/binance-api-tx.js
deleted file mode 100644
index 63b0e1f..0000000
--- a/mock/ext-api-dyson/get/binance-api-tx.js
+++ /dev/null
@@ -1,60 +0,0 @@
-/// Binance chain block explorer API Mock, tx
-/// Returns:
-/// - Multi-transaction transaction for a specific address
-///   see http://localhost:3347/binance-api/v1/tx?txHash=F53BB470A3B6B83977CFFE5D5F9937FB1CBB8785FBE818D9B38AD43F3ECD82BC
-///   see https://explorer.binance.org/api/v1/tx?txHash=F53BB470A3B6B83977CFFE5D5F9937FB1CBB8785FBE818D9B38AD43F3ECD82BC
-///   see http://localhost:8437/v1/binance/bnb1563k58pc3keeuwkhlrxwz7sdsetyn9l7gdnznp
-///   see http://localhost:8437/v1/binance/bnb1563k58pc3keeuwkhlrxwz7sdsetyn9l7gdnznp?token=BUSD-BD1
-/// - empty response for other txHash'es
-
-module.exports = {
-    path: '/binance-api/v1/tx',
-    template: function(params, query, body) {
-        if (query['txHash'] == 'F53BB470A3B6B83977CFFE5D5F9937FB1CBB8785FBE818D9B38AD43F3ECD82BC') {
-            return {
-                txHash: "F53BB470A3B6B83977CFFE5D5F9937FB1CBB8785FBE818D9B38AD43F3ECD82BC",
-                blockHeight: Number.parseFrom('63280715'),
-                txType: "TRANSFER",
-                timeStamp: Number.parseFrom('1579688431580'),
-                txFee: Number.parseFrom('0.00060'),
-                txAge: Number.parseFrom('2350509'),
-                code: 0,
-                log: "Msg 0: ",
-                confirmBlocks: 5818526,
-                memo: "Trust Wallet Redeem",
-                source: 0,
-                sequence: 175,
-                hasChildren: 1,
-                subTxsDto: {
-                    totalNum: 2,
-                    pageSize: 15,
-                    subTxDtoList: [
-                        {
-                            hash: "F53BB470A3B6B83977CFFE5D5F9937FB1CBB8785FBE818D9B38AD43F3ECD82BC",
-                            height: Number.parseFrom('63280715'),
-                            type: "TRANSFER",
-                            value: 0.00375,
-                            asset: "BNB",
-                            fromAddr: "bnb1rhv98jcx2yu26shxedskttjzpkvsrz4nd226yv",
-                            toAddr: "bnb1563k58pc3keeuwkhlrxwz7sdsetyn9l7gdnznp",
-                            fee: Number.parseFrom('0.00060')
-                        },
-                        {
-                            hash: "F53BB470A3B6B83977CFFE5D5F9937FB1CBB8785FBE818D9B38AD43F3ECD82BC",
-                            height: Number.parseFrom('63280715'),
-                            type: "TRANSFER",
-                            value: 10.0,
-                            asset: "BUSD-BD1",
-                            fromAddr: "bnb1rhv98jcx2yu26shxedskttjzpkvsrz4nd226yv",
-                            toAddr: "bnb1563k58pc3keeuwkhlrxwz7sdsetyn9l7gdnznp",
-                            fee: null
-                        }
-                    ]
-                }
-            };
-        }
-
-        // not found txHash, return empty response
-        return {}
-    }
-};
diff --git a/mock/ext-api-dyson/get/binance-api-txs.js b/mock/ext-api-dyson/get/binance-api-txs.js
deleted file mode 100644
index 3c0591d..0000000
--- a/mock/ext-api-dyson/get/binance-api-txs.js
+++ /dev/null
@@ -1,86 +0,0 @@
-/// Binance chain block explorer API Mock, txs
-/// Return
-/// - for address 'bnb1563k58pc3keeuwkhlrxwz7sdsetyn9l7gdnznp' 2 txs, one of them multi
-/// - for address 'bnb1mnf0g6zhy2rpy63w8ryc6yp77s0fmqfyzjtkvd' 1 tx
-/// - empty list for other addresses
-/// See:
-/// curl "http://localhost:3347/explorer-api/v1/txs?address=bnb1563k58pc3keeuwkhlrxwz7sdsetyn9l7gdnznp&page=1&rows=20&txAsset=BNB&txType=TRANSFER"
-/// curl "https://explorer.binance.org/api/v1/txs?address=bnb1563k58pc3keeuwkhlrxwz7sdsetyn9l7gdnznp&page=1&rows=20&txAsset=BNB&txType=TRANSFER"
-/// curl "http://localhost:8437/v1/binance/bnb1563k58pc3keeuwkhlrxwz7sdsetyn9l7gdnznp"
-
-module.exports = {
-    path: '/binance-api/v1/txs',
-    template: function(params, query, body) {
-        //console.log(query);
-        var address = query['address'];
-        //console.log('address', address);
-        switch (address) {
-            case 'bnb1563k58pc3keeuwkhlrxwz7sdsetyn9l7gdnznp':
-                return JSON.parse(`{
-                    "txNums": 2,
-                    "txArray": [
-                        {
-                            "txHash": "4A5E688755E3588B89C5F0325274430AA52786E527313739C542BC69436E18F4",
-                            "blockHeight": 63282272,
-                            "txType": "TRANSFER",
-                            "timeStamp": 1579689046296,
-                            "fromAddr": "bnb1563k58pc3keeuwkhlrxwz7sdsetyn9l7gdnznp",
-                            "toAddr": "bnb136ns6lfw4zs5hg4n85vdthaad7hq5m4gtkgf23",
-                            "value": 0.55415460,
-                            "txAsset": "BNB",
-                            "txFee": 0.00037500,
-                            "txAge": 5273327,
-                            "code": 0,
-                            "log": "Msg 0: ",
-                            "confirmBlocks": 0,
-                            "memo": "102101832",
-                            "source": 0,
-                            "hasChildren": 0
-                        },
-                        {
-                            "txHash": "F53BB470A3B6B83977CFFE5D5F9937FB1CBB8785FBE818D9B38AD43F3ECD82BC",
-                            "blockHeight": 63280715,
-                            "txType": "TRANSFER",
-                            "timeStamp": 1579688431580,
-                            "txFee": 0.00060000,
-                            "txAge": 5273941,
-                            "code": 0,
-                            "log": "Msg 0: ",
-                            "confirmBlocks": 0,
-                            "memo": "Trust Wallet Redeem",
-                            "source": 0,
-                            "hasChildren": 1
-                        }
-                    ]
-                }`);
-
-            case 'bnb1mnf0g6zhy2rpy63w8ryc6yp77s0fmqfyzjtkvd':
-                return JSON.parse(`{
-                    "txNums": 1,
-                    "txArray": [
-                        {
-                            "txHash": "DDA939C475755B2A00123CDA37A5EC442F502EA2983014D04F647C3CB9FB57A0",
-                            "blockHeight": 75110907,
-                            "txType": "TRANSFER",
-                            "timeStamp": 1584450870939,
-                            "fromAddr": "bnb166fvwtfra2atta5mm8mygt2fyltktqctgpedcg",
-                            "toAddr": "bnb1mnf0g6zhy2rpy63w8ryc6yp77s0fmqfyzjtkvd",
-                            "value": 0.00037500,
-                            "txAsset": "BNB",
-                            "txFee": 0.00037500,
-                            "txAge": 10170,
-                            "code": 0,
-                            "log": "Msg 0: ",
-                            "confirmBlocks": 0,
-                            "memo": "",
-                            "source": 0,
-                            "hasChildren": 0
-                        }
-                    ]
-                }`);
-        }
-
-        // not found, address
-        return {txNums: 0, txArray: []}
-    }
-};
diff --git a/mock/ext-api-dyson/get/binance-dex-commands2.js b/mock/ext-api-dyson/get/binance-dex-commands2.js
deleted file mode 100644
index 6a7299f..0000000
--- a/mock/ext-api-dyson/get/binance-dex-commands2.js
+++ /dev/null
@@ -1,543 +0,0 @@
-/// Binance chain block explorer API Mock, Dex
-/// See:
-/// curl "http://localhost:3347/binance-dex/v1/account/bnb1jxfh2g85q3v0tdq56fnevx6xcxtcnhtsmcu64m"
-/// curl "http://localhost:3347/binance-dex/v1/tokens?limit=1000&offset=0"
-/// curl "https://dex.binance.org/api/v1/account/bnb1jxfh2g85q3v0tdq56fnevx6xcxtcnhtsmcu64m"
-/// curl "https://dex.binance.org/api/v1/tokens?limit=1000&offset=0"
-/// curl "http://localhost:8437/v2/binance/tokens/bnb1jxfh2g85q3v0tdq56fnevx6xcxtcnhtsmcu64m?Authorization=Bearer"
-
-module.exports = {
-    path: '/binance-dex/:version/:command1/:command2?',
-    template: function(params, query, body) {
-        //console.log(params);
-        //console.log(query);
-        switch (params.version) {
-            case 'v1':
-                switch (params.command1) {
-                    case 'account':
-                        switch (params.command2) {
-                            case 'bnb1jxfh2g85q3v0tdq56fnevx6xcxtcnhtsmcu64m':
-                                return JSON.parse(`
-                                    {
-                                        "account_number": 51,
-                                        "address": "bnb1jxfh2g85q3v0tdq56fnevx6xcxtcnhtsmcu64m",
-                                        "balances": [
-                                            {
-                                                "free": "1732627268.91580163",
-                                                "frozen": "0.00000000",
-                                                "locked": "0.00000000",
-                                                "symbol": "CHZ-ECD"
-                                            },
-                                            {
-                                                "free": "927279.98843502",
-                                                "frozen": "0.00000000",
-                                                "locked": "0.00000000",
-                                                "symbol": "GTO-908"
-                                            },
-                                            {
-                                                "free": "22990392.97970594",
-                                                "frozen": "0.00000000",
-                                                "locked": "0.00000000",
-                                                "symbol": "LBA-340"
-                                            },
-                                            {
-                                                "free": "13504.20603578",
-                                                "frozen": "0.00000000",
-                                                "locked": "0.00000000",
-                                                "symbol": "LTC-F07"
-                                            },
-                                            {
-                                                "free": "1.00000000",
-                                                "frozen": "0.00000000",
-                                                "locked": "0.00000000",
-                                                "symbol": "SLV-986"
-                                            },
-                                            {
-                                                "free": "3400.00000000",
-                                                "frozen": "0.00000000",
-                                                "locked": "0.00000000",
-                                                "symbol": "TWT-8C2"
-                                            },
-                                            {
-                                                "free": "417595410.39908617",
-                                                "frozen": "0.00000000",
-                                                "locked": "0.00000000",
-                                                "symbol": "COS-2E4"
-                                            },
-                                            {
-                                                "free": "8859448.20434497",
-                                                "frozen": "0.00000000",
-                                                "locked": "0.00000000",
-                                                "symbol": "XRP-BF2"
-                                            },
-                                            {
-                                                "free": "66199647.50538896",
-                                                "frozen": "0.00000000",
-                                                "locked": "0.00000000",
-                                                "symbol": "VRAB-B56"
-                                            },
-                                            {
-                                                "free": "565.32000000",
-                                                "frozen": "0.00000000",
-                                                "locked": "0.00000000",
-                                                "symbol": "AERGO-46B"
-                                            },
-                                            {
-                                                "free": "145.00000000",
-                                                "frozen": "0.00000000",
-                                                "locked": "0.00000000",
-                                                "symbol": "ART-3C9"
-                                            },
-                                            {
-                                                "free": "483312.47553546",
-                                                "frozen": "0.00000000",
-                                                "locked": "0.00000000",
-                                                "symbol": "BOLT-4C6"
-                                            },
-                                            {
-                                                "free": "85668472.69714541",
-                                                "frozen": "0.00000000",
-                                                "locked": "0.00000000",
-                                                "symbol": "ERD-D06"
-                                            },
-                                            {
-                                                "free": "372741.55000000",
-                                                "frozen": "0.00000000",
-                                                "locked": "0.00000000",
-                                                "symbol": "MDAB-D42"
-                                            },
-                                            {
-                                                "free": "56343499.10367935",
-                                                "frozen": "0.00000000",
-                                                "locked": "0.00000000",
-                                                "symbol": "ONE-5F9"
-                                            },
-                                            {
-                                                "free": "2000000.00000000",
-                                                "frozen": "0.00000000",
-                                                "locked": "0.00000000",
-                                                "symbol": "BCPT-95A"
-                                            },
-                                            {
-                                                "free": "5.00110000",
-                                                "frozen": "0.00000000",
-                                                "locked": "0.00000000",
-                                                "symbol": "BEAR-14C"
-                                            },
-                                            {
-                                                "free": "2000.00000000",
-                                                "frozen": "0.00000000",
-                                                "locked": "0.00000000",
-                                                "symbol": "GIV-94E"
-                                            },
-                                            {
-                                                "free": "9.44356120",
-                                                "frozen": "0.00000000",
-                                                "locked": "0.00000000",
-                                                "symbol": "NEXO-A84"
-                                            },
-                                            {
-                                                "free": "193182441.20916349",
-                                                "frozen": "0.00000000",
-                                                "locked": "0.00000000",
-                                                "symbol": "UND-EBC"
-                                            },
-                                            {
-                                                "free": "569871.98092216",
-                                                "frozen": "0.00000000",
-                                                "locked": "0.00000000",
-                                                "symbol": "TUSDB-888"
-                                            },
-                                            {
-                                                "free": "316344310.00000000",
-                                                "frozen": "0.00000000",
-                                                "locked": "0.00000000",
-                                                "symbol": "BKRW-AB7"
-                                            },
-                                            {
-                                                "free": "0.00091449",
-                                                "frozen": "0.00000000",
-                                                "locked": "0.00000000",
-                                                "symbol": "EOSBEAR-721"
-                                            },
-                                            {
-                                                "free": "10918.75299816",
-                                                "frozen": "0.00000000",
-                                                "locked": "0.00000000",
-                                                "symbol": "EOSBULL-F0D"
-                                            },
-                                            {
-                                                "free": "296751584.10699693",
-                                                "frozen": "0.00000000",
-                                                "locked": "0.00000000",
-                                                "symbol": "TROY-9B8"
-                                            },
-                                            {
-                                                "free": "450587749.03659246",
-                                                "frozen": "0.00000000",
-                                                "locked": "0.00000000",
-                                                "symbol": "WINB-41F"
-                                            },
-                                            {
-                                                "free": "1438139.59497068",
-                                                "frozen": "0.00000000",
-                                                "locked": "0.00000000",
-                                                "symbol": "ARN-71B"
-                                            },
-                                            {
-                                                "free": "19597996.48343213",
-                                                "frozen": "0.00000000",
-                                                "locked": "0.00000000",
-                                                "symbol": "COTI-CBB"
-                                            },
-                                            {
-                                                "free": "3572612.16675809",
-                                                "frozen": "0.00000000",
-                                                "locked": "0.00000000",
-                                                "symbol": "LTO-BDF"
-                                            },
-                                            {
-                                                "free": "1.22227000",
-                                                "frozen": "0.00000000",
-                                                "locked": "0.00000000",
-                                                "symbol": "XRPBEAR-00B"
-                                            },
-                                            {
-                                                "free": "8619272.37637807",
-                                                "frozen": "0.00000000",
-                                                "locked": "0.00000000",
-                                                "symbol": "CAN-677"
-                                            },
-                                            {
-                                                "free": "338507.95870700",
-                                                "frozen": "0.00000000",
-                                                "locked": "0.00000000",
-                                                "symbol": "HNST-3C9"
-                                            },
-                                            {
-                                                "free": "173741504.28850373",
-                                                "frozen": "0.00000000",
-                                                "locked": "0.00000000",
-                                                "symbol": "BTTB-D31"
-                                            },
-                                            {
-                                                "free": "65500.72562560",
-                                                "frozen": "0.00000000",
-                                                "locked": "0.00000000",
-                                                "symbol": "BUSD-BD1"
-                                            },
-                                            {
-                                                "free": "8549.17210965",
-                                                "frozen": "0.00000000",
-                                                "locked": "0.00000000",
-                                                "symbol": "ETH-1C9"
-                                            },
-                                            {
-                                                "free": "1654100.82380293",
-                                                "frozen": "0.00000000",
-                                                "locked": "0.00000000",
-                                                "symbol": "TOMOB-4BC"
-                                            },
-                                            {
-                                                "free": "5.00455774",
-                                                "frozen": "0.00000000",
-                                                "locked": "0.00000000",
-                                                "symbol": "XRPBULL-E7C"
-                                            },
-                                            {
-                                                "free": "35.00000000",
-                                                "frozen": "0.00000000",
-                                                "locked": "0.00000000",
-                                                "symbol": "AWC-986"
-                                            },
-                                            {
-                                                "free": "1587996.65265528",
-                                                "frozen": "0.00000000",
-                                                "locked": "0.00000000",
-                                                "symbol": "BNB"
-                                            },
-                                            {
-                                                "free": "45605.00637205",
-                                                "frozen": "0.00000000",
-                                                "locked": "0.00000000",
-                                                "symbol": "QARK-FCE"
-                                            },
-                                            {
-                                                "free": "1406863.84448749",
-                                                "frozen": "0.00000000",
-                                                "locked": "0.00000000",
-                                                "symbol": "ARPA-575"
-                                            },
-                                            {
-                                                "free": "1619733.62576473",
-                                                "frozen": "0.00000000",
-                                                "locked": "0.00000000",
-                                                "symbol": "ENTRP-C8D"
-                                            },
-                                            {
-                                                "free": "0.01392000",
-                                                "frozen": "0.00000000",
-                                                "locked": "0.00000000",
-                                                "symbol": "MTXLT-286"
-                                            },
-                                            {
-                                                "free": "2340.58605759",
-                                                "frozen": "0.00000000",
-                                                "locked": "0.00000000",
-                                                "symbol": "BCH-1FD"
-                                            },
-                                            {
-                                                "free": "3.49158551",
-                                                "frozen": "0.00000000",
-                                                "locked": "0.00000000",
-                                                "symbol": "BULL-BE4"
-                                            },
-                                            {
-                                                "free": "1.00000000",
-                                                "frozen": "0.00000000",
-                                                "locked": "0.00000000",
-                                                "symbol": "ECO-083"
-                                            },
-                                            {
-                                                "free": "0.50000000",
-                                                "frozen": "0.00000000",
-                                                "locked": "0.00000000",
-                                                "symbol": "WICC-01D"
-                                            },
-                                            {
-                                                "free": "4235575.51194174",
-                                                "frozen": "0.00000000",
-                                                "locked": "0.00000000",
-                                                "symbol": "KAVA-10C"
-                                            },
-                                            {
-                                                "free": "10.00000000",
-                                                "frozen": "0.00000000",
-                                                "locked": "0.00000000",
-                                                "symbol": "PVT-554"
-                                            },
-                                            {
-                                                "free": "9772.00009772",
-                                                "frozen": "0.00000000",
-                                                "locked": "0.00000000",
-                                                "symbol": "UPX-F3E"
-                                            },
-                                            {
-                                                "free": "221000.60154058",
-                                                "frozen": "0.00000000",
-                                                "locked": "0.00000000",
-                                                "symbol": "USDSB-1AC"
-                                            },
-                                            {
-                                                "free": "4372695.27174854",
-                                                "frozen": "0.00000000",
-                                                "locked": "0.00000000",
-                                                "symbol": "WRX-ED1"
-                                            },
-                                            {
-                                                "free": "19906076.03857030",
-                                                "frozen": "0.00000000",
-                                                "locked": "0.00000000",
-                                                "symbol": "PHB-2DF"
-                                            },
-                                            {
-                                                "free": "12696933.52213685",
-                                                "frozen": "0.00000000",
-                                                "locked": "0.00000000",
-                                                "symbol": "TRXB-2E6"
-                                            },
-                                            {
-                                                "free": "267793524.10892121",
-                                                "frozen": "0.00000000",
-                                                "locked": "0.00000000",
-                                                "symbol": "BLINK-9C6"
-                                            },
-                                            {
-                                                "free": "3370.02600563",
-                                                "frozen": "0.00000000",
-                                                "locked": "0.00000000",
-                                                "symbol": "BTCB-1DE"
-                                            },
-                                            {
-                                                "free": "103467039.59858401",
-                                                "frozen": "0.00000000",
-                                                "locked": "0.00000000",
-                                                "symbol": "CBM-4B2"
-                                            },
-                                            {
-                                                "free": "4095309.32370000",
-                                                "frozen": "0.00000000",
-                                                "locked": "0.00000000",
-                                                "symbol": "DUSK-45E"
-                                            },
-                                            {
-                                                "free": "82964636.96725382",
-                                                "frozen": "0.00000000",
-                                                "locked": "0.00000000",
-                                                "symbol": "FTM-A64"
-                                            },
-                                            {
-                                                "free": "182686435.86912742",
-                                                "frozen": "0.00000000",
-                                                "locked": "0.00000000",
-                                                "symbol": "ANKR-E97"
-                                            },
-                                            {
-                                                "free": "5.00100000",
-                                                "frozen": "0.00000000",
-                                                "locked": "0.00000000",
-                                                "symbol": "ETHBEAR-B2B"
-                                            },
-                                            {
-                                                "free": "0.00872511",
-                                                "frozen": "0.00000000",
-                                                "locked": "0.00000000",
-                                                "symbol": "ETHBULL-D33"
-                                            },
-                                            {
-                                                "free": "39286407.28666093",
-                                                "frozen": "0.00000000",
-                                                "locked": "0.00000000",
-                                                "symbol": "MATIC-84A"
-                                            },
-                                            {
-                                                "free": "20813555.86251786",
-                                                "frozen": "0.00000000",
-                                                "locked": "0.00000000",
-                                                "symbol": "MITH-C76"
-                                            }
-                                        ],
-                                        "flags": 0,
-                                        "public_key": [
-                                            3,
-                                            86,
-                                            224,
-                                            165,
-                                            128,
-                                            56,
-                                            154,
-                                            111,
-                                            210,
-                                            204,
-                                            145,
-                                            205,
-                                            82,
-                                            92,
-                                            109,
-                                            90,
-                                            77,
-                                            128,
-                                            84,
-                                            175,
-                                            112,
-                                            223,
-                                            23,
-                                            72,
-                                            78,
-                                            88,
-                                            103,
-                                            143,
-                                            159,
-                                            87,
-                                            74,
-                                            11,
-                                            77
-                                        ],
-                                        "sequence": 547072
-                                    }
-                                `);
-                        }
-                        break;
-
-                    case 'tokens':
-                        return JSON.parse(`
-                            [
-                                {
-                                    "mintable": true,
-                                    "name": "Africa Stable-Coin",
-                                    "original_symbol": "ABCD",
-                                    "owner": "bnb1ujvzeuft0ezf9fu4u0mk52t8mc7t8geyfkevms",
-                                    "symbol": "ABCD-5D8",
-                                    "total_supply": "3347000.00000000"
-                                },
-                                {
-                                    "mintable": false,
-                                    "name": "Aditus",
-                                    "original_symbol": "ADI",
-                                    "owner": "bnb1djdymfgzknmcsu9dzm9s0uavdszn0cl82z4hps",
-                                    "symbol": "ADI-6BB",
-                                    "total_supply": "750000000.00000000"
-                                },
-                                {
-                                    "mintable": false,
-                                    "name": "Aergo",
-                                    "original_symbol": "AERGO",
-                                    "owner": "bnb1llqhwwwmh878844tm3g8v47k0t7xtnhl4hggjl",
-                                    "symbol": "AERGO-46B",
-                                    "total_supply": "500000000.00000000"
-                                },
-                                {
-                                    "mintable": false,
-                                    "name": "Alaris",
-                                    "original_symbol": "ALA",
-                                    "owner": "bnb1pmdkvw6cquwylr46wcrl82xzmul0y2jpj5cwx7",
-                                    "symbol": "ALA-DCD",
-                                    "total_supply": "60000000.00000000"
-                                },
-                                {
-                                    "mintable": false,
-                                    "name": "ANKR",
-                                    "original_symbol": "ANKR",
-                                    "owner": "bnb1hvg059mkwleum35j6y2qjn4fvmgl7zxtlah4tn",
-                                    "symbol": "ANKR-E97",
-                                    "total_supply": "10000000000.00000000"
-                                },
-                                {
-                                    "mintable": false,
-                                    "name": "Aeron",
-                                    "original_symbol": "ARN",
-                                    "owner": "bnb1dq8ae0ayztqp99peggq5sygzf3n7u2ze4t0jne",
-                                    "symbol": "ARN-71B",
-                                    "total_supply": "20000000.00000000"
-                                },
-                                {
-                                    "mintable": true,
-                                    "name": "ARPA",
-                                    "original_symbol": "ARPA",
-                                    "owner": "bnb1mecnt25u3j9ne7th5av7hqvnmzvyrr7ny8hg8c",
-                                    "symbol": "ARPA-575",
-                                    "total_supply": "12000000.00000000"
-                                },
-                                {
-                                    "mintable": false,
-                                    "name": "Maecenas ART Token",
-                                    "original_symbol": "ART",
-                                    "owner": "bnb13plj9kycvcew5v0achpatnd5l5pacys9h0gu8l",
-                                    "symbol": "ART-3C9",
-                                    "total_supply": "100000000.00000000"
-                                },
-                                {
-                                    "mintable": true,
-                                    "name": "Atlas Protocol",
-                                    "original_symbol": "ATP",
-                                    "owner": "bnb1msw3avv894nlpeu0vn4qlkl0r65a3rp7gtz5hf",
-                                    "symbol": "ATP-38C",
-                                    "total_supply": "40000000.00000000"
-                                },
-                                {
-                                    "mintable": false,
-                                    "name": "Travala.com Token",
-                                    "original_symbol": "AVA",
-                                    "owner": "bnb1dm9c7gccgd07td5r69m50u8fg8danfgqvlhj6c",
-                                    "symbol": "AVA-645",
-                                    "total_supply": "61383832.00000000"
-                                }
-                            ]
-                        `);
-                }
-        }
-
-        // not found, address
-        return {txNums: 0, txArray: []}
-    }
-};
diff --git a/mock/ext-api-dyson/get/binance-rpc-commands2.js b/mock/ext-api-dyson/get/binance-rpc-commands2.js
new file mode 100644
index 0000000..a20a7f4
--- /dev/null
+++ b/mock/ext-api-dyson/get/binance-rpc-commands2.js
@@ -0,0 +1,143 @@
+/// Binance chain RPC Mock
+/// See:
+/// curl "http://localhost:3347/binance-rpc/v1/account/bnb1jeu6gscugy6l2wyatxthkh2hmer4hzevgcmf0q"
+/// curl "http://localhost:3347/binance-rpc/v1/tokens?limit=1000&offset=0"
+/// curl "https://{binance_rpc}/v1/account/bnb1jeu6gscugy6l2wyatxthkh2hmer4hzevgcmf0q"
+/// curl "https://{binance_rpc}/v1/tokens?limit=1000&offset=0"
+/// curl "http://localhost:8437/v2/binance/tokens/bnb1jeu6gscugy6l2wyatxthkh2hmer4hzevgcmf0q?Authorization=Bearer"
+
+module.exports = {
+    path: '/binance-rpc/:version/:command1/:command2?',
+    template: function(params, query, body) {
+        switch (params.version) {
+            case 'v1':
+                switch (params.command1) {
+                    case 'account':
+                        switch (params.command2) {
+                            case 'bnb1jeu6gscugy6l2wyatxthkh2hmer4hzevgcmf0q':
+                                return JSON.parse(`
+                                    {
+                                        "account_number": 273171,
+                                        "address": "bnb1jeu6gscugy6l2wyatxthkh2hmer4hzevgcmf0q",
+                                        "balances": [
+                                            {
+                                                "free": "226.53110295",
+                                                "frozen": "0.00000000",
+                                                "locked": "0.00000000",
+                                                "symbol": "BNB"
+                                            },
+                                            {
+                                                "free": "2623.96917801",
+                                                "frozen": "0.00000000",
+                                                "locked": "0.00000000",
+                                                "symbol": "BUSD-BD1"
+                                            },
+                                            {
+                                                "free": "0.05000000",
+                                                "frozen": "0.00000000",
+                                                "locked": "0.00000000",
+                                                "symbol": "TWT-8C2"
+                                            }
+                                        ],
+                                        "flags": 0,
+                                        "public_key": [
+                                            2, 142, 117
+                                        ],
+                                        "sequence": 75
+                                    }
+                                `);
+                        }
+                        break;
+
+                    case 'tokens':
+                        return JSON.parse(`
+                            [
+                                {
+                                    "mintable": true,
+                                    "name": "Africa Stable-Coin",
+                                    "original_symbol": "ABCD",
+                                    "owner": "bnb1ujvzeuft0ezf9fu4u0mk52t8mc7t8geyfkevms",
+                                    "symbol": "ABCD-5D8",
+                                    "total_supply": "3347000.00000000"
+                                },
+                                {
+                                    "mintable": false,
+                                    "name": "Aditus",
+                                    "original_symbol": "ADI",
+                                    "owner": "bnb1djdymfgzknmcsu9dzm9s0uavdszn0cl82z4hps",
+                                    "symbol": "ADI-6BB",
+                                    "total_supply": "750000000.00000000"
+                                },
+                                {
+                                    "mintable": false,
+                                    "name": "Aergo",
+                                    "original_symbol": "AERGO",
+                                    "owner": "bnb1llqhwwwmh878844tm3g8v47k0t7xtnhl4hggjl",
+                                    "symbol": "AERGO-46B",
+                                    "total_supply": "500000000.00000000"
+                                },
+                                {
+                                    "mintable": false,
+                                    "name": "Alaris",
+                                    "original_symbol": "ALA",
+                                    "owner": "bnb1pmdkvw6cquwylr46wcrl82xzmul0y2jpj5cwx7",
+                                    "symbol": "ALA-DCD",
+                                    "total_supply": "60000000.00000000"
+                                },
+                                {
+                                    "mintable": false,
+                                    "name": "ANKR",
+                                    "original_symbol": "ANKR",
+                                    "owner": "bnb1hvg059mkwleum35j6y2qjn4fvmgl7zxtlah4tn",
+                                    "symbol": "ANKR-E97",
+                                    "total_supply": "10000000000.00000000"
+                                },
+                                {
+                                    "mintable": false,
+                                    "name": "Aeron",
+                                    "original_symbol": "ARN",
+                                    "owner": "bnb1dq8ae0ayztqp99peggq5sygzf3n7u2ze4t0jne",
+                                    "symbol": "ARN-71B",
+                                    "total_supply": "20000000.00000000"
+                                },
+                                {
+                                    "mintable": true,
+                                    "name": "ARPA",
+                                    "original_symbol": "ARPA",
+                                    "owner": "bnb1mecnt25u3j9ne7th5av7hqvnmzvyrr7ny8hg8c",
+                                    "symbol": "ARPA-575",
+                                    "total_supply": "12000000.00000000"
+                                },
+                                {
+                                    "mintable": false,
+                                    "name": "Maecenas ART Token",
+                                    "original_symbol": "ART",
+                                    "owner": "bnb13plj9kycvcew5v0achpatnd5l5pacys9h0gu8l",
+                                    "symbol": "ART-3C9",
+                                    "total_supply": "100000000.00000000"
+                                },
+                                {
+                                    "mintable": true,
+                                    "name": "Atlas Protocol",
+                                    "original_symbol": "ATP",
+                                    "owner": "bnb1msw3avv894nlpeu0vn4qlkl0r65a3rp7gtz5hf",
+                                    "symbol": "ATP-38C",
+                                    "total_supply": "40000000.00000000"
+                                },
+                                {
+                                    "mintable": false,
+                                    "name": "Travala.com Token",
+                                    "original_symbol": "AVA",
+                                    "owner": "bnb1dm9c7gccgd07td5r69m50u8fg8danfgqvlhj6c",
+                                    "symbol": "AVA-645",
+                                    "total_supply": "61383832.00000000"
+                                }
+                            ]
+                        `);
+                }
+        }
+
+        // not found, address
+        return {txNums: 0, txArray: []}
+    }
+};
diff --git a/mock/ext-api-dyson/get/binance-rpc-txs.js b/mock/ext-api-dyson/get/binance-rpc-txs.js
new file mode 100644
index 0000000..5813d3d
--- /dev/null
+++ b/mock/ext-api-dyson/get/binance-rpc-txs.js
@@ -0,0 +1,69 @@
+/// Binance chain block explorer mock transaction
+/// Returns:
+/// - Multi-transaction transaction for a specific address
+///   1. newman calls: http://localhost:8437/v1/binance/bnb1jeu6gscugy6l2wyatxthkh2hmer4hzevgcmf0q
+///   2. Block Atlas calls internally : https://{binance_explorer}/api/v1/txs?address=bnb1jeu6gscugy6l2wyatxthkh2hmer4hzevgcmf0q&page=1&rows=25&txType=TRANSFER
+///   3. Dyson response mock data: http://localhost:3347/binance-explorer/api/v1/txs?address=bnb1jeu6gscugy6l2wyatxthkh2hmer4hzevgcmf0q&page=1&rows=25&txType=TRANSFER
+/// - empty response for other txHash'es
+
+// Example contains each type, BNB transfer, BEP2 transfer, BEP2 transfer as multisend transaction
+module.exports = {
+    path: '/binance-explorer/api/v1/txs',
+    template: function (params, query, body) {
+        return JSON.parse(`{
+    "txNums": 3,
+    "txArray": [
+        {
+            "txHash": "963D8C627DE1E739845C0AC0C0EAC3387B53806C77289ACB8C1653CD6D62C9CC",
+            "blockHeight": 84191249,
+            "txType": "TRANSFER",
+            "timeStamp": 1588086370574,
+            "fromAddr": "bnb14cjy0yl23xkf0hnw3ql295v8nghqstvlzkvqpl",
+            "toAddr": "bnb1mr5f97rx5wnkfcakx9fcpvljmx2s6kwqc08yur",
+            "value": 2800.00000000,
+            "txAsset": "TWT-8C2",
+            "txFee": 0.00037500,
+            "txAge": 446701,
+            "code": 0,
+            "log": "Msg 0: ",
+            "confirmBlocks": 0,
+            "memo": "",
+            "source": 0,
+            "hasChildren": 0
+        },
+        {
+            "txHash": "4577CB3B5B202696E9E0B093A6DA973C7DD9CBC6808DA1326872745C35F3C089",
+            "blockHeight": 84191216,
+            "txType": "TRANSFER",
+            "timeStamp": 1588086357686,
+            "fromAddr": "bnb1mr5f97rx5wnkfcakx9fcpvljmx2s6kwqc08yur",
+            "toAddr": "bnb14cjy0yl23xkf0hnw3ql295v8nghqstvlzkvqpl",
+            "value": 0.00040000,
+            "txAsset": "BNB",
+            "txFee": 0.00037500,
+            "txAge": 446714,
+            "code": 0,
+            "log": "Msg 0: ",
+            "confirmBlocks": 0,
+            "memo": "",
+            "source": 0,
+            "hasChildren": 0
+        },
+        {
+            "txHash": "FAD8C1C5E450BE5E0913B12007AAEACC307F8CFFAFFB0844A9F83155E1235C25",
+            "blockHeight": 80167666,
+            "txType": "TRANSFER",
+            "timeStamp": 1586464452922,
+            "txFee": 0.29970000,
+            "txAge": 2068619,
+            "code": 0,
+            "log": "Msg 0: ",
+            "confirmBlocks": 0,
+            "memo": "",
+            "source": 0,
+            "hasChildren": 1
+        }
+    ]
+}`)
+    }
+};
diff --git a/pkg/blockatlas/marshal.go b/pkg/blockatlas/marshal.go
index 91b9a54..8be4e22 100644
--- a/pkg/blockatlas/marshal.go
+++ b/pkg/blockatlas/marshal.go
@@ -47,7 +47,9 @@ func (t *Tx) UnmarshalJSON(data []byte) error {
 	default:
 		return errors.E("unsupported tx type", errors.Params{"type": t.Type})
 	}
-	if err := json.Unmarshal(raw, t.Meta); err != nil {
+
+	err := json.Unmarshal(raw, t.Meta)
+	if err != nil {
 		return err
 	}
 	return nil
diff --git a/pkg/blockatlas/tx.go b/pkg/blockatlas/tx.go
index e36e141..d0ec8a6 100644
--- a/pkg/blockatlas/tx.go
+++ b/pkg/blockatlas/tx.go
@@ -93,10 +93,9 @@ type (
 		Date int64 `json:"date"`
 		// Height of the block the transaction was included in
 		Block uint64 `json:"block"`
-		// Status of the transaction
+		// Status of the transaction e.g: "completed", "pending", "error"
 		Status Status `json:"status"`
-		// Empty if the transaction was successful,
-		// else error explaining why the transaction failed (optional)
+		// Empty if the transaction "completed" or "pending", else error explaining why the transaction failed (optional)
 		Error string `json:"error,omitempty"`
 		// Transaction nonce or sequence
 		Sequence uint64 `json:"sequence"`
diff --git a/pkg/numbers/number.go b/pkg/numbers/number.go
index c36be11..7ac3208 100644
--- a/pkg/numbers/number.go
+++ b/pkg/numbers/number.go
@@ -32,10 +32,21 @@ func Float64toPrecision(num float64, precision int) float64 {
 	return float64(Round(num*output)) / output
 }
 
+// 0.1010 => "0.101"
 func Float64toString(num float64) string {
 	return strconv.FormatFloat(num, 'f', -1, 64)
 }
 
+// "0.00037500" => 0.000375, "non-string-number" => 0
+func StringNumberToFloat64(str string) (float64,  error) {
+	value, err := strconv.ParseFloat(str, 64)
+	if err != nil {
+		return 0, err
+	} else {
+		return value, nil
+	}
+}
+
 func FromDecimal(dec string) string {
 	v, err := DecimalToSatoshis(dec)
 	if err != nil {
diff --git a/platform/binance/base.go b/platform/binance/base.go
index 55f9fb3..678bf0f 100644
--- a/platform/binance/base.go
+++ b/platform/binance/base.go
@@ -6,18 +6,18 @@ import (
 )
 
 type Platform struct {
-	client    Client
-	dexClient DexClient
+	rpcClient      Client
+	explorerClient ExplorerClient
 }
 
-func Init(api, dex string) *Platform {
-	p := &Platform{
-		client:    Client{blockatlas.InitClient(api)},
-		dexClient: DexClient{blockatlas.InitClient(dex)},
+func Init(rpcApi, explorerApi string) *Platform {
+	p := Platform{
+		rpcClient:      Client{blockatlas.InitClient(rpcApi)},
+		explorerClient: ExplorerClient{blockatlas.InitClient(explorerApi)},
 	}
-	p.client.ErrorHandler = getHTTPError
-	p.dexClient.ErrorHandler = getHTTPError
-	return p
+	p.rpcClient.ErrorHandler = handleHTTPError
+	p.explorerClient.ErrorHandler = handleHTTPError
+	return &p
 }
 
 func (p *Platform) Coin() coin.Coin {
diff --git a/platform/binance/block.go b/platform/binance/block.go
index c4647d8..90b931d 100644
--- a/platform/binance/block.go
+++ b/platform/binance/block.go
@@ -2,38 +2,74 @@ package binance
 
 import (
 	"github.com/trustwallet/blockatlas/pkg/blockatlas"
-	"github.com/trustwallet/blockatlas/pkg/errors"
+	"github.com/trustwallet/blockatlas/pkg/numbers"
+	"time"
 )
 
 func (p *Platform) CurrentBlockNumber() (int64, error) {
-	// No native function to get height in explorer API
-	// Workaround: Request list of blocks
-	// and return number of the newest one
-	list, err := p.client.GetBlockList(1)
+	info, err := p.rpcClient.fetchNodeInfo()
 	if err != nil {
 		return 0, err
 	}
-	if len(list.BlockArray) == 0 {
-		return 0, errors.E("no block descriptor found", errors.TypePlatformApi)
-	}
-	return list.BlockArray[0].BlockHeight, nil
+
+	return info.SyncInfo.LatestBlockHeight, nil
 }
 
 func (p *Platform) GetBlockByNumber(num int64) (*blockatlas.Block, error) {
-	srcTxs, err := p.client.GetBlockByNumber(num)
+	blockTransactions, err := p.rpcClient.fetchBlockTransactions(num)
 	if err != nil {
 		return nil, err
 	}
 
-	var txs blockatlas.TxPage
-	childTxs, err := p.getTxChildChan(srcTxs.Txs)
-	if err == nil {
-		txs = NormalizeTxs(childTxs, "", "")
-	} else {
-		txs = NormalizeTxs(srcTxs.Txs, "", "")
+	explorerTransactions := make([]ExplorerTxs, 0, len(blockTransactions))
+	for _, tx := range blockTransactions {
+		explorerTransactions = append(explorerTransactions, normalizeTxsToExplorer(tx))
+	}
+
+	var normalizedTxs []blockatlas.Tx
+	for _, tx := range explorerTransactions {
+		normalizedTx := normalizeTx(tx, "")
+		if normalizedTx == nil {
+			continue
+		}
+		normalizedTxs = append(normalizedTxs, normalizedTx...)
+	}
+
+	return &blockatlas.Block{Number: num, Txs: normalizedTxs}, nil
+}
+
+func normalizeTxsToExplorer(txV2 TxV2) ExplorerTxs {
+	tx := ExplorerTxs{
+		TxAsset:     txV2.Asset,
+		Code:        txV2.Code,
+		FromAddr:    txV2.FromAddr,
+		TxHash:      txV2.TxHash,
+		Memo:        txV2.Memo,
+		ToAddr:      txV2.ToAddr,
+		TxType:      txV2.Type,
+		BlockHeight: txV2.BlockHeight,
+	}
+
+	if value, err := numbers.StringNumberToFloat64(txV2.Value); err == nil {
+		tx.Value = value
+	}
+	if txV2.Fee == "" && len(txV2.SubTransactions) > 1 {
+		txV2.Fee = txV2.SubTransactions[0].Fee
+	}
+	if fee, err := numbers.StringNumberToFloat64(txV2.Fee); err == nil {
+		tx.TxFee = fee
+	}
+	if len(txV2.SubTransactions) > 0 {
+		tx.HasChildren = 1
+	}
+	if t, err := time.Parse(time.RFC3339, txV2.Timestamp); err == nil {
+		tx.Timestamp = t.Unix()
+	}
+
+	mts := make([]MultiTransfer, len(txV2.SubTransactions))
+	for i, st := range txV2.SubTransactions {
+		mts[i] = MultiTransfer{Amount: st.Value, Asset: st.Asset, From: st.FromAddr, To: st.ToAddr}
 	}
-	return &blockatlas.Block{
-		Number: num,
-		Txs:    txs,
-	}, nil
+	tx.MultisendTransfers = mts
+	return tx
 }
diff --git a/platform/binance/client.go b/platform/binance/client.go
index cd1b2f1..b920034 100644
--- a/platform/binance/client.go
+++ b/platform/binance/client.go
@@ -2,83 +2,70 @@ package binance
 
 import (
 	"encoding/json"
+	"fmt"
 	"github.com/trustwallet/blockatlas/pkg/blockatlas"
 	"github.com/trustwallet/blockatlas/pkg/errors"
 	"github.com/trustwallet/blockatlas/pkg/logger"
 	"net/http"
 	"net/url"
-	"strconv"
+	"time"
 )
 
-// TODO Headers + rate limiting
-
 type Client struct {
 	blockatlas.Request
 }
 
-func (c *Client) GetBlockList(count int) (*BlockList, error) {
-	result := new(BlockList)
-	query := url.Values{"rows": {strconv.Itoa(count)}, "page": {"1"}}
-	err := c.Get(result, "blocks", query)
+const tokensLimit = "1000"
+
+func (c *Client) fetchNodeInfo() (*NodeInfo, error) {
+	result := new(NodeInfo)
+	err := c.Get(result, "v1/node-info", nil)
 	return result, err
 }
 
-func (c *Client) GetBlockByNumber(num int64) (*TxPage, error) {
-	stx := new(TxPage)
-	query := url.Values{
-		"blockHeight": {strconv.FormatInt(num, 10)},
-		// Only first 100 transactions of block returned
-		// Shouldn't be a problem at the current transaction rate
-		"rows": {"100"},
-		"page": {"1"},
-	}
-	err := c.Get(stx, "txs", query)
-	return stx, err
+func (c *Client) fetchBlockTransactions(num int64) ([]TxV2, error) {
+	stx := new(BlockTransactions)
+	err := c.Get(stx, fmt.Sprintf("v2/transactions-in-block/%d", num), nil)
+	return stx.Txs, err
+}
+
+func (c *Client) fetchAccountMetadata(address string) (*Account, error) {
+	var result Account
+	err := c.Get(&result, fmt.Sprintf("v1/account/%s", address), nil)
+	return &result, err
 }
 
-func (c *Client) GetTxsOfAddress(address string, token string) (*TxPage, error) {
-	stx := new(TxPage)
-	query := url.Values{"address": {address}, "rows": {"20"}, "page": {"1"}, "txAsset": {token}, "txType": {"TRANSFER"}}
-	err := c.Get(stx, "txs", query)
-	return stx, err
+func (c *Client) fetchTokens() (*TokenList, error) {
+	stp := new(TokenList)
+	query := url.Values{"limit": {tokensLimit}}
+	err := c.GetWithCache(stp, "v1/tokens", query, time.Minute*1)
+	return stp, err
 }
 
-func (c *Client) GetTx(hash string) (stx Tx, err error) {
-	err = c.Get(&stx, "tx", url.Values{"txHash": {hash}})
-	return
+func (c *Client) fetchTransactionHash(hash string) (*TxHashRPC, error) {
+	var result TxHashRPC
+	err := c.Get(&result, fmt.Sprintf("v1/tx/%s", hash), url.Values{"format": {"json"}})
+	return &result, err
 }
 
-func getHTTPError(res *http.Response, desc string) error {
+func handleHTTPError(res *http.Response, desc string) error {
 	switch res.StatusCode {
 	case http.StatusBadRequest:
-		return getAPIError(res, desc)
+		return handleAPIError(res, desc)
 	case http.StatusNotFound:
 		return blockatlas.ErrNotFound
 	case http.StatusOK:
 		return nil
 	default:
-		return errors.E("getHTTPError error", errors.Params{"status": res.Status})
+		return errors.E("handleHTTPError error", errors.Params{"status": res.Status})
 	}
 }
 
-func getAPIError(res *http.Response, desc string) error {
-	var sErr Error
-	err := json.NewDecoder(res.Body).Decode(&sErr)
-	if err != nil {
-		err = errors.E(err, errors.TypePlatformUnmarshal, errors.Params{"desc": desc})
-		logger.Error(err, "Binance: Failed to decode error response")
-		return blockatlas.ErrSourceConn
-	}
-
-	switch sErr.Message {
-	case "address is not valid":
+func handleAPIError(res *http.Response, desc string) error {
+	var e Error
+	if json.NewDecoder(res.Body).Decode(&e) == nil && e.Message == "address is not valid" {
 		return blockatlas.ErrInvalidAddr
 	}
-
-	logger.Error("Binance: Failed", desc, err, logger.Params{
-		"status":  res.StatusCode,
-		"code":    sErr.Code,
-		"message": sErr.Message,
-	})
+	logger.Error(desc, logger.Params{"status": res.StatusCode, "code": e.Code, "message": e.Message})
 	return blockatlas.ErrSourceConn
 }
diff --git a/platform/binance/dex_client.go b/platform/binance/dex_client.go
deleted file mode 100644
index 094fcde..0000000
--- a/platform/binance/dex_client.go
+++ /dev/null
@@ -1,27 +0,0 @@
-package binance
-
-import (
-	"fmt"
-	"github.com/trustwallet/blockatlas/pkg/blockatlas"
-	"net/url"
-	"time"
-)
-
-// TODO Headers + rate limiting
-
-type DexClient struct {
-	blockatlas.Request
-}
-
-func (c *DexClient) GetAccountMetadata(address string) (account *Account, err error) {
-	path := fmt.Sprintf("v1/account/%s", address)
-	err = c.Get(&account, path, nil)
-	return account, err
-}
-
-func (c *DexClient) GetTokens() (*TokenPage, error) {
-	stp := new(TokenPage)
-	query := url.Values{"limit": {"1000"}, "offset": {"0"}}
-	err := c.GetWithCache(stp, "v1/tokens", query, time.Hour*1)
-	return stp, err
-}
diff --git a/platform/binance/explorer_client.go b/platform/binance/explorer_client.go
new file mode 100644
index 0000000..1c9bce4
--- /dev/null
+++ b/platform/binance/explorer_client.go
@@ -0,0 +1,32 @@
+package binance
+
+import (
+	"github.com/trustwallet/blockatlas/coin"
+	"github.com/trustwallet/blockatlas/pkg/blockatlas"
+	"net/url"
+)
+
+type ExplorerClient struct {
+	blockatlas.Request
+}
+
+const (
+	explorerRows = "25"
+	explorerPage = "1"
+)
+
+func (c *ExplorerClient) getTxsOfAddress(address, token string) (ExplorerResponse, error) {
+	result := new(ExplorerResponse)
+	if token == "" {
+		token = coin.Binance().Symbol
+	}
+	query := url.Values{
+		"address": {address},
+		"rows":    {explorerRows},
+		"page":    {explorerPage},
+		"txType":  {string(TxTransfer)},
+		"txAsset": {token},
+	}
+	err := c.Get(result, "v1/txs", query)
+	return *result, err
+}
diff --git a/platform/binance/model.go b/platform/binance/model.go
index 8523d09..e41446b 100644
--- a/platform/binance/model.go
+++ b/platform/binance/model.go
@@ -1,229 +1,247 @@
 package binance
 
 import (
-	"encoding/json"
 	"fmt"
 	"github.com/trustwallet/blockatlas/coin"
-	"github.com/trustwallet/blockatlas/pkg/errors"
+	"github.com/trustwallet/blockatlas/pkg/blockatlas"
 	"github.com/trustwallet/blockatlas/pkg/numbers"
-	"math"
 	"strconv"
-	"strings"
 )
 
-type Account struct {
-	AccountNumber int       `json:"account_number"`
-	Address       string    `json:"address"`
-	Balances      []Balance `json:"balances"`
-	PublicKey     []byte    `json:"public_key"`
-	Sequence      uint64    `json:"sequence"`
-}
+const (
+	TxTransfer              TxType                  = "TRANSFER"       // e.g: BNB, TWT-8C2
+	SingleTransferOperation ExplorerTransactionType = "singleTransfer" // e.g: BNB, TWT-8C2
+	MultiTransferOperation  ExplorerTransactionType = "multiTransfer"  // e.g [BNB, BNB], [TWT-8C2, TWT-8C2]
+)
 
-type Balance struct {
-	Free   string `json:"free"`
-	Frozen string `json:"frozen"`
-	Locked string `json:"locked"`
-	Symbol string `json:"symbol"`
-}
+type (
+	TxType                  string
+	ExplorerTransactionType string
 
-type Error struct {
-	Code    int64  `json:"code"`
-	Message string `json:"message"`
-}
+	Account struct {
+		AccountNumber int       `json:"account_number"`
+		Address       string    `json:"address"`
+		Balances      []Balance `json:"balances"`
+		PublicKey     []byte    `json:"public_key"`
+		Sequence      uint64    `json:"sequence"`
+	}
 
-type BlockDescriptor struct {
-	BlockHeight int64  `json:"blockHeight"`
-	BlockHash   string `json:"blockHash"`
-	TxNum       int    `json:"txNum"`
-}
+	Balance struct {
+		Free   string `json:"free"`
+		Frozen string `json:"frozen"`
+		Locked string `json:"locked"`
+		Symbol string `json:"symbol"`
+	}
 
-type BlockList struct {
-	BlockArray []BlockDescriptor `json:"blockArray"`
-}
+	Error struct {
+		Code    int64  `json:"code"`
+		Message string `json:"message"`
+	}
 
-type TxType string
+	NodeInfo struct {
+		SyncInfo SyncInfo `json:"sync_info"`
+	}
 
-const (
-	TxTransfer    TxType = "TRANSFER"
-	TxNewOrder    TxType = "NEW_ORDER"
-	TxCancelOrder TxType = "CANCEL_ORDER"
-)
+	SyncInfo struct {
+		LatestBlockHeight int64 `json:"latest_block_height"`
+	}
 
-type Tx struct {
-	BlockHeight   uint64      `json:"blockHeight"`
-	Type          TxType      `json:"txType"`
-	Code          int         `json:"code"`
-	ConfirmBlocks int         `json:"confirmBlocks"`
-	Data          string      `json:"data"`
-	FromAddr      string      `json:"fromAddr"`
-	OrderID       string      `json:"orderId"`
-	Timestamp     int64       `json:"timeStamp"`
-	ToAddr        string      `json:"toAddr"`
-	Age           int64       `json:"txAge"`
-	Asset         string      `json:"txAsset"`
-	Fee           json.Number `json:"txFee"`
-	Hash          string      `json:"txHash"`
-	Value         json.Number `json:"value"`
-	Memo          string      `json:"memo"`
-	HasChildren   int         `json:"hasChildren"`
-	SubTxsDto     SubTxsDto   `json:"subTxsDto"`
-}
+	Transactions struct {
+		Total int  `json:"total"`
+		Txs   []Tx `json:"tx"`
+	}
 
-type SubTxsDto struct {
-	TotalNum     uint   `json:"totalNum"`
-	SubTxDtoList SubTxs `json:"subTxDtoList"`
-}
+	Tx struct {
+		Asset       string `json:"txAsset"`
+		BlockHeight uint64 `json:"blockHeight"`
+		Code        int    `json:"code"`
+		Data        string `json:"data"`
+		Fee         string `json:"txFee"`
+		FromAddr    string `json:"fromAddr"`
+		Memo        string `json:"memo"`
+		OrderID     string `json:"orderId"`
+		Sequence    uint64 `json:"sequence"`
+		Source      int    `json:"source"`
+		Timestamp   string `json:"timeStamp"`
+		ToAddr      string `json:"toAddr"`
+		TxHash      string `json:"txHash"`
+		Type        TxType `json:"txType"`
+		Value       string `json:"value"`
+	}
 
-type SubTx struct {
-	Hash     string      `json:"hash"`
-	Height   uint64      `json:"height"`
-	Type     TxType      `json:"type"`
-	Value    json.Number `json:"value"`
-	Asset    string      `json:"asset"`
-	FromAddr string      `json:"fromAddr"`
-	ToAddr   string      `json:"toAddr"`
-	Fee      json.Number `json:"fee"`
-}
+	BlockTransactions struct {
+		BlockHeight int64  `json:"blockHeight"`
+		Txs         []TxV2 `json:"tx"`
+	}
 
-type SubTxs []SubTx
+	TxV2 struct {
+		Tx
+		OrderID         string  `json:"orderId"`         // Optional. Available when the transaction type is NEW_ORDER
+		SubTransactions []SubTx `json:"subTransactions"` // Optional. Available when the transaction has sub-transactions, such as multi-send transaction or a transaction have multiple assets
+	}
 
-func (subTxs *SubTxs) getTxs() (txs []Tx) {
-	mapTx := map[string]Tx{}
-	for _, subTx := range *subTxs {
-		key := subTx.ToAddr + subTx.Asset
-		tx, ok := mapTx[key]
-		if !ok {
-			mapTx[key] = subTx.toTx()
-			continue
-		}
-		txValue, err := tx.Value.Float64()
-		if err != nil {
-			txValue = 0
-		}
-		subTxValue, err := subTx.Value.Float64()
-		if err != nil {
-			subTxValue = 0
-		}
-		value := numbers.Float64toString(txValue + subTxValue)
-		tx.Value = json.Number(value)
-		mapTx[key] = tx
+	SubTx struct {
+		Asset    string `json:"txAsset"`
+		Height   uint64 `json:"blockHeight"`
+		Fee      string `json:"txFee"`
+		FromAddr string `json:"fromAddr"`
+		Hash     string `json:"txHash"`
+		ToAddr   string `json:"toAddr"`
+		Type     TxType `json:"txType"`
+		Value    string `json:"value"`
 	}
-	for _, tx := range mapTx {
-		txs = append(txs, tx)
+
+	TokenList []Token
+
+	Token struct {
+		Name           string `json:"name"`
+		OriginalSymbol string `json:"original_symbol"`
+		Owner          string `json:"owner"`
+		Symbol         string `json:"symbol"`
+		TotalSupply    string `json:"total_supply"`
 	}
-	return
-}
 
-func (subTx *SubTx) toTx() Tx {
-	return Tx{
-		Hash:        subTx.Hash,
-		BlockHeight: subTx.Height,
-		Type:        TxTransfer,
-		FromAddr:    subTx.FromAddr,
-		ToAddr:      subTx.ToAddr,
-		Asset:       subTx.Asset,
-		Fee:         subTx.Fee,
-		Value:       subTx.Value,
-		HasChildren: 0,
+	// Transaction response from Explorer
+	ExplorerResponse struct {
+		Nums int           `json:"txNums"`
+		Txs  []ExplorerTxs `json:"txArray"`
 	}
-}
 
-func (tx *Tx) containAddress(address string) bool {
-	if len(address) == 0 {
-		return true
+	ExplorerTxs struct {
+		BlockHeight        uint64          `json:"blockHeight"`
+		Code               int             `json:"code"`
+		FromAddr           string          `json:"fromAddr"`
+		HasChildren        int             `json:"hasChildren"`
+		Memo               string          `json:"memo"`
+		MultisendTransfers []MultiTransfer `json:"subTxsDto"` // Not part of response, added from hash info tx for simplifying logic
+		Timestamp          int64           `json:"timeStamp"`
+		ToAddr             string          `json:"toAddr"`
+		TxFee              float64         `json:"txFee"`
+		TxHash             string          `json:"txHash"`
+		TxType             TxType          `json:"txType"`
+		Value              float64         `json:"value"`
+		TxAsset            string          `json:"txAsset"`
 	}
-	if tx.FromAddr == address {
-		return true
+
+	TxHashRPC struct {
+		Hash string   `json:"hash"`
+		Tx   TxHashTx `json:"tx"`
 	}
-	if tx.ToAddr == address {
-		return true
+
+	TxHashTx struct {
+		Value Value `json:"value"`
 	}
-	return false
-}
 
-func (tx *Tx) getFee() string {
-	fee := "0"
-	feeNumber, err := tx.Fee.Float64()
-	if err == nil && feeNumber > 0 {
-		fee = numbers.DecimalExp(string(tx.Fee), 8)
+	Value struct {
+		Msg []Msg `json:"msg"`
 	}
-	return fee
-}
 
-func (tx *Tx) getData() (Data, error) {
-	rawIn := json.RawMessage(tx.Data)
-	b, err := rawIn.MarshalJSON()
-	if err != nil {
-		return Data{}, errors.E(err, "getData MarshalJSON", errors.Params{"data": tx.Data})
+	Msg struct {
+		Value MsgValue `json:"value"`
 	}
 
-	var data Data
-	err = json.Unmarshal(b, &data)
-	if err != nil {
-		return Data{}, errors.E(err, "getData Unmarshal", errors.Params{"data": string(b)})
+	MsgValue struct {
+		Inputs  []Input  `json:"inputs"`
+		Outputs []Output `json:"outputs"`
 	}
 
-	symbols := strings.Split(data.OrderData.Symbol, "_")
-	if len(symbols) < 2 {
-		return data, nil
+	Input struct {
+		Address string `json:"address"`
 	}
 
-	data.OrderData.Base = symbols[0]
-	data.OrderData.Quote = symbols[1]
-	return data, nil
-}
+	Output struct {
+		Address string `json:"address"`
+		Coins   []struct {
+			Amount string `json:"amount"`
+			Denom  string `json:"denom"`
+		} `json:"coins"`
+	}
 
-type Data struct {
-	OrderData OrderData `json:"orderData"`
-}
+	MultiTransfer struct {
+		Amount string `json:"amount"` // Float string ind decimal point
+		Asset  string `json:"asset"`
+		From   string `json:"from"`
+		To     string `json:"to"`
+	}
+)
 
-type OrderData struct {
-	Symbol   string      `json:"symbol"`
-	Base     string      `json:"-"`
-	Quote    string      `json:"-"`
-	Quantity interface{} `json:"quantity"`
-	Price    interface{} `json:"price"`
+func extractMultiTransfers(messages Value) (extracted []MultiTransfer) {
+	for _, msg := range messages.Msg {
+		var tr MultiTransfer
+		tr.From = msg.Value.Inputs[0].Address // Assumed multisend transfer has one input, never seen multiple
+		for _, output := range msg.Value.Outputs {
+			tr.Amount = output.Coins[0].Amount
+			tr.Asset = output.Coins[0].Denom
+			tr.To = output.Address
+
+			extracted = append(extracted, tr)
+		}
+	}
+	return
 }
 
-func (od OrderData) GetVolume() (int64, bool) {
-	price, ok := od.GetPrice()
-	if !ok {
-		return 0, false
+// Get explorer transfer fee converted to decimal expression
+func (tx *Tx) getFee() string {
+	if _, err := strconv.ParseFloat(tx.Fee, 64); err == nil {
+		return numbers.DecimalExp(tx.Fee, int(coin.Binance().Decimals))
 	}
-	quantity, ok := od.GetQuantity()
-	if !ok {
-		return 0, false
+	return "0"
+}
+
+// Converts explorer transfer fee to amount in decimal expression
+func (tx *ExplorerTxs) getDexFee() blockatlas.Amount {
+	if tx.TxFee > 0 {
+		return blockatlas.Amount(numbers.DecimalExp(numbers.Float64toString(tx.TxFee), int(coin.Binance().Decimals)))
+	} else {
+		return blockatlas.Amount(0)
 	}
-	return removeFloatPoint(price * quantity), true
 }
 
-func (od OrderData) GetPrice() (float64, bool) {
-	return convertValue(od.Price)
+// Get Explorer transfer status based on transfer code
+func (tx *ExplorerTxs) getStatus() blockatlas.Status {
+	switch tx.Code {
+	case 0:
+		return blockatlas.StatusCompleted
+	default:
+		return blockatlas.StatusError
+	}
 }
 
-func (od OrderData) GetQuantity() (float64, bool) {
-	return convertValue(od.Quantity)
+func (tx *ExplorerTxs) getDexValue() blockatlas.Amount {
+	val := numbers.DecimalExp(numbers.Float64toString(tx.Value), int(coin.Binance().Decimals))
+	return blockatlas.Amount(val)
 }
 
-type TxPage struct {
-	Nums int  `json:"txNums"`
-	Txs  []Tx `json:"txArray"`
+// Determines transaction status
+func (tx *Tx) getStatus() blockatlas.Status {
+	switch tx.Code {
+	case 0:
+		return blockatlas.StatusCompleted
+	default:
+		return blockatlas.StatusError
+	}
 }
 
-type Token struct {
-	Mintable       bool   `json:"mintable"`
-	Name           string `json:"name"`
-	OriginalSymbol string `json:"original_symbol"`
-	Owner          string `json:"owner"`
-	Symbol         string `json:"symbol"`
-	TotalSupply    string `json:"total_supply"`
+// Get explorer transfer error message if transaction failed
+func (tx *ExplorerTxs) getError() string {
+	switch tx.getStatus() {
+	case blockatlas.StatusCompleted:
+		return ""
+	default:
+		return "error"
+	}
 }
 
-type TokenPage []Token
+func (tx *Tx) containAddress(address string) bool {
+	if len(address) == 0 || tx.FromAddr == address || tx.ToAddr == address {
+		return true
+	}
+	return false
+}
 
 // findToken find a token into a token list
-func (a TokenPage) findToken(symbol string) *Token {
-	for _, t := range a {
+func (page TokenList) findToken(symbol string) *Token {
+	for _, t := range page {
 		if t.Symbol == symbol {
 			return &t
 		}
@@ -240,33 +258,35 @@ func (balance *Balance) isAllZeroBalance() bool {
 		}
 	}
 	return true
-
 }
 
 func (e *Error) Error() string {
 	return fmt.Sprintf("%d: %s", e.Code, e.Message)
 }
 
-func removeFloatPoint(value float64) int64 {
-	bnbCoin := coin.Coins[coin.BNB]
-	pow := math.Pow(10, float64(bnbCoin.Decimals))
-	return int64(value * pow)
+// Determines Explorer transaction direction relatively to address
+func (tx *ExplorerTxs) getDirection(address string) blockatlas.Direction {
+	if address == "" {
+		return ""
+	}
+
+	if tx.FromAddr == address && tx.ToAddr == address {
+		return blockatlas.DirectionSelf
+	}
+	if tx.FromAddr == address && tx.ToAddr != address {
+		return blockatlas.DirectionOutgoing
+	}
+
+	return blockatlas.DirectionIncoming
 }
 
-func convertValue(value interface{}) (float64, bool) {
-	result := 0.0
-	switch v := value.(type) {
-	case float64:
-		result = v
-	case int:
-		result = float64(v)
-	case string:
-		f, err := strconv.ParseFloat(v, 64)
-		if err == nil {
-			result = f
-		}
-	default:
-		return result, false
+// Determines Explorer transaction type
+func (tx *ExplorerTxs) getTransactionType() ExplorerTransactionType {
+	var txType ExplorerTransactionType
+	if tx.HasChildren == 1 {
+		txType = MultiTransferOperation
+	} else {
+		txType = SingleTransferOperation
 	}
-	return result, true
+	return txType
 }
diff --git a/platform/binance/token.go b/platform/binance/token.go
index 0e63334..425d40f 100644
--- a/platform/binance/token.go
+++ b/platform/binance/token.go
@@ -7,50 +7,52 @@ import (
 )
 
 func (p *Platform) GetTokenListByAddress(address string) (blockatlas.TokenPage, error) {
-	account, err := p.dexClient.GetAccountMetadata(address)
+	account, err := p.rpcClient.fetchAccountMetadata(address)
 	if err != nil || len(account.Balances) == 0 {
 		return []blockatlas.Token{}, nil
 	}
-	tokens, err := p.dexClient.GetTokens()
+	tokens, err := p.rpcClient.fetchTokens()
 	if err != nil {
 		return nil, err
 	}
-	return NormalizeTokens(account.Balances, tokens), nil
+	return normalizeTokens(account.Balances, tokens), nil
 }
 
-// NormalizeToken converts a Binance token into the generic model
-func NormalizeToken(srcToken *Balance, tokens *TokenPage) (t blockatlas.Token, ok bool) {
+// NormalizeTxs converts multiple Binance tokens
+func normalizeTokens(srcBalance []Balance, tokens *TokenList) []blockatlas.Token {
+	tokensList := make([]blockatlas.Token, 0, len(srcBalance))
+	for _, srcToken := range srcBalance {
+		token, ok := normalizeToken(&srcToken, tokens)
+		if !ok {
+			continue
+		}
+		tokensList = append(tokensList, token)
+	}
+	return tokensList
+}
+
+// normalizeToken converts a Binance token into the generic model
+func normalizeToken(srcToken *Balance, tokens *TokenList) (blockatlas.Token, bool) {
+	var result blockatlas.Token
 	if srcToken.isAllZeroBalance() {
-		return t, false
+		return result, false
 	}
 
-	tk := tokens.findToken(srcToken.Symbol)
-	if tk == nil {
-		return t, false
+	token := tokens.findToken(srcToken.Symbol)
+	if token == nil {
+		return result, false
 	}
 
-	t = blockatlas.Token{
-		Name:     tk.Name,
-		Symbol:   tk.OriginalSymbol,
-		TokenID:  tk.Symbol,
+	result = blockatlas.Token{
+		Name:     token.Name,
+		Symbol:   token.OriginalSymbol,
+		TokenID:  token.Symbol,
 		Coin:     coin.BNB,
-		Decimals: uint(decimalPlaces(tk.TotalSupply)),
+		Decimals: uint(decimalPlaces(token.TotalSupply)),
 		Type:     blockatlas.TokenTypeBEP2,
 	}
 
-	return t, true
-}
-
-// NormalizeTxs converts multiple Binance tokens
-func NormalizeTokens(srcBalance []Balance, tokens *TokenPage) (tokenPage []blockatlas.Token) {
-	for _, srcToken := range srcBalance {
-		token, ok := NormalizeToken(&srcToken, tokens)
-		if !ok {
-			continue
-		}
-		tokenPage = append(tokenPage, token)
-	}
-	return
+	return result, true
 }
 
 // decimalPlaces count the decimals places.
diff --git a/platform/binance/transaction.go b/platform/binance/transaction.go
index ba8ab21..84581cb 100644
--- a/platform/binance/transaction.go
+++ b/platform/binance/transaction.go
@@ -1,190 +1,200 @@
 package binance
 
 import (
+	"github.com/trustwallet/blockatlas/coin"
 	"github.com/trustwallet/blockatlas/pkg/blockatlas"
-	"github.com/trustwallet/blockatlas/pkg/logger"
 	"github.com/trustwallet/blockatlas/pkg/numbers"
+	"strconv"
 	"strings"
 	"sync"
-
-	"github.com/trustwallet/blockatlas/coin"
 )
 
+const emptyToken = ""
+
 func (p *Platform) GetTxsByAddress(address string) (blockatlas.TxPage, error) {
-	// Endpoint supports queries without token query parameter
-	return p.GetTokenTxsByAddress(address, p.Coin().Symbol)
+	explorerResponse, err := p.GetTokenTxsByAddress(address, emptyToken)
+	if err != nil {
+		return nil, err
+	}
+	return filterTxsByType(explorerResponse, blockatlas.TxTransfer), nil
 }
 
-func (p *Platform) GetTokenTxsByAddress(address string, token string) (blockatlas.TxPage, error) {
-	srcTxs, err := p.client.GetTxsOfAddress(address, token)
+func (p *Platform) GetTokenTxsByAddress(address, token string) (blockatlas.TxPage, error) {
+	explorerResponse, err := p.explorerClient.getTxsOfAddress(address, token)
 	if err != nil {
 		return nil, err
 	}
-	txs, err := p.getTxChildChan(srcTxs.Txs)
+
+	explorerTxs, err := p.addTxDetails(explorerResponse.Txs)
 	if err != nil {
 		return nil, err
 	}
-	return NormalizeTxs(txs, token, address), nil
+
+	return normalizeTxs(explorerTxs, address), nil
 }
 
-// getTxChildChan get all child assets from a tx
-func (p *Platform) getTxChildChan(srcTxs []Tx) ([]Tx, error) {
-	txs := make([]Tx, 0)
-	var wg sync.WaitGroup
-	out := make(chan Tx, len(srcTxs))
-	for _, srcTx := range srcTxs {
-		if srcTx.HasChildren != 1 {
-			// Return the same transaction if doesn't have a child
-			txs = append(txs, srcTx)
+func normalizeTxs(explorerTxs []ExplorerTxs, address string) []blockatlas.Tx {
+	var txs []blockatlas.Tx
+	for _, tx := range explorerTxs {
+		normalizedTxs := normalizeTx(tx, address)
+		if normalizedTxs == nil {
 			continue
 		}
+		txs = append(txs, normalizedTxs...)
+	}
+	return txs
+}
+
+func filterTxsByType(txs []blockatlas.Tx, txType blockatlas.TransactionType) []blockatlas.Tx {
+	var result = make([]blockatlas.Tx, 0, len(txs))
+	for _, tx := range txs {
+		if tx.Type == txType {
+			result = append(result, tx)
+		}
+	}
+	return result
+}
+
+func normalizeTx(srcTx ExplorerTxs, address string) []blockatlas.Tx {
+	explorerTxType := srcTx.getTransactionType()
+	switch explorerTxType {
+	case SingleTransferOperation:
+		return normalizeSingleTransfer(srcTx, address)
+	case MultiTransferOperation:
+		return normalizeMultiTransfer(srcTx, address)
+	default:
+		return nil
+	}
+}
+
+func normalizeSingleTransfer(srcTx ExplorerTxs, address string) blockatlas.TxPage {
+	if srcTx.TxType != TxTransfer {
+		return nil
+	}
+	tx := getBase(srcTx)
+	tx.Direction = srcTx.getDirection(address)
+	bnbCoin := coin.Coins[coin.BNB]
+
+	if srcTx.TxAsset == bnbCoin.Symbol {
+		tx.Type = blockatlas.TxTransfer
+		tx.Meta = blockatlas.Transfer{
+			Decimals: bnbCoin.Decimals,
+			Symbol:   bnbCoin.Symbol,
+			Value:    srcTx.getDexValue(),
+		}
+		return blockatlas.TxPage{tx}
+	}
+
+	if srcTx.TxAsset != "" {
+		tx.Type = blockatlas.TxNativeTokenTransfer
+		tx.Meta = blockatlas.NativeTokenTransfer{
+			Decimals: bnbCoin.Decimals,
+			From:     srcTx.FromAddr,
+			Symbol:   tokenSymbol(srcTx.TxAsset),
+			To:       srcTx.ToAddr,
+			TokenID:  srcTx.TxAsset,
+			Value:    srcTx.getDexValue(),
+		}
+		return blockatlas.TxPage{tx}
+	}
+	return nil
+}
+
+func normalizeMultiTransfer(srcTx ExplorerTxs, address string) []blockatlas.Tx {
+	var txs blockatlas.TxPage
+	for _, t := range srcTx.MultisendTransfers {
+		if t.From == address || t.To == address {
+			srcTx.FromAddr = t.From
+			srcTx.ToAddr = t.To
+			srcTx.TxAsset = t.Asset
+
+			if value, err := strconv.ParseFloat(numbers.ToDecimal(t.Amount, 8), 64); err == nil {
+				srcTx.Value = value
+			}
+
+			if single := normalizeSingleTransfer(srcTx, address); single != nil {
+				txs = append(txs, single...)
+			}
+		}
+	}
+	return txs
+}
+
+func (p *Platform) addTxDetails(txs []ExplorerTxs) ([]ExplorerTxs, error) {
+	var (
+		wg              sync.WaitGroup
+		txsWithDetails  = make([]ExplorerTxs, 0, len(txs))
+		txHashChan      = make(chan TxHashRPC, len(txs))
+		multiSendTxsMap = make(map[string]ExplorerTxs, len(txs))
+	)
+
+	for _, tx := range txs {
+		multiSendTxsMap[tx.TxHash] = tx
+
+		if tx.HasChildren != 1 {
+			continue
+		}
+
 		wg.Add(1)
-		go func(srcTx Tx, out chan Tx, wg *sync.WaitGroup) {
+
+		go func(srcTx ExplorerTxs, txHashChan chan TxHashRPC, wg *sync.WaitGroup) {
 			defer wg.Done()
-			tx, err := p.client.GetTx(srcTx.Hash)
+			txHash, err := p.rpcClient.fetchTransactionHash(srcTx.TxHash)
 			if err != nil {
-				// Return the same transaction if an error occurs
-				out <- srcTx
-				logger.Error("GetTransactionsByBlockChan", err, logger.Params{"hash": srcTx.Hash})
 				return
 			}
-			out <- tx
-		}(srcTx, out, &wg)
+			txHashChan <- *txHash
+		}(tx, txHashChan, &wg)
 	}
+
 	wg.Wait()
-	close(out)
-	for r := range out {
-		txs = append(txs, r)
-	}
-	return txs, nil
-}
+	close(txHashChan)
 
-func normalizeTransfer(tx blockatlas.Tx, srcTx Tx, token, address string) (blockatlas.TxPage, bool) {
-	// Verify if the tx has more them one asset
-	if srcTx.HasChildren == 1 {
-		txs := make(blockatlas.TxPage, 0)
-		// Parse all assets as a transaction
-		for _, subTx := range srcTx.SubTxsDto.SubTxDtoList.getTxs() {
-			// If this is not called from a block observer_test, only get the user txs/assets
-			if !subTx.containAddress(address) {
-				continue
-			}
-			// Recursive call to normalize the tx
-			newTxs, ok := normalizeTransfer(tx, subTx, token, address)
+	for res := range txHashChan {
+		if len(res.Tx.Value.Msg) > 0 {
+			a, ok := multiSendTxsMap[res.Hash]
 			if !ok {
 				continue
 			}
-			txs = append(txs, newTxs...)
-		}
-		if len(txs) == 0 {
-			return txs, false
+			a.MultisendTransfers = extractMultiTransfers(res.Tx.Value)
+			multiSendTxsMap[res.Hash] = a
 		}
-		return txs, true
 	}
 
-	// Verify if this is the same asset we are looking for
-	if len(token) > 0 && srcTx.Asset != token {
-		return blockatlas.TxPage{tx}, false
+	for _, tx := range multiSendTxsMap {
+		txsWithDetails = append(txsWithDetails, tx)
 	}
 
-	tx.From = srcTx.FromAddr
-	tx.To = srcTx.ToAddr
+	return txsWithDetails, nil
+}
 
-	bnbCoin := coin.Coins[coin.BNB]
-	value := numbers.DecimalExp(string(srcTx.Value), 8)
-	if srcTx.Asset == bnbCoin.Symbol {
-		// Condition for native transfer (BNB)
-		tx.Meta = blockatlas.Transfer{
-			Value:    blockatlas.Amount(value),
-			Symbol:   bnbCoin.Symbol,
-			Decimals: bnbCoin.Decimals,
-		}
-		return blockatlas.TxPage{tx}, true
+// Construct base Tx out of explorer transfer using common fields for all type of Blockatlas transfers
+func getBase(srcTx ExplorerTxs) blockatlas.Tx {
+	base := blockatlas.Tx{
+		ID:    srcTx.TxHash,
+		Coin:  coin.BNB,
+		From:  srcTx.FromAddr,
+		Fee:   srcTx.getDexFee(),
+		Date:  srcTx.Timestamp / 1000,
+		Block: srcTx.BlockHeight,
+		Memo:  srcTx.Memo,
+		To:    srcTx.ToAddr,
 	}
 
-	// Condition for native token transfer
-	tx.Meta = blockatlas.NativeTokenTransfer{
-		TokenID:  srcTx.Asset,
-		Symbol:   TokenSymbol(srcTx.Asset),
-		Value:    blockatlas.Amount(value),
-		Decimals: bnbCoin.Decimals,
-		From:     srcTx.FromAddr,
-		To:       srcTx.ToAddr,
+	status := srcTx.getStatus()
+	base.Status = status
+	if status == blockatlas.StatusError {
+		base.Error = srcTx.getError()
 	}
-	return blockatlas.TxPage{tx}, true
-}
 
-// NormalizeTx converts a Binance transaction into the generic model
-func NormalizeTx(srcTx Tx, token, address string) (blockatlas.TxPage, bool) {
-	tx := blockatlas.Tx{
-		ID:     srcTx.Hash,
-		Coin:   coin.BNB,
-		From:   srcTx.FromAddr,
-		To:     srcTx.ToAddr,
-		Fee:    blockatlas.Amount(srcTx.getFee()),
-		Date:   srcTx.Timestamp / 1000,
-		Block:  srcTx.BlockHeight,
-		Status: blockatlas.StatusCompleted,
-		Memo:   srcTx.Memo,
-	}
-
-	switch srcTx.Type {
-	case TxTransfer:
-		return normalizeTransfer(tx, srcTx, token, address)
-	}
-	//case TxCancelOrder, TxNewOrder:
-	//	return tx, false
-	//	dt, err := srcTx.getData()
-	//	if err != nil {
-	//		return tx, false
-	//	}
-	//
-	//	symbol := dt.OrderData.Quote
-	//	if len(token) > 0 && symbol != token {
-	//		return tx, false
-	//	}
-	//
-	//	key := blockatlas.KeyPlaceOrder
-	//	title := blockatlas.KeyTitlePlaceOrder
-	//	if srcTx.Type == TxCancelOrder {
-	//		key = blockatlas.KeyCancelOrder
-	//		title = blockatlas.KeyTitleCancelOrder
-	//	}
-	//	volume, ok := dt.OrderData.GetVolume()
-	//	if ok {
-	//		value = strconv.Itoa(int(volume))
-	//	}
-	//
-	//	tx.Meta = blockatlas.AnyAction{
-	//		Coin:     coin.BNB,
-	//		TokenID:  dt.OrderData.Symbol,
-	//		Symbol:   TokenSymbol(symbol),
-	//		Name:     symbol,
-	//		Value:    blockatlas.Amount(value),
-	//		Decimals: coin.Coins[coin.BNB].Decimals,
-	//		Title:    title,
-	//		Key:      key,
-	//	}
-	//}
-	return blockatlas.TxPage{tx}, false
+	return base
 }
 
-func TokenSymbol(asset string) string {
+// Extract BEP2 token symbol from asset name e.g: TWT-8C2 => TWT
+func tokenSymbol(asset string) string {
 	s := strings.Split(asset, "-")
 	if len(s) > 1 {
 		return s[0]
 	}
 	return asset
 }
-
-// NormalizeTxs converts multiple Binance transactions
-func NormalizeTxs(srcTxs []Tx, token, adress string) (txs []blockatlas.Tx) {
-	for _, srcTx := range srcTxs {
-		tx, ok := NormalizeTx(srcTx, token, adress)
-		if !ok {
-			continue
-		}
-		txs = append(txs, tx...)
-	}
-	return
-}
diff --git a/platform/platform.go b/platform/platform.go
index 287eaa2..7790401 100644
--- a/platform/platform.go
+++ b/platform/platform.go
@@ -76,7 +76,7 @@ func getAllHandlers() blockatlas.Platforms {
 		coin.Aeternity().Handle:    aeternity.Init(GetApiVar(coin.AE)),
 		coin.Solana().Handle:       solana.Init(GetApiVar(coin.SOL)),
 		coin.Tezos().Handle:        tezos.Init(GetApiVar(coin.XTZ), GetRpcVar(coin.XTZ)),
-		coin.Binance().Handle:      binance.Init(GetApiVar(coin.BNB), GetVar("binance.dex")),
+		coin.Binance().Handle:      binance.Init(GetApiVar(coin.BNB), GetVar("binance.explorer")),
 		coin.Zilliqa().Handle:      zilliqa.Init(GetApiVar(coin.ZIL), GetVar("zilliqa.key"), GetRpcVar(coin.ZIL), GetVar("zilliqa.lookup")),
 		coin.Kusama().Handle:       polkadot.Init(coin.KSM, GetApiVar(coin.KSM)),
 		coin.Stellar().Handle:      stellar.Init(coin.XLM, GetApiVar(coin.XLM)),
diff --git a/services/observer/parser/parser.go b/services/observer/parser/parser.go
index 58195f0..6343565 100644
--- a/services/observer/parser/parser.go
+++ b/services/observer/parser/parser.go
@@ -290,7 +290,7 @@ func getBlockByNumberWithRetry(attempts int, sleep time.Duration, getBlockByNumb
 	return r, err
 }
 
-func (t *transactionsBatch) fillBatch(transactions blockatlas.Txs) {
+func (t *transactionsBatch) fillBatch(transactions []blockatlas.Tx) {
 	t.Lock()
 	defer t.Unlock()
 	if len(transactions) == 0 {


Test patch:
diff --git a/pkg/numbers/decimal_test.go b/pkg/numbers/decimal_test.go
index b32ed89..2cfcc29 100644
--- a/pkg/numbers/decimal_test.go
+++ b/pkg/numbers/decimal_test.go
@@ -30,6 +30,7 @@ func TestDecimalExp(t *testing.T) {
 
 	// No-Op
 	assertEquals("0", 300, "0")
+	assertEquals("0", 8, "0")
 	assertEquals("123", 0, "123")
 	assertEquals("0.456", 0, "0.456")
 	assertEquals("123.456", 0, "123.456")
@@ -57,6 +58,7 @@ func TestDecimalExp(t *testing.T) {
 	// Tiny
 	assertEquals("0.001234", -1, "0.0001234")
 	assertEquals("0.001234", 1, "0.01234")
+	assertEquals("0.000375", 8, "37500")
 }
 
 func TestCutZeroFractional(t *testing.T) {
diff --git a/pkg/numbers/number_test.go b/pkg/numbers/number_test.go
index 23d0ce4..5af1964 100644
--- a/pkg/numbers/number_test.go
+++ b/pkg/numbers/number_test.go
@@ -64,4 +64,32 @@ func TestFloat64toString(t *testing.T) {
 	assert.Equal(t, Float64toString(1), "1")
 	assert.Equal(t, Float64toString(1.1), "1.1")
 	assert.Equal(t, Float64toString(1.015), "1.015")
+	assert.Equal(t, Float64toString(2800.00000000), "2800")
+	assert.Equal(t, Float64toString(0.00037500), "0.000375")
+}
+
+func TestStringNumberToFloat64(t *testing.T) {
+	var tests = []struct {
+		stringNumber string
+		expect       float64
+		ecpectErr    bool
+	}{
+		{"0.29970000", 0.2997, false},
+		{"0.00037500", 0.000375, false},
+		{"1.0", 1, false},
+		{"1", 1, false},
+		{"0", 0, false},
+		{"23.12", 23.120, true},
+	}
+
+	for _, tt := range tests {
+		t.Run("", func(t *testing.T) {
+			actual, err := StringNumberToFloat64(tt.stringNumber)
+			if tt.ecpectErr {
+				assert.Nil(t, err)
+			} else {
+				assert.Equal(t, tt.expect, actual)
+			}
+		})
+	}
 }
diff --git a/platform/binance/block_test.go b/platform/binance/block_test.go
new file mode 100644
index 0000000..6baaf37
--- /dev/null
+++ b/platform/binance/block_test.go
@@ -0,0 +1,124 @@
+package binance
+
+import (
+	"encoding/json"
+	"github.com/stretchr/testify/assert"
+	"testing"
+)
+
+const (
+	bnbSingleTransfer = `
+{
+    "blockHeight": 84191216,
+    "tx": [
+        {
+            "txHash": "4577CB3B5B202696E9E0B093A6DA973C7DD9CBC6808DA1326872745C35F3C089",
+            "blockHeight": 84191216,
+            "txType": "TRANSFER",
+            "timeStamp": "2020-04-28T15:05:57.686Z",
+            "fromAddr": "bnb1mr5f97rx5wnkfcakx9fcpvljmx2s6kwqc08yur",
+            "toAddr": "bnb14cjy0yl23xkf0hnw3ql295v8nghqstvlzkvqpl",
+            "value": "0.00040000",
+            "txAsset": "BNB",
+            "txFee": "0.00037500",
+            "code": 0,
+            "data": null,
+            "memo": "",
+            "source": 0,
+            "sequence": 95
+        }
+    ]
+}`
+	bep2MultiTransfer = `
+{
+    "blockHeight": 80167666,
+    "tx": [
+        {
+            "txHash": "FAD8C1C5E450BE5E0913B12007AAEACC307F8CFFAFFB0844A9F83155E1235C25",
+            "blockHeight": 80167666,
+            "txType": "TRANSFER",
+            "timeStamp": "2020-04-09T20:34:12.922Z",
+            "fromAddr": null,
+            "toAddr": null,
+            "value": null,
+            "txAsset": null,
+            "txFee": null,
+            "code": 0,
+            "data": null,
+            "memo": "multisend",
+            "source": 1,
+            "sequence": 72,
+            "subTransactions": [
+                {
+                    "txHash": "FAD8C1C5E450BE5E0913B12007AAEACC307F8CFFAFFB0844A9F83155E1235C25",
+                    "blockHeight": 80167666,
+                    "txType": "TRANSFER",
+                    "fromAddr": "bnb1ds83nt2tz2s9m7kkdcu53t3ccjc07un4xvdld7",
+                    "toAddr": "bnb14cjy0yl23xkf0hnw3ql295v8nghqstvlzkvqpl",
+                    "txAsset": "TWT-8C2",
+                    "txFee": "0.29970000",
+                    "value": "2800.00000000"
+                }
+            ]
+        }
+    ]
+}
+`
+)
+
+var (
+	expectBnbSingleRPCV2TransferResponse = ExplorerTxs{
+		BlockHeight:        84191216,
+		Code:               0,
+		FromAddr:           "bnb1mr5f97rx5wnkfcakx9fcpvljmx2s6kwqc08yur",
+		HasChildren:        0,
+		Memo:               "",
+		MultisendTransfers: []MultiTransfer{},
+		Timestamp:          1588086357,
+		ToAddr:             "bnb14cjy0yl23xkf0hnw3ql295v8nghqstvlzkvqpl",
+		TxFee:              0.000375,
+		TxHash:             "4577CB3B5B202696E9E0B093A6DA973C7DD9CBC6808DA1326872745C35F3C089",
+		TxType:             "TRANSFER",
+		Value:              0.0004,
+		TxAsset:            "BNB",
+	}
+
+	expectBEP2MultiRPCV2TransferResponse = ExplorerTxs{
+		BlockHeight:        80167666,
+		Code:               0,
+		HasChildren:        1,
+		Memo:               "multisend",
+		MultisendTransfers: bep2MultisendTransfer,
+		Timestamp:          1586464452,
+		TxHash:             "FAD8C1C5E450BE5E0913B12007AAEACC307F8CFFAFFB0844A9F83155E1235C25",
+		TxType:             "TRANSFER",
+		Value:              0,
+	}
+
+	sender   = "bnb1ds83nt2tz2s9m7kkdcu53t3ccjc07un4xvdld7"
+	receiver = "bnb14cjy0yl23xkf0hnw3ql295v8nghqstvlzkvqpl"
+
+	bep2MultisendTransfer = []MultiTransfer{
+		{Amount: "2800.00000000", Asset: "TWT-8C2", From: sender, To: receiver},
+	}
+)
+
+func Test_normalizeBlockSubTx(t *testing.T) {
+	tests := []struct {
+		name       string
+		V2Response string
+		expected   ExplorerTxs
+	}{
+		{name: "Normalize single BNB transfer", V2Response: bnbSingleTransfer, expected: expectBnbSingleRPCV2TransferResponse},
+		{name: "Normalize multiple BEP2 transfer", V2Response: bep2MultiTransfer, expected: expectBEP2MultiRPCV2TransferResponse},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			var blockTxs BlockTransactions
+			err := json.Unmarshal([]byte(tt.V2Response), &blockTxs)
+			assert.Nil(t, err)
+			assert.Equal(t, tt.expected, normalizeTxsToExplorer(blockTxs.Txs[0]), "tx don't equal")
+		})
+	}
+}
diff --git a/platform/binance/model_test.go b/platform/binance/model_test.go
index fabaa16..24df6b4 100644
--- a/platform/binance/model_test.go
+++ b/platform/binance/model_test.go
@@ -1,353 +1,205 @@
 package binance
 
 import (
-	"encoding/json"
 	"github.com/stretchr/testify/assert"
-	"sort"
+	"github.com/trustwallet/blockatlas/pkg/blockatlas"
+	"strconv"
 	"testing"
-	"time"
 )
 
-var newOrderDataDst = Data{OrderData: OrderData{
-	Symbol:   "AWC-986_BNB",
-	Base:     "AWC-986",
-	Quote:    "BNB",
-	Quantity: 2.0,
-	Price:    0.00324939,
-}}
-
-var cancelOrderDataDst = Data{OrderData: OrderData{
-	Symbol:   "GTO-908_BNB",
-	Base:     "GTO-908",
-	Quote:    "BNB",
-	Quantity: 1.0,
-	Price:    0.00104716,
-}}
-
-func TestTx_getData(t *testing.T) {
-	tests := []struct {
-		name string
-		Data string
-		want Data
-	}{
-		{
-			"new order",
-			"{\"orderData\":{\"symbol\":\"AWC-986_BNB\",\"orderType\":\"limit\",\"side\":\"buy\",\"price\":0.00324939,\"quantity\":2.00000000,\"timeInForce\":\"GTE\",\"orderId\":\"D13BAF4BD6638FA3AAD6EBCA0E4BEEA73DF4D519-30\"}}",
-			newOrderDataDst,
-		},
-		{
-			"cancel order",
-			"{\"orderData\":{\"symbol\":\"GTO-908_BNB\",\"orderType\":\"limit\",\"side\":\"buy\",\"price\":0.00104716,\"quantity\":1.00000000,\"timeInForce\":\"GTE\",\"orderId\":\"D13BAF4BD6638FA3AAD6EBCA0E4BEEA73DF4D519-28\"}}",
-			cancelOrderDataDst,
-		},
+func Test_isZeroBalance(t *testing.T) {
+	type testZeroStruct struct {
+		name    string
+		balance Balance
+		want    bool
+	}
+	// all combinations of 3 variables with 2 possible value 0 or 1 is 2^3 = 8
+	tests := []testZeroStruct{
+		{"1", Balance{"0.00000000", "0.00000000", "0.00000000", "BNB"}, true},
+		{"2", Balance{"0.00000000", "0", "0.00000001", "BNB"}, false},
+		{"3", Balance{"0.00000000", "0.00000001", "0.00000000", "BNB"}, false},
+		{"4", Balance{"0.00000000", "0.00000001", "0.00000001", "BNB"}, false},
+		{"5", Balance{"0.00000001", "0.00000000", "0.00000000", "BNB"}, false},
+		{"6", Balance{"0.00000001", "0.00000000", "0.00000001", "BNB"}, false},
+		{"7", Balance{"0.00000001", "0.00000001", "0.00000000", "BNB"}, false},
+		{"8", Balance{"0.00000001", "0.00000001", "0.00000001", "BNB"}, false},
+		{"Negative", Balance{"-0.00000001", "0.00000001", "0.00000001", "BNB"}, false},
+		{"Bad others are 0", Balance{"f", "0.0000000", "0.0000000", "BNB"}, false},
+		{"Bad others are not 0", Balance{"f", "0.0000001", "0.0000000", "BNB"}, false},
+		{"Empty others are not 0", Balance{"", "0.00000001", "0.00000001", "BNB"}, false},
+		{"Empty others are 0", Balance{"", "0.00000000", "0.00000000", "BNB"}, false},
+		{"Big", Balance{"9999999999999999999999999999999999999999999999999999999999999999999999999999999999" +
+			"9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999" +
+			"9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999" +
+			"9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999" +
+			"9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999" +
+			"9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999" +
+			"9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999" +
+			"9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999" +
+			"9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999" +
+			"9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999" +
+			"9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999" +
+			"9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999" +
+			"9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999" +
+			"9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999" +
+			"9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999" +
+			"9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999" +
+			"9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999" +
+			"99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999", "0.00000000", "0.00000000", "BNB"}, false},
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
-			tx := &Tx{Data: tt.Data}
-			got, _ := tx.getData()
-			assert.Equal(t, tt.want, got)
+			if got := tt.balance.isAllZeroBalance(); got != tt.want {
+				t.Errorf("isAllZeroBalance() = %v, want %v, name %v", got, tt.want, tt.name)
+			}
 		})
 	}
 }
 
-func TestConvertValue(t *testing.T) {
+//
+
+func TestTx_containAddress(t *testing.T) {
+	type fields struct {
+		FromAddr string
+		ToAddr   string
+	}
 	tests := []struct {
-		name       string
-		value      interface{}
-		wantResult float64
-		wantError  bool
+		name    string
+		fields  fields
+		address string
+		want    bool
 	}{
-		{"test string 1", "9", 9, false},
-		{"test number 1", 9, 9, false},
-		{"test string 2", "9380938973", 9380938973, false},
-		{"test number 2", 9380938973, 9380938973, false},
-		{"test string 3", "0.0000003", 0.0000003, false},
-		{"test number 3", 0.0000003, 0.0000003, false},
-		{"test string 4", "0.44", 0.44, false},
-		{"test number 4", 0.44, 0.44, false},
-		{"test string 5", "3334", 3334, false},
-		{"test number 5", 3334, 3334, false},
-		{"test error", time.Time{}, 3334, true},
+		{"test from address valid", fields{FromAddr: "bnb1nm4n03x00gw0x6v784jzryyp6wxnjaxswr3xm8", ToAddr: "bnb1eff4hzx4lfsun3px5walchdy4vek4n0njcdzyn"}, "bnb1nm4n03x00gw0x6v784jzryyp6wxnjaxswr3xm8", true},
+		{"test to address valid", fields{FromAddr: "bnb1nm4n03x00gw0x6v784jzryyp6wxnjaxswr3xm8", ToAddr: "bnb1eff4hzx4lfsun3px5walchdy4vek4n0njcdzyn"}, "bnb1eff4hzx4lfsun3px5walchdy4vek4n0njcdzyn", true},
+		{"test no address valid", fields{FromAddr: "bnb1nm4n03x00gw0x6v784jzryyp6wxnjaxswr3xm8", ToAddr: "bnb1eff4hzx4lfsun3px5walchdy4vek4n0njcdzyn"}, "tbnb1qxm48ndhmh7su0r7zgwmwkltuqgly57jdf8yf8", false},
+		{"test empty address", fields{FromAddr: "bnb1nm4n03x00gw0x6v784jzryyp6wxnjaxswr3xm8", ToAddr: "bnb1eff4hzx4lfsun3px5walchdy4vek4n0njcdzyn"}, "", true},
+		{"test empty address without from", fields{FromAddr: "", ToAddr: "bnb1eff4hzx4lfsun3px5walchdy4vek4n0njcdzyn"}, "", true},
+		{"test empty address without to", fields{FromAddr: "bnb1nm4n03x00gw0x6v784jzryyp6wxnjaxswr3xm8", ToAddr: ""}, "", true},
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
-			got, ok := convertValue(tt.value)
-			if tt.wantError {
-				assert.False(t, ok)
-				return
+			tx := &Tx{
+				FromAddr: tt.fields.FromAddr,
+				ToAddr:   tt.fields.ToAddr,
+			}
+			if got := tx.containAddress(tt.address); got != tt.want {
+				t.Errorf("containAddress() = %v, want %v", got, tt.want)
 			}
-			assert.True(t, ok)
-			assert.Equal(t, tt.wantResult, got)
 		})
 	}
 }
 
-func Test_removeFloatPoint(t *testing.T) {
+func Test_getFee(t *testing.T) {
 	tests := []struct {
-		name  string
-		value float64
-		want  int64
+		name string
+		fee  string
+		want string
 	}{
-		{"test float 1", 0.0034, 340000},
-		{"test float 2", 0.00000013, 13},
-		{"test float 3", 0.938984, 93898400},
-		{"test float 4", 0.1, 10000000},
-		{"test int 1", 12, 1200000000},
-		{"test int 2", 2333333333, 233333333300000000},
+		{"test empty", "", "0"},
+		{"test error", "test", "0"},
+		{"test float 1", "444.5", "44450000000"},
+		{"test float 2", "0.00000001", "1"},
+		{"test float 3", "0.00037500", "37500"}, // standard transfer fee
+		{"test int", "3", "300000000"},
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
-			if got := removeFloatPoint(tt.value); got != tt.want {
-				t.Errorf("removeFloatPoint() = %v, want %v", got, tt.want)
+			tx := &Tx{Fee: tt.fee}
+			if got := tx.getFee(); got != tt.want {
+				t.Errorf("getFee() = %v, want %v", got, tt.want)
 			}
 		})
 	}
 }
 
-func Test_isZeroBalance(t *testing.T) {
-	type testZeroStruct struct {
-		name    string
-		balance Balance
-		want    bool
-	}
-	// all combinations of 3 variables with 2 possible value 0 or 1 is 2^3 = 8
-	tests := []testZeroStruct{
-		{"1",
-			Balance{"0.00000000", "0.00000000", "0.00000000", "BNB"},
-			true,
-		},
-		{"2",
-			Balance{"0.00000000", "0", "0.00000001", "BNB"},
-			false,
-		},
-		{"3",
-			Balance{"0.00000000", "0.00000001", "0.00000000", "BNB"},
-			false,
-		},
-		{"4",
-			Balance{"0.00000000", "0.00000001", "0.00000001", "BNB"},
-			false,
-		},
-		{"5",
-			Balance{"0.00000001", "0.00000000", "0.00000000", "BNB"},
-			false,
-		},
-		{"6",
-			Balance{"0.00000001", "0.00000000", "0.00000001", "BNB"},
-			false,
-		},
-		{"7",
-			Balance{"0.00000001", "0.00000001", "0.00000000", "BNB"},
-			false,
-		},
-		{"8",
-			Balance{"0.00000001", "0.00000001", "0.00000001", "BNB"},
-			false,
-		},
-		{"Negative",
-			Balance{"-0.00000001", "0.00000001", "0.00000001", "BNB"},
-			false,
-		},
-		{"Bad others are 0",
-			Balance{"f",
-				"0.0000000", "0.0000000", "BNB"},
-			false,
-		},
-		{"Bad others are not 0",
-			Balance{"f",
-				"0.0000001", "0.0000000", "BNB"},
-			false,
-		},
-		{"Empty others are not 0",
-			Balance{"",
-				"0.00000001", "0.00000001", "BNB"},
-			false,
-		},
-		{"Empty others are 0",
-			Balance{"",
-				"0.00000000", "0.00000000", "BNB"},
-			false,
-		},
-		{"Big",
-			Balance{"9999999999999999999999999999999999999999999999999999999999999999999999999999999999" +
-				"9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999" +
-				"9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999" +
-				"9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999" +
-				"9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999" +
-				"9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999" +
-				"9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999" +
-				"9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999" +
-				"9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999" +
-				"9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999" +
-				"9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999" +
-				"9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999" +
-				"9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999" +
-				"9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999" +
-				"9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999" +
-				"9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999" +
-				"9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999" +
-				"99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999",
-				"0.00000000", "0.00000000", "BNB"},
-			false,
-		},
+func Test_getStatus(t *testing.T) {
+	tests := []struct {
+		name   string
+		trx    Tx
+		expect blockatlas.Status
+	}{
+		{"Should have status completed", Tx{Code: 0}, blockatlas.StatusCompleted},
+		{"Should have status error", Tx{Code: 1}, blockatlas.StatusError},
+		{"Should have status error", Tx{Code: -1}, blockatlas.StatusError},
 	}
 	for _, tt := range tests {
-		t.Run(tt.name, func(t *testing.T) {
-			if got := tt.balance.isAllZeroBalance(); got != tt.want {
-				t.Errorf("isAllZeroBalance() = %v, want %v, name %v", got, tt.want, tt.name)
-			}
+		t.Run("", func(t *testing.T) {
+			assert.Equal(t, tt.trx.getStatus(), tt.expect)
 		})
 	}
 }
 
-var (
-	subTxDst = SubTx{
-		Hash:     "C29D822EFBC0C91656D1C5870BA55922F3A72A25BC8415B32D1D1AD0C85142F5",
-		Height:   63591484,
-		Type:     "TRANSFER",
-		Value:    "0.00000001",
-		Asset:    "BNB",
-		FromAddr: "bnb1nm4n03x00gw0x6v784jzryyp6wxnjaxswr3xm8",
-		ToAddr:   "bnb1eff4hzx4lfsun3px5walchdy4vek4n0njcdzyn",
-		Fee:      "0.0006",
-	}
-	subTxTokenDst = SubTx{
-		Hash:     "C29D822EFBC0C91656D1C5870BA55922F3A72A25BC8415B32D1D1AD0C85142F5",
-		Height:   63591485,
-		Type:     "TRANSFER",
-		Value:    "0.000064",
-		Asset:    "AERGO-46B",
-		FromAddr: "bnb1nm4n03x00gw0x6v784jzryyp6wxnjaxswr3xm8",
-		ToAddr:   "bnb1eff4hzx4lfsun3px5walchdy4vek4n0njcdzyn",
-		Fee:      "0.0006",
-	}
-	txDst = Tx{
-		Hash:        "C29D822EFBC0C91656D1C5870BA55922F3A72A25BC8415B32D1D1AD0C85142F5",
-		BlockHeight: 63591484,
-		Type:        "TRANSFER",
-		Value:       "0.00000001",
-		Asset:       "BNB",
-		FromAddr:    "bnb1nm4n03x00gw0x6v784jzryyp6wxnjaxswr3xm8",
-		ToAddr:      "bnb1eff4hzx4lfsun3px5walchdy4vek4n0njcdzyn",
-		Fee:         "0.0006",
-	}
-	txTokenDst = Tx{
-		Hash:        "C29D822EFBC0C91656D1C5870BA55922F3A72A25BC8415B32D1D1AD0C85142F5",
-		BlockHeight: 63591485,
-		Type:        "TRANSFER",
-		Value:       "0.000064",
-		Asset:       "AERGO-46B",
-		FromAddr:    "bnb1nm4n03x00gw0x6v784jzryyp6wxnjaxswr3xm8",
-		ToAddr:      "bnb1eff4hzx4lfsun3px5walchdy4vek4n0njcdzyn",
-		Fee:         "0.0006",
-	}
-)
-
-func TestSubTx_toTx(t *testing.T) {
+func Test_getError(t *testing.T) {
 	tests := []struct {
-		name  string
-		subTx SubTx
-		want  Tx
+		name   string
+		trx    ExplorerTxs
+		expect string
 	}{
-		{"test conversion subTx to Tx", subTxTokenDst,
-			Tx{
-				Hash:        "C29D822EFBC0C91656D1C5870BA55922F3A72A25BC8415B32D1D1AD0C85142F5",
-				BlockHeight: 63591485,
-				Type:        TxTransfer,
-				FromAddr:    "bnb1nm4n03x00gw0x6v784jzryyp6wxnjaxswr3xm8",
-				ToAddr:      "bnb1eff4hzx4lfsun3px5walchdy4vek4n0njcdzyn",
-				Asset:       "AERGO-46B",
-				Fee:         "0.0006",
-				Value:       "0.000064",
-				SubTxsDto:   SubTxsDto{},
-			},
-		},
+		{"Should not have error message", ExplorerTxs{Code: 0}, ""},
+		{"Should have error message", ExplorerTxs{Code: 1}, "error"},
+		{"Should have error message", ExplorerTxs{Code: -1}, "error"},
 	}
 	for _, tt := range tests {
-		t.Run(tt.name, func(t *testing.T) {
-			got := tt.subTx.toTx()
-			assert.Equal(t, tt.want, got, "conversion failed")
+		t.Run("", func(t *testing.T) {
+			assert.Equal(t, tt.trx.getError(), tt.expect)
 		})
 	}
 }
 
-func TestSubTxs_getTxs(t *testing.T) {
-	txDuplicatedTokenDst := txTokenDst
-	txDuplicatedTokenDst.Value = "0.000128"
-	txDuplicatedDst := txDst
-	txDuplicatedDst.Value = "0.00000002"
+func Test_QuantityTransferType(t *testing.T) {
 	tests := []struct {
-		name    string
-		subTxs  SubTxs
-		wantTxs []Tx
+		name   string
+		trx    ExplorerTxs
+		expect ExplorerTransactionType
 	}{
-		{"test empty", SubTxs{}, nil},
-		{"test subTx transfer", SubTxs{subTxDst}, []Tx{txDst}},
-		{"test subTx token transfer", SubTxs{subTxTokenDst}, []Tx{txTokenDst}},
-		{"test subTx and token transfer", SubTxs{subTxDst, subTxTokenDst}, []Tx{txDst, txTokenDst}},
-		{"test duplicate subTx token transfer", SubTxs{subTxTokenDst, subTxTokenDst}, []Tx{txDuplicatedTokenDst}},
-		{"test duplicate subTx", SubTxs{subTxDst, subTxDst}, []Tx{txDuplicatedDst}},
+		{"Should be multi transfer", ExplorerTxs{HasChildren: 1}, MultiTransferOperation},
+		{"Should be single transfer", ExplorerTxs{HasChildren: 0}, SingleTransferOperation},
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
-			gotTxs := tt.subTxs.getTxs()
-			sort.Slice(gotTxs, func(i, j int) bool {
-				return gotTxs[i].BlockHeight < gotTxs[j].BlockHeight
-			})
-			assert.Equal(t, tt.wantTxs, gotTxs, "get txs from subTxs failed")
+			assert.Equal(t, tt.trx.getTransactionType(), tt.expect)
 		})
 	}
 }
 
-func TestTx_containAddress(t *testing.T) {
-	type fields struct {
-		FromAddr string
-		ToAddr   string
-	}
+func TestExplorerTxs_getDirection(t *testing.T) {
+	const (
+		addr1 = "bnb14cjy0yl23xkf0hnw3ql295v8nghqstvlzkvqpl"
+		addr2 = "bnb1mr5f97rx5wnkfcakx9fcpvljmx2s6kwqc08yur"
+	)
+
 	tests := []struct {
 		name    string
-		fields  fields
 		address string
-		want    bool
+		trx     ExplorerTxs
+		expect  blockatlas.Direction
 	}{
-		{"test from address valid", fields{FromAddr: "bnb1nm4n03x00gw0x6v784jzryyp6wxnjaxswr3xm8", ToAddr: "bnb1eff4hzx4lfsun3px5walchdy4vek4n0njcdzyn"}, "bnb1nm4n03x00gw0x6v784jzryyp6wxnjaxswr3xm8", true},
-		{"test to address valid", fields{FromAddr: "bnb1nm4n03x00gw0x6v784jzryyp6wxnjaxswr3xm8", ToAddr: "bnb1eff4hzx4lfsun3px5walchdy4vek4n0njcdzyn"}, "bnb1eff4hzx4lfsun3px5walchdy4vek4n0njcdzyn", true},
-		{"test no address valid", fields{FromAddr: "bnb1nm4n03x00gw0x6v784jzryyp6wxnjaxswr3xm8", ToAddr: "bnb1eff4hzx4lfsun3px5walchdy4vek4n0njcdzyn"}, "tbnb1qxm48ndhmh7su0r7zgwmwkltuqgly57jdf8yf8", false},
-		{"test empty address", fields{FromAddr: "bnb1nm4n03x00gw0x6v784jzryyp6wxnjaxswr3xm8", ToAddr: "bnb1eff4hzx4lfsun3px5walchdy4vek4n0njcdzyn"}, "", true},
-		{"test empty address without from", fields{FromAddr: "", ToAddr: "bnb1eff4hzx4lfsun3px5walchdy4vek4n0njcdzyn"}, "", true},
-		{"test empty address without to", fields{FromAddr: "bnb1nm4n03x00gw0x6v784jzryyp6wxnjaxswr3xm8", ToAddr: ""}, "", true},
+		{"getDirection should be self send", addr1, ExplorerTxs{FromAddr: addr1, ToAddr: addr1}, blockatlas.DirectionSelf},
+		{"getDirection should be incoming", addr1, ExplorerTxs{FromAddr: addr2, ToAddr: addr1}, blockatlas.DirectionIncoming},
+		{"getDirection should be outgoing", addr1, ExplorerTxs{FromAddr: addr1, ToAddr: addr2}, blockatlas.DirectionOutgoing},
+		{"getDirection should be empty", "", ExplorerTxs{FromAddr: addr1, ToAddr: addr2}, blockatlas.Direction("")},
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
-			tx := &Tx{
-				FromAddr: tt.fields.FromAddr,
-				ToAddr:   tt.fields.ToAddr,
-			}
-			if got := tx.containAddress(tt.address); got != tt.want {
-				t.Errorf("containAddress() = %v, want %v", got, tt.want)
-			}
+			assert.Equal(t, tt.trx.getDirection(tt.address), tt.expect)
 		})
 	}
 }
 
-func TestTx_getFee(t *testing.T) {
+func Test_getDexFee(t *testing.T) {
 	tests := []struct {
-		name string
-		fee  json.Number
-		want string
+		name      string
+		trx       ExplorerTxs
+		expectFee blockatlas.Amount
 	}{
-		{"test empty", json.Number(""), "0"},
-		{"test error", json.Number("test"), "0"},
-		{"test float 1", json.Number("444.5"), "44450000000"},
-		{"test float 2", json.Number("0.00000001"), "1"},
-		{"test int", json.Number("3"), "300000000"},
+		{"Should have zero fee", ExplorerTxs{TxFee: 0}, blockatlas.Amount(0)},
+		{"Should have zero fee", ExplorerTxs{TxFee: 0.0}, blockatlas.Amount(0)},
+		{"Should have standard fee", ExplorerTxs{TxFee: 0.00037500}, blockatlas.Amount(strconv.Itoa(37500))},
 	}
 	for _, tt := range tests {
-		t.Run(tt.name, func(t *testing.T) {
-			tx := &Tx{Fee: tt.fee}
-			if got := tx.getFee(); got != tt.want {
-				t.Errorf("getFee() = %v, want %v", got, tt.want)
-			}
+		t.Run("", func(t *testing.T) {
+			fee := tt.trx.getDexFee()
+			assert.Equal(t, fee, tt.expectFee)
 		})
 	}
 }
diff --git a/platform/binance/token_test.go b/platform/binance/token_test.go
index 99106ac..33734c0 100644
--- a/platform/binance/token_test.go
+++ b/platform/binance/token_test.go
@@ -120,11 +120,11 @@ func TestNormalizeToken(t *testing.T) {
 			err := json.Unmarshal([]byte(testToken.apiResponse), &srcToken)
 			assert.Nil(t, err)
 
-			var srcTokens TokenPage
+			var srcTokens TokenList
 			err = json.Unmarshal([]byte(testToken.tokens), &srcTokens)
 			assert.Nil(t, err)
 
-			tk, ok := NormalizeToken(&srcToken, &srcTokens)
+			tk, ok := normalizeToken(&srcToken, &srcTokens)
 			assert.Equal(t, testToken.ok, ok, "token: token could not be normalized")
 			assert.Equal(t, testToken.expected, tk, "token: token don't equal")
 		})
diff --git a/platform/binance/transaction_test.go b/platform/binance/transaction_test.go
index cbe80c7..eb4a8a3 100644
--- a/platform/binance/transaction_test.go
+++ b/platform/binance/transaction_test.go
@@ -3,550 +3,174 @@ package binance
 import (
 	"encoding/json"
 	"github.com/stretchr/testify/assert"
-	"github.com/trustwallet/blockatlas/coin"
 	"github.com/trustwallet/blockatlas/pkg/blockatlas"
 	"testing"
 )
 
 const (
-	transferTransaction = `
-{
-	"blockHeight": 7761368,
-	"code": 0,
-	"confirmBlocks": 2089441,
-	"fromAddr": "tbnb1fhr04azuhcj0dulm7ka40y0cqjlafwae9k9gk2",
-	"hasChildren": 0,
-	"log": "Msg 0: ",
-	"timeStamp": 1555049867552,
-	"toAddr": "tbnb1sylyjw032eajr9cyllp26n04300qzzre38qyv5",
-	"txAge": 836729,
-	"txAsset": "BNB",
-	"txFee": 0.00125,
-	"txHash": "1681EE543FB4B5A628EF21D746E031F018E226D127044A4F9BA5EE2542A44555",
-	"txType": "TRANSFER",
-	"value": 100000,
-	"memo": "test"
-}`
-	tokenTransferTransaction = `
-{
-	"blockHeight": 7928667,
-	"code": 0,
-	"confirmBlocks": 1922024,
-	"fromAddr": "tbnb1ttyn4csghfgyxreu7lmdu3lcplhqhxtzced45a",
-	"hasChildren": 0,
-	"log": "Msg 0: ",
-	"timeStamp": 1555117625829,
-	"toAddr": "tbnb12hlquylu78cjylk5zshxpdj6hf3t0tahwjt3ex",
-	"txAge": 768924,
-	"txAsset": "YLC-D8B",
-	"txFee": 0.00125,
-	"txHash": "95CF63FAA27579A9B6AF84EF8B2DFEAC29627479E9C98E7F5AE4535E213FA4C9",
-	"txType": "TRANSFER",
-	"value": 2.10572645,
-	"memo": "test"
-}`
-	newOrderTransaction = `
-{
-      "txHash": "B0677F3436C1B1661E94D192B84B98AA42AC2485D9808357796EE501CBF794F7",
-      "blockHeight": 10815565,
-      "txType": "NEW_ORDER",
-      "timeStamp": 1559689901929,
-      "fromAddr": "bnb16ya67j7kvw8682kka09qujlw5u7lf4geqef0ku",
-      "value": 0.00649878,
-      "txAsset": "BNB",
-      "txQuoteAsset": "AWC-986",
-      "txFee": 0,
-      "txAge": 14346340,
-      "orderId": "D13BAF4BD6638FA3AAD6EBCA0E4BEEA73DF4D519-30",
-      "data": "{\"orderData\":{\"symbol\":\"BNB_AWC-986\",\"orderType\":\"limit\",\"side\":\"buy\",\"price\":0.00324939,\"quantity\":2.00000000,\"timeInForce\":\"GTE\",\"orderId\":\"D13BAF4BD6638FA3AAD6EBCA0E4BEEA73DF4D519-30\"}}",
-      "code": 0,
-      "log": "Msg 0: ",
-      "confirmBlocks": 0,
-      "memo": "",
-      "source": 0,
-      "hasChildren": 0
-}`
-	cancelOrderTransaction = `
-{
-      "txHash": "F48DE755170C10F4A4C0E6836A708C33EEF9A7144800F25187D5F2349FD15A34",
-      "blockHeight": 10815539,
-      "txType": "CANCEL_ORDER",
-      "timeStamp": 1559689892180,
-      "fromAddr": "bnb16ya67j7kvw8682kka09qujlw5u7lf4geqef0ku",
-      "txFee": 0,
-      "txAge": 14346349,
-      "data": "{\"orderData\":{\"symbol\":\"BNB_GTO-908\",\"orderType\":\"limit\",\"side\":\"buy\",\"price\":0.00104716,\"quantity\":1.00000000,\"timeInForce\":\"GTE\",\"orderId\":\"D13BAF4BD6638FA3AAD6EBCA0E4BEEA73DF4D519-28\"}}",
-      "code": 0,
-      "log": "Msg 0: ",
-      "confirmBlocks": 0,
-      "memo": "",
-      "source": 0,
-      "hasChildren": 0
-}`
-	multipleTx = `
-{
-  "txHash": "0C954A46D5AE90EBF9CB7E6F2EAC0E7C3E8DA2DA94B868962164A3AF9D54BEE8",
-  "blockHeight": 64374278,
-  "txType": "TRANSFER",
-  "timeStamp": 1580128370826,
-  "txFee": 0.0006,
-  "txAge": 222591,
-  "code": 0,
-  "log": "Msg 0: ",
-  "confirmBlocks": 553829,
-  "memo": "",
-  "source": 0,
-  "sequence": 154231,
-  "hasChildren": 1,
-  "subTxsDto": {
-    "totalNum": 2,
-    "pageSize": 15,
-    "subTxDtoList": [
-      {
-        "hash": "0C954A46D5AE90EBF9CB7E6F2EAC0E7C3E8DA2DA94B868962164A3AF9D54BEE8",
-        "height": 64374278,
-        "type": "TRANSFER",
-        "value": 3269,
-        "asset": "AERGO-46B",
-        "fromAddr": "bnb1nm4n03x00gw0x6v784jzryyp6wxnjaxswr3xm8",
-        "toAddr": "bnb1eff4hzx4lfsun3px5walchdy4vek4n0njcdzyn",
-        "fee": 0.0006
-      },
-      {
-        "hash": "0C954A46D5AE90EBF9CB7E6F2EAC0E7C3E8DA2DA94B868962164A3AF9D54BEE8",
-        "height": 64374278,
-        "type": "TRANSFER",
-        "value": 1,
-        "asset": "BNB",
-        "fromAddr": "bnb1nm4n03x00gw0x6v784jzryyp6wxnjaxswr3xm8",
-        "toAddr": "bnb1eff4hzx4lfsun3px5walchdy4vek4n0njcdzyn",
-        "fee": null
-      }
-    ]
-  }
-}`
-	multipleTwiceTx = `
-{
-  "txHash": "C29D822EFBC0C91656D1C5870BA55922F3A72A25BC8415B32D1D1AD0C85142F5",
-  "blockHeight": 63591484,
-  "txType": "TRANSFER",
-  "timeStamp": 1580421001269,
-  "txFee": 0.0006,
-  "txAge": 18773,
-  "code": 0,
-  "log": "Msg 0: ",
-  "confirmBlocks": 38965,
-  "memo": "Trust Wallet Redeem",
-  "source": 0,
-  "sequence": 33,
-  "hasChildren": 1,
-  "subTxsDto": {
-    "totalNum": 2,
-    "pageSize": 15,
-    "subTxDtoList": [
-      {
-        "hash": "C29D822EFBC0C91656D1C5870BA55922F3A72A25BC8415B32D1D1AD0C85142F5",
-        "height": 63591484,
-        "type": "TRANSFER",
-        "value": 1e-8,
-        "asset": "BNB",
-        "fromAddr": "bnb1nm4n03x00gw0x6v784jzryyp6wxnjaxswr3xm8",
-        "toAddr": "bnb1eff4hzx4lfsun3px5walchdy4vek4n0njcdzyn",
-        "fee": 0.0006
-      },
-      {
-        "hash": "C29D822EFBC0C91656D1C5870BA55922F3A72A25BC8415B32D1D1AD0C85142F5",
-        "height": 63591484,
-        "type": "TRANSFER",
-        "value": 1e-8,
-        "asset": "BNB",
-        "fromAddr": "bnb1nm4n03x00gw0x6v784jzryyp6wxnjaxswr3xm8",
-        "toAddr": "bnb1eff4hzx4lfsun3px5walchdy4vek4n0njcdzyn",
-        "fee": null
-      }
-    ]
-  }
-}`
+	addr1 = "bnb13a7gyv5zl57c0rzeu0henx6d0tzspvrrakxxtv"
+	addr2 = "bnb1t6tnm2rckd3pfptngj6u8466v3ah4fcdu78n5y"
+)
+
+const (
+	bnbSingleExplorerTransferResponse = `
+        {
+            "txHash": "73176E5BFA5856AEAB9BAB1F3030E6F2B2F274324052E84562BE9BE70E1AAEE7",
+            "blockHeight": 74821444,
+            "txType": "TRANSFER",
+            "timeStamp": 1588086370574,
+            "fromAddr": "bnb13a7gyv5zl57c0rzeu0henx6d0tzspvrrakxxtv",
+            "toAddr": "bnb1t6tnm2rckd3pfptngj6u8466v3ah4fcdu78n5y",
+            "value": 10.00000000,
+            "txAsset": "BNB",
+            "txFee": 0.00037500,
+            "txAge": 1868055,
+            "code": 0,
+			"log": "Msg 0: ",
+            "confirmBlocks": 0,
+			"memo": "bnb-transfer",
+			"source": 1,
+            "hasChildren": 0
+        }`
+
+	bep2SingleExplorerTransferResponse = `
+		{
+            "txHash": "73176E5BFA5856AEAB9BAB1F3030E6F2B2F274324052E84562BE9BE70E1AAEE7",
+            "blockHeight": 74821444,
+            "txType": "TRANSFER",
+            "timeStamp": 1588086357686,
+            "fromAddr": "bnb13a7gyv5zl57c0rzeu0henx6d0tzspvrrakxxtv",
+            "toAddr": "bnb1t6tnm2rckd3pfptngj6u8466v3ah4fcdu78n5y",
+            "value": 2800.00000000,
+            "txAsset": "TWT-8C2",
+            "txFee": 0.00037500,
+            "txAge": 276251,
+            "code": 0,
+            "log": "Msg 0: ",
+            "confirmBlocks": 0,
+            "memo": "bep2-transfer",
+            "source": 0,
+            "hasChildren": 0
+        }`
+	bep2MultipleExplorerTransferResponse = `
+		{
+  			"txHash": "73176E5BFA5856AEAB9BAB1F3030E6F2B2F274324052E84562BE9BE70E1AAEE7",
+  			"blockHeight": 74821444,
+  			"txType": "TRANSFER",
+  			"timeStamp": 1588086357686,
+  			"txFee": 0.00037500,
+  			"txAge": 2068619,
+  			"code": 0,
+  			"log": "Msg 0: ",
+  			"confirmBlocks": 0,
+ 			"memo": "bep2-transfer",
+  			"source": 0,
+  			"hasChildren": 1,
+  			"subTxsDto": [
+   			 {
+      			"amount": "280000000000",
+      			"asset": "TWT-8C2",
+      			"from": "bnb13a7gyv5zl57c0rzeu0henx6d0tzspvrrakxxtv",
+      			"to": "bnb1t6tnm2rckd3pfptngj6u8466v3ah4fcdu78n5y"
+  			 }
+  			 ]
+		}`
 )
 
 var (
-	transferDst = blockatlas.Tx{
-		ID:     "1681EE543FB4B5A628EF21D746E031F018E226D127044A4F9BA5EE2542A44555",
-		Coin:   coin.BNB,
-		From:   "tbnb1fhr04azuhcj0dulm7ka40y0cqjlafwae9k9gk2",
-		To:     "tbnb1sylyjw032eajr9cyllp26n04300qzzre38qyv5",
-		Fee:    "125000",
-		Date:   1555049867,
-		Block:  7761368,
-		Status: blockatlas.StatusCompleted,
-		Memo:   "test",
+	expectBnbSingleExplorerTransfer = blockatlas.Tx{
+		ID:        "73176E5BFA5856AEAB9BAB1F3030E6F2B2F274324052E84562BE9BE70E1AAEE7",
+		Coin:      714,
+		From:      addr1,
+		To:        addr2,
+		Fee:       "37500",
+		Date:      1588086370,
+		Block:     74821444,
+		Status:    blockatlas.StatusCompleted,
+		Error:     "",
+		Sequence:  0,
+		Type:      blockatlas.TxTransfer,
+		Direction: blockatlas.DirectionOutgoing,
+		Memo:      "bnb-transfer",
 		Meta: blockatlas.Transfer{
-			Value:    "10000000000000",
-			Decimals: 8,
+			Value:    "1000000000",
 			Symbol:   "BNB",
-		},
-	}
-	tokenTransferDst = blockatlas.Tx{
-		ID:     "95CF63FAA27579A9B6AF84EF8B2DFEAC29627479E9C98E7F5AE4535E213FA4C9",
-		Coin:   coin.BNB,
-		From:   "tbnb1ttyn4csghfgyxreu7lmdu3lcplhqhxtzced45a",
-		To:     "tbnb12hlquylu78cjylk5zshxpdj6hf3t0tahwjt3ex",
-		Fee:    "125000",
-		Date:   1555117625,
-		Block:  7928667,
-		Status: blockatlas.StatusCompleted,
-		Memo:   "test",
-		Meta: blockatlas.NativeTokenTransfer{
-			TokenID:  "YLC-D8B",
-			Symbol:   "YLC",
-			Value:    "210572645",
 			Decimals: 8,
-			From:     "tbnb1ttyn4csghfgyxreu7lmdu3lcplhqhxtzced45a",
-			To:       "tbnb12hlquylu78cjylk5zshxpdj6hf3t0tahwjt3ex",
 		},
 	}
-	newOrderTransferDst = blockatlas.Tx{
-		ID:     "B0677F3436C1B1661E94D192B84B98AA42AC2485D9808357796EE501CBF794F7",
-		Coin:   coin.BNB,
-		From:   "bnb16ya67j7kvw8682kka09qujlw5u7lf4geqef0ku",
-		Fee:    "0",
-		Date:   1559689901,
-		Block:  10815565,
-		Status: blockatlas.StatusCompleted,
-		Meta: blockatlas.AnyAction{
-			Coin:     coin.BNB,
-			Title:    blockatlas.KeyTitlePlaceOrder,
-			Key:      blockatlas.KeyPlaceOrder,
-			TokenID:  "BNB_AWC-986",
-			Name:     "AWC-986",
-			Symbol:   "AWC",
-			Value:    "649878",
-			Decimals: 8,
-		},
-	}
-	//TODO: temp test dst
-	metaFreeNewOrderTransferDst = blockatlas.Tx{
-		ID:     "B0677F3436C1B1661E94D192B84B98AA42AC2485D9808357796EE501CBF794F7",
-		Coin:   coin.BNB,
-		From:   "bnb16ya67j7kvw8682kka09qujlw5u7lf4geqef0ku",
-		Fee:    "0",
-		Date:   1559689901,
-		Block:  10815565,
-		Status: blockatlas.StatusCompleted,
-		Meta:   nil,
-	}
-	cancelOrdeTransferDst = blockatlas.Tx{
-		ID:     "F48DE755170C10F4A4C0E6836A708C33EEF9A7144800F25187D5F2349FD15A34",
-		Coin:   coin.BNB,
-		From:   "bnb16ya67j7kvw8682kka09qujlw5u7lf4geqef0ku",
-		Fee:    "0",
-		Date:   1559689892,
-		Block:  10815539,
-		Status: blockatlas.StatusCompleted,
-		Meta: blockatlas.AnyAction{
-			Coin:     coin.BNB,
-			Title:    blockatlas.KeyTitleCancelOrder,
-			Key:      blockatlas.KeyCancelOrder,
-			TokenID:  "BNB_GTO-908",
-			Name:     "GTO-908",
-			Symbol:   "GTO",
-			Value:    "104716",
-			Decimals: 8,
-		},
-	}
-	multipleTxDst = blockatlas.Tx{
-		ID:     "0C954A46D5AE90EBF9CB7E6F2EAC0E7C3E8DA2DA94B868962164A3AF9D54BEE8",
-		Coin:   coin.BNB,
-		From:   "bnb1nm4n03x00gw0x6v784jzryyp6wxnjaxswr3xm8",
-		To:     "bnb1eff4hzx4lfsun3px5walchdy4vek4n0njcdzyn",
-		Fee:    "60000",
-		Date:   1580128370,
-		Block:  64374278,
-		Status: blockatlas.StatusCompleted,
+
+	expectBEP2SingleExplorerTransfer = blockatlas.Tx{
+		ID:        "73176E5BFA5856AEAB9BAB1F3030E6F2B2F274324052E84562BE9BE70E1AAEE7",
+		Coin:      714,
+		From:      addr1,
+		To:        addr2,
+		Fee:       "37500",
+		Date:      1588086357,
+		Block:     74821444,
+		Status:    blockatlas.StatusCompleted,
+		Error:     "",
+		Sequence:  0,
+		Type:      blockatlas.TxNativeTokenTransfer,
+		Direction: blockatlas.DirectionIncoming,
+		Memo:      "bep2-transfer",
 		Meta: blockatlas.NativeTokenTransfer{
-			From:     "bnb1nm4n03x00gw0x6v784jzryyp6wxnjaxswr3xm8",
-			To:       "bnb1eff4hzx4lfsun3px5walchdy4vek4n0njcdzyn",
-			TokenID:  "AERGO-46B",
-			Symbol:   "AERGO",
-			Value:    "326900000000",
-			Decimals: 8,
-		},
-	}
-	multipleTwiceTxDst = blockatlas.Tx{
-		ID:     "C29D822EFBC0C91656D1C5870BA55922F3A72A25BC8415B32D1D1AD0C85142F5",
-		Coin:   coin.BNB,
-		From:   "bnb1nm4n03x00gw0x6v784jzryyp6wxnjaxswr3xm8",
-		To:     "bnb1eff4hzx4lfsun3px5walchdy4vek4n0njcdzyn",
-		Fee:    "60000",
-		Date:   1580421001,
-		Block:  63591484,
-		Status: blockatlas.StatusCompleted,
-		Memo:   "Trust Wallet Redeem",
-		Meta: blockatlas.Transfer{
-			Value:    "2",
-			Decimals: 8,
-			Symbol:   "BNB",
-		},
-	}
-	//TODO: temp test dst
-	metaFreeCancelOrdeTransferDst = blockatlas.Tx{
-		ID:     "F48DE755170C10F4A4C0E6836A708C33EEF9A7144800F25187D5F2349FD15A34",
-		Coin:   coin.BNB,
-		From:   "bnb16ya67j7kvw8682kka09qujlw5u7lf4geqef0ku",
-		Fee:    "0",
-		Date:   1559689892,
-		Block:  10815539,
-		Status: blockatlas.StatusCompleted,
-		Meta:   nil,
-	}
-	baseTransferTx = blockatlas.Tx{
-		ID:     "0C954A46D5AE90EBF9CB7E6F2EAC0E7C3E8DA2DA94B868962164A3AF9D54BEE8",
-		Coin:   coin.BNB,
-		From:   "bnb1nm4n03x00gw0x6v784jzryyp6wxnjaxswr3xm8",
-		To:     "bnb1eff4hzx4lfsun3px5walchdy4vek4n0njcdzyn",
-		Fee:    "60000",
-		Date:   1580128370,
-		Block:  63591484,
-		Status: blockatlas.StatusCompleted,
-		Memo:   "Trust Wallet Redeem",
-		Meta: blockatlas.Transfer{
-			Value:    "2",
 			Decimals: 8,
-			Symbol:   "BNB",
+			From:     addr1,
+			Name:     "",
+			Symbol:   "TWT",
+			To:       addr2,
+			TokenID:  "TWT-8C2",
+			Value:    "280000000000",
 		},
 	}
 )
 
-type testTx struct {
-	name        string
-	apiResponse string
-	expected    blockatlas.Tx
-	token       string
-	wantError   bool
-}
-
-func TestNormalizeTx(t *testing.T) {
-	testTxList := []testTx{
-		{
-			name:        "bnb transfer",
-			apiResponse: transferTransaction,
-			expected:    transferDst,
-			token:       "BNB",
-			wantError:   false,
-		},
-		{
-			name:        "native token transfer",
-			apiResponse: tokenTransferTransaction,
-			expected:    tokenTransferDst,
-			token:       "YLC-D8B",
-			wantError:   false,
-		},
-		{
-			name:        "multiple addresses token transfer",
-			apiResponse: multipleTx,
-			expected:    multipleTxDst,
-			token:       "AERGO-46B",
-			wantError:   false,
-		},
-		{
-			name:        "multiple addresses with two transfers",
-			apiResponse: multipleTwiceTx,
-			expected:    multipleTwiceTxDst,
-			token:       "BNB",
-			wantError:   false,
-		},
-		{
-			name:        "new order transfer",
-			apiResponse: newOrderTransaction,
-			expected:    newOrderTransferDst,
-			token:       "AWC-986",
-			wantError:   true,
-		},
-		{
-			name:        "cancel order transfer",
-			apiResponse: cancelOrderTransaction,
-			expected:    cancelOrdeTransferDst,
-			token:       "GTO-908",
-			wantError:   true,
-		},
-		{
-			name:        "new order transfer",
-			apiResponse: newOrderTransaction,
-			expected:    metaFreeNewOrderTransferDst,
-			token:       "AWC-986",
-			wantError:   true,
-		},
-		{
-			name:        "cancel order transfer",
-			apiResponse: cancelOrderTransaction,
-			expected:    metaFreeCancelOrdeTransferDst,
-			token:       "GTO-908",
-			wantError:   true,
-		},
-		{
-			name:        "normalize error transfer",
-			apiResponse: tokenTransferTransaction,
-			token:       "GTO-908",
-			wantError:   true,
-		},
-	}
-
-	for _, testTxInstance := range testTxList {
-		t.Run(testTxInstance.name, func(t *testing.T) {
-			var srcTx Tx
-			err := json.Unmarshal([]byte(testTxInstance.apiResponse), &srcTx)
-			assert.Nil(t, err)
-			tx, ok := NormalizeTx(srcTx, testTxInstance.token, "")
-			if testTxInstance.wantError {
-				assert.False(t, ok, "transfer: tx could be normalized")
-				return
-			}
-			assert.True(t, ok, "transfer: tx could not be normalized")
-			assert.Equal(t, blockatlas.TxPage{testTxInstance.expected}, tx, "transfer: tx don't equal")
-		})
-	}
-}
-
-type testTxs struct {
-	name        string
-	apiResponse string
-	expected    []blockatlas.Tx
-	token       string
-}
-
-func convertJsonToArray(jsonString string) string {
-	return "[" + jsonString + "]"
-}
-
 func TestNormalizeTxs(t *testing.T) {
-	testTxsList := []testTxs{
-		{
-			name:        "bnb transfer",
-			apiResponse: convertJsonToArray(transferTransaction),
-			expected:    []blockatlas.Tx{transferDst},
-			token:       "BNB",
-		},
-		{
-			name:        "native token transfer",
-			apiResponse: convertJsonToArray(tokenTransferTransaction),
-			expected:    []blockatlas.Tx{tokenTransferDst},
-			token:       "YLC-D8B",
-		},
-		//{
-		//	name:        "all transfers",
-		//	apiResponse: AllTransfersType,
-		//	expected:    []blockatlas.Tx{transferDst, tokenTransferDst, newOrderTransferDst, cancelOrdeTransferDst},
-		//	token:       "",
-		//},
-		//{
-		//	name:        "new order transfer",
-		//	apiResponse: convertJsonToArray(newOrderTransaction),
-		//	expected:    []blockatlas.Tx{newOrderTransferDst},
-		//	token:       "AWC-986",
-		//},
-		//{
-		//	name:        "cancel order transfer",
-		//	apiResponse: convertJsonToArray(cancelOrderTransaction),
-		//	expected:    []blockatlas.Tx{cancelOrdeTransferDst},
-		//	token:       "GTO-908",
-		//}
+	type test struct {
+		name, address, dexTxResponse string
+		expected                     []blockatlas.Tx
+	}
+	tests := []test{
+		{name: "BNB single transfer", dexTxResponse: bnbSingleExplorerTransferResponse, expected: []blockatlas.Tx{expectBnbSingleExplorerTransfer}, address: addr1},
+		{name: "BEP2 single transfer", dexTxResponse: bep2SingleExplorerTransferResponse, expected: []blockatlas.Tx{expectBEP2SingleExplorerTransfer}, address: addr2},
+		{name: "BEP2 multiple transfer", dexTxResponse: bep2MultipleExplorerTransferResponse, expected: []blockatlas.Tx{expectBEP2SingleExplorerTransfer}, address: addr2},
 	}
 
-	for _, testTxsInstance := range testTxsList {
-		t.Run(testTxsInstance.name, func(t *testing.T) {
-			var srcTxs []Tx
-			err := json.Unmarshal([]byte(testTxsInstance.apiResponse), &srcTxs)
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			var srcTx ExplorerTxs
+			err := json.Unmarshal([]byte(tt.dexTxResponse), &srcTx)
 			assert.Nil(t, err)
-			txs := NormalizeTxs(srcTxs, testTxsInstance.token, "")
-			assert.Equal(t, testTxsInstance.expected, txs, "transfer: tx don't equal")
+			actual := normalizeTx(srcTx, tt.address)
+			assert.Equal(t, tt.expected, actual, "tx don't equal")
 		})
 	}
 }
 
 func TestTokenSymbol(t *testing.T) {
-	assert.Equal(t, "UGAS", TokenSymbol("UGAS"))
-	assert.Equal(t, "UGAS", TokenSymbol("UGAS-B0C"))
+	assert.Equal(t, "UGAS", tokenSymbol("UGAS"))
+	assert.Equal(t, "UGAS", tokenSymbol("UGAS-B0C"))
+	assert.Equal(t, "cargabe", tokenSymbol("cargabe"))
+	assert.Equal(t, "CARBAGE", tokenSymbol("CARBAGE"))
+	assert.Equal(t, "", tokenSymbol(""))
 }
 
-var (
-	metaTx = blockatlas.Transfer{
-		Value:    "100000000",
-		Symbol:   "BNB",
-		Decimals: 8,
-	}
-	metaTx2 = blockatlas.Transfer{
-		Value:    "2",
-		Symbol:   "BNB",
-		Decimals: 8,
-	}
-	metaTokenTx = blockatlas.NativeTokenTransfer{
-		Value:    "326900000000",
-		TokenID:  "AERGO-46B",
-		Symbol:   "AERGO",
-		From:     "bnb1nm4n03x00gw0x6v784jzryyp6wxnjaxswr3xm8",
-		To:       "bnb1eff4hzx4lfsun3px5walchdy4vek4n0njcdzyn",
-		Decimals: 8,
-	}
-)
-
-func Test_normalizeTransfer(t *testing.T) {
-	testTx := baseTransferTx
-	testTx.Meta = metaTx
-	testTx2 := baseTransferTx
-	testTx2.Meta = metaTx2
-	testTokenTx := baseTransferTx
-	testTokenTx.Meta = metaTokenTx
-	type args struct {
-		tx      blockatlas.Tx
-		srcTx   string
-		token   string
-		address string
-	}
+func Test_getBase(t *testing.T) {
 	tests := []struct {
-		name  string
-		args  args
-		want  blockatlas.TxPage
-		want1 bool
+		name           string
+		srcTx          ExplorerTxs
+		expectStatus   blockatlas.Status
+		expectErrorMsg string
 	}{
-		{"test multiple tx 1", args{
-			tx:      baseTransferTx,
-			srcTx:   multipleTx,
-			token:   "BNB",
-			address: "",
-		}, blockatlas.TxPage{testTx}, true},
-		{"test multiple tx 2", args{
-			tx:      baseTransferTx,
-			srcTx:   multipleTwiceTx,
-			token:   "BNB",
-			address: "",
-		}, blockatlas.TxPage{testTx2}, true},
-		{"tx multiple token tx", args{
-			tx:      baseTransferTx,
-			srcTx:   multipleTx,
-			token:   "AERGO-46B",
-			address: "",
-		}, blockatlas.TxPage{testTokenTx}, true},
-		{"test multiple tx fail", args{
-			tx:      baseTransferTx,
-			srcTx:   multipleTwiceTx,
-			token:   "AERGO-46B",
-			address: "",
-		}, blockatlas.TxPage{}, false},
-		{"test multiple tx address fail", args{
-			tx:      baseTransferTx,
-			srcTx:   multipleTwiceTx,
-			token:   "AERGO-46B",
-			address: "tbnb1qxm48ndhmh7su0r7zgwmwkltuqgly57jdf8yf8",
-		}, blockatlas.TxPage{}, false},
+		{"Should have status completed", ExplorerTxs{Code: 0}, blockatlas.StatusCompleted, ""},
+		{"Should have status error and error message", ExplorerTxs{Code: 1}, blockatlas.StatusError, "error"},
 	}
+
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
-			var srcTx Tx
-			err := json.Unmarshal([]byte(tt.args.srcTx), &srcTx)
-			assert.Nil(t, err)
-			got, got1 := normalizeTransfer(tt.args.tx, srcTx, tt.args.token, tt.args.address)
-			assert.Equal(t, tt.want, got)
-			assert.Equal(t, tt.want1, got1)
+			base := getBase(tt.srcTx)
+			assert.Equal(t, base.Status, tt.expectStatus)
+			assert.Equal(t, base.Error, tt.expectErrorMsg)
 		})
 	}
 }
diff --git a/tests/postman/token_data.json b/tests/postman/token_data.json
index da7a287..f53b1c7 100644
--- a/tests/postman/token_data.json
+++ b/tests/postman/token_data.json
@@ -29,10 +29,10 @@
     },
     {
         "handler": "binance",
-        "address": "bnb1jxfh2g85q3v0tdq56fnevx6xcxtcnhtsmcu64m"
+        "address": "bnb1jeu6gscugy6l2wyatxthkh2hmer4hzevgcmf0q"
     },
     {
         "handler": "classic",
         "address": "0xa12105efa0663147bddee178f6a741ac15676b79"
     }
-]
\ No newline at end of file
+]
diff --git a/tests/postman/transaction_data.json b/tests/postman/transaction_data.json
index 35682bd..5cf4224 100644
--- a/tests/postman/transaction_data.json
+++ b/tests/postman/transaction_data.json
@@ -85,9 +85,9 @@
     },
     {
         "handler": "binance",
-        "address": "bnb1mnf0g6zhy2rpy63w8ryc6yp77s0fmqfyzjtkvd",
+        "address": "bnb1jeu6gscugy6l2wyatxthkh2hmer4hzevgcmf0q",
         "expectedTxNum": 1,
-        "expectedTxId": "DDA939C475755B2A00123CDA37A5EC442F502EA2983014D04F647C3CB9FB57A0"
+        "expectedTxId": "4577CB3B5B202696E9E0B093A6DA973C7DD9CBC6808DA1326872745C35F3C089"
     },
     {
         "handler": "tezos",