Repository: trustwallet/blockatlas
Pull request #1262 (2020-10-28 10:35:42)

[Indexer] Update api and db
- Add coin to db and as param to query
- Use GET instead of POST

codecov[bot]: # [Codecov](https://codecov.io/gh/trustwallet/blockatlas/pull/1262?src=pr&el=h1) Report
> Merging [#1262](https://codecov.io/gh/trustwallet/blockatlas/pull/1262?src=pr&el=desc) into [master](https://codecov.io/gh/trustwallet/blockatlas/commit/335b54ae51b0ba4f5db555817acdaf2a42f4b576?el=desc) will **decrease** coverage by `0%`.
> The diff coverage is `0%`.

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

```diff
@@          Coverage Diff           @@
##           master   #1262   +/-   ##
======================================
- Coverage      42%     42%   -1%     
======================================
  Files         154     154           
  Lines        4792    4793    +1     
======================================
  Hits         2033    2033           
- Misses       2581    2582    +1     
  Partials      178     178           
```


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

------

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


Patch:
diff --git a/api/endpoint/token.go b/api/endpoint/token.go
index c2b57f8..22ec72e 100644
--- a/api/endpoint/token.go
+++ b/api/endpoint/token.go
@@ -140,13 +140,35 @@ func GetTokensByAddressIndexer(c *gin.Context, instance tokensearcher.Instance)
 	c.JSON(http.StatusOK, result)
 }
 
+// @Description Get new tokens
+// @ID tokens_new_v3
+// @Summary Get list of new tokens by coin from specific unix timstamp
+// @Accept json
+// @Produce json
+// @Tags Transactions
+// @Param from query int true "unix timestamp"
+// @Param coin query int false "coin like 60"
+// @Success 200 {object} tokenindexer.Response
+// @Router /v3/tokens/new [get]
 func GetNewTokens(c *gin.Context, instance tokenindexer.Instance) {
-	var query tokenindexer.Request
-	if err := c.Bind(&query); err != nil {
+	var request tokenindexer.Request
+	fromRaw := c.Query("from")
+	coinRaw := c.DefaultQuery("coin", "-1")
+
+	from, err := strconv.Atoi(fromRaw)
+	if err != nil {
 		c.AbortWithStatusJSON(http.StatusBadRequest, errorResponse(err))
-		return
 	}
-	resp, err := instance.HandleNewTokensRequest(query, c.Request.Context())
+
+	coin, err := strconv.Atoi(coinRaw)
+	if err != nil {
+		c.AbortWithStatusJSON(http.StatusBadRequest, errorResponse(err))
+	}
+
+	request.Coin = coin
+	request.From = int64(from)
+
+	resp, err := instance.HandleNewTokensRequest(request, c.Request.Context())
 	if err != nil {
 		c.AbortWithStatusJSON(http.StatusInternalServerError, errorResponse(err))
 		return
diff --git a/api/registry.go b/api/registry.go
index e445091..aae152a 100644
--- a/api/registry.go
+++ b/api/registry.go
@@ -112,7 +112,7 @@ func RegisterTokensSearcherAPI(router gin.IRouter, instance tokensearcher.Instan
 }
 
 func RegisterTokensIndexAPI(router gin.IRouter, instance tokenindexer.Instance) {
-	router.POST("/v3/tokens/new", func(c *gin.Context) {
+	router.GET("/v3/tokens/new", func(c *gin.Context) {
 		endpoint.GetNewTokens(c, instance)
 	})
 }
diff --git a/config.yml b/config.yml
index 170eba0..28b29fc 100644
--- a/config.yml
+++ b/config.yml
@@ -26,7 +26,7 @@ observer:
   # Amount of time between fetching blocks concurrently
   fetch_blocks_interval: 1ms
   # Don't request more than N blocks at once
-  backlog_max_blocks: 200
+  backlog_max_blocks: 20
   # Limit amount of transactions in batch
   txs_batch_limit: 3000
   # Limit of push notifications in batch
diff --git a/db/asset.go b/db/asset.go
index db14c7e..ddfe167 100644
--- a/db/asset.go
+++ b/db/asset.go
@@ -101,12 +101,19 @@ func (i *Instance) GetAssetsByIDs(ids []string, ctx context.Context) ([]models.A
 	return dbAssets, nil
 }
 
-func (i *Instance) GetAssetsFrom(from time.Time, ctx context.Context) ([]models.Asset, error) {
+func (i *Instance) GetAssetsFrom(from time.Time, coin int, ctx context.Context) ([]models.Asset, error) {
 	db := i.Gorm.WithContext(ctx)
 	var dbAssets []models.Asset
-	if err := db.Find(&dbAssets, "created_at > ?", from).Error; err != nil {
-		return nil, err
+	if coin == -1 {
+		if err := db.Find(&dbAssets, "created_at > ?", from).Error; err != nil {
+			return nil, err
+		}
+	} else {
+		if err := db.Find(&dbAssets, "created_at > ? and coin = ?", from, coin).Error; err != nil {
+			return nil, err
+		}
 	}
+
 	return dbAssets, nil
 }
 
diff --git a/db/models/asset.go b/db/models/asset.go
index 5e323e2..a0c90b9 100644
--- a/db/models/asset.go
+++ b/db/models/asset.go
@@ -11,6 +11,7 @@ type Asset struct {
 	Name     string `gorm:"type:varchar(128)"`
 	Symbol   string `gorm:"type:varchar(128)"`
 	Type     string `gorm:"type:varchar(12)"`
+	Coin     uint
 }
 
 func AssetIDs(assets []Asset) []string {
diff --git a/docs/docs.go b/docs/docs.go
index af7c1e4..507a28c 100644
--- a/docs/docs.go
+++ b/docs/docs.go
@@ -19,6 +19,7 @@ var doc = `{
         "description": "{{.Description}}",
         "title": "{{.Title}}",
         "contact": {},
+        "license": {},
         "version": "{{.Version}}"
     },
     "host": "{{.Host}}",
@@ -45,10 +46,7 @@ var doc = `{
                         "in": "body",
                         "required": true,
                         "schema": {
-                            "type": "array",
-                            "items": {
-                                "$ref": "#/definitions/api_endpoint.AddressBatchRequest"
-                            }
+                            "$ref": "#/definitions/endpoint.AddressesRequest"
                         }
                     }
                 ],
@@ -56,10 +54,7 @@ var doc = `{
                     "200": {
                         "description": "OK",
                         "schema": {
-                            "type": "array",
-                            "items": {
-                                "$ref": "#/definitions/blockatlas.DelegationResponse"
-                            }
+                            "$ref": "#/definitions/blockatlas.DelegationsBatchPage"
                         }
                     }
                 }
@@ -86,10 +81,7 @@ var doc = `{
                         "in": "body",
                         "required": true,
                         "schema": {
-                            "type": "array",
-                            "items": {
-                                "$ref": "#/definitions/api_endpoint.AddressBatchRequest"
-                            }
+                            "$ref": "#/definitions/endpoint.AddressesRequest"
                         }
                     }
                 ],
@@ -97,10 +89,7 @@ var doc = `{
                     "200": {
                         "description": "OK",
                         "schema": {
-                            "type": "array",
-                            "items": {
-                                "$ref": "#/definitions/blockatlas.DelegationResponse"
-                            }
+                            "$ref": "#/definitions/blockatlas.DelegationsBatchPage"
                         }
                     }
                 }
@@ -178,7 +167,7 @@ var doc = `{
                     "500": {
                         "description": "Internal Server Error",
                         "schema": {
-                            "$ref": "#/definitions/github.com_trustwallet_blockatlas_api_endpoint.ErrorResponse"
+                            "$ref": "#/definitions/endpoint.ErrorResponse"
                         }
                     }
                 }
@@ -226,7 +215,7 @@ var doc = `{
                     "500": {
                         "description": "Internal Server Error",
                         "schema": {
-                            "$ref": "#/definitions/api_endpoint.ErrorResponse"
+                            "$ref": "#/definitions/endpoint.ErrorResponse"
                         }
                     }
                 }
@@ -266,7 +255,7 @@ var doc = `{
                     "500": {
                         "description": "Internal Server Error",
                         "schema": {
-                            "$ref": "#/definitions/api_endpoint.ErrorResponse"
+                            "$ref": "#/definitions/endpoint.ErrorResponse"
                         }
                     }
                 }
@@ -308,16 +297,13 @@ var doc = `{
                     "200": {
                         "description": "OK",
                         "schema": {
-                            "type": "array",
-                            "items": {
-                                "$ref": "#/definitions/blockatlas.Collection"
-                            }
+                            "$ref": "#/definitions/blockatlas.CollectionPage"
                         }
                     },
                     "500": {
                         "description": "Internal Server Error",
                         "schema": {
-                            "$ref": "#/definitions/github.com_trustwallet_blockatlas_api_endpoint.ErrorResponse"
+                            "$ref": "#/definitions/endpoint.ErrorResponse"
                         }
                     }
                 }
@@ -359,7 +345,7 @@ var doc = `{
                     "500": {
                         "description": "Internal Server Error",
                         "schema": {
-                            "$ref": "#/definitions/github.com_trustwallet_blockatlas_api_endpoint.ErrorResponse"
+                            "$ref": "#/definitions/endpoint.ErrorResponse"
                         }
                     }
                 }
@@ -401,7 +387,7 @@ var doc = `{
                     "500": {
                         "description": "Internal Server Error",
                         "schema": {
-                            "$ref": "#/definitions/github.com_trustwallet_blockatlas_api_endpoint.ErrorResponse"
+                            "$ref": "#/definitions/endpoint.ErrorResponse"
                         }
                     }
                 }
@@ -433,17 +419,53 @@ var doc = `{
                         "schema": {
                             "type": "array",
                             "items": {
-                                "type": "array",
-                                "items": {
-                                    "$ref": "#/definitions/blockatlas.DelegationResponse"
-                                }
+                                "$ref": "#/definitions/blockatlas.DelegationsBatchPage"
                             }
                         }
                     },
                     "400": {
                         "description": "Bad Request",
                         "schema": {
-                            "$ref": "#/definitions/api_endpoint.ErrorResponse"
+                            "$ref": "#/definitions/endpoint.ErrorResponse"
+                        }
+                    }
+                }
+            }
+        },
+        "/v3/tokens/new": {
+            "get": {
+                "description": "Get new tokens",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "Transactions"
+                ],
+                "summary": "Get list of new tokens by coin from specific unix timstamp",
+                "operationId": "tokens_new_v3",
+                "parameters": [
+                    {
+                        "type": "integer",
+                        "description": "unix timestamp",
+                        "name": "from",
+                        "in": "query",
+                        "required": true
+                    },
+                    {
+                        "type": "integer",
+                        "description": "coin like 60",
+                        "name": "coin",
+                        "in": "query"
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "$ref": "#/definitions/tokenindexer.Response"
                         }
                     }
                 }
@@ -529,16 +551,13 @@ var doc = `{
                     "200": {
                         "description": "OK",
                         "schema": {
-                            "type": "array",
-                            "items": {
-                                "$ref": "#/definitions/blockatlas.Collection"
-                            }
+                            "$ref": "#/definitions/blockatlas.CollectionPage"
                         }
                     },
                     "500": {
                         "description": "Internal Server Error",
                         "schema": {
-                            "$ref": "#/definitions/github.com_trustwallet_blockatlas_api_endpoint.ErrorResponse"
+                            "$ref": "#/definitions/endpoint.ErrorResponse"
                         }
                     }
                 }
@@ -546,33 +565,6 @@ var doc = `{
         }
     },
     "definitions": {
-        "api_endpoint.AddressBatchRequest": {
-            "type": "object",
-            "properties": {
-                "address": {
-                    "type": "string"
-                },
-                "coin": {
-                    "type": "integer"
-                }
-            }
-        },
-        "api_endpoint.ErrorDetails": {
-            "type": "object",
-            "properties": {
-                "message": {
-                    "type": "string"
-                }
-            }
-        },
-        "api_endpoint.ErrorResponse": {
-            "type": "object",
-            "properties": {
-                "error": {
-                    "$ref": "#/definitions/api_endpoint.ErrorDetails"
-                }
-            }
-        },
         "blockatlas.Collection": {
             "type": "object",
             "properties": {
@@ -602,10 +594,17 @@ var doc = `{
                 }
             }
         },
+        "blockatlas.CollectionPage": {
+            "type": "array",
+            "items": {
+                "$ref": "#/definitions/blockatlas.Collection"
+            }
+        },
         "blockatlas.Delegation": {
             "type": "object",
             "properties": {
                 "delegator": {
+                    "type": "object",
                     "$ref": "#/definitions/blockatlas.StakeValidator"
                 },
                 "metadata": {
@@ -629,19 +628,31 @@ var doc = `{
                     "type": "string"
                 },
                 "coin": {
+                    "type": "object",
                     "$ref": "#/definitions/coin.ExternalCoin"
                 },
                 "delegations": {
-                    "type": "array",
-                    "items": {
-                        "$ref": "#/definitions/blockatlas.Delegation"
-                    }
+                    "type": "object",
+                    "$ref": "#/definitions/blockatlas.DelegationsPage"
                 },
                 "details": {
+                    "type": "object",
                     "$ref": "#/definitions/blockatlas.StakingDetails"
                 }
             }
         },
+        "blockatlas.DelegationsBatchPage": {
+            "type": "array",
+            "items": {
+                "$ref": "#/definitions/blockatlas.DelegationResponse"
+            }
+        },
+        "blockatlas.DelegationsPage": {
+            "type": "array",
+            "items": {
+                "$ref": "#/definitions/blockatlas.Delegation"
+            }
+        },
         "blockatlas.DocsResponse": {
             "type": "object",
             "properties": {
@@ -665,12 +676,14 @@ var doc = `{
             "type": "object",
             "properties": {
                 "details": {
+                    "type": "object",
                     "$ref": "#/definitions/blockatlas.StakingDetails"
                 },
                 "id": {
                     "type": "string"
                 },
                 "info": {
+                    "type": "object",
                     "$ref": "#/definitions/blockatlas.StakeValidatorInfo"
                 },
                 "status": {
@@ -705,6 +718,7 @@ var doc = `{
                     "type": "string"
                 },
                 "reward": {
+                    "type": "object",
                     "$ref": "#/definitions/blockatlas.StakingReward"
                 },
                 "type": {
@@ -737,7 +751,7 @@ var doc = `{
                 }
             }
         },
-        "github.com_trustwallet_blockatlas_api_endpoint.AddressBatchRequest": {
+        "endpoint.AddressBatchRequest": {
             "type": "object",
             "properties": {
                 "address": {
@@ -748,7 +762,13 @@ var doc = `{
                 }
             }
         },
-        "github.com_trustwallet_blockatlas_api_endpoint.ErrorDetails": {
+        "endpoint.AddressesRequest": {
+            "type": "array",
+            "items": {
+                "$ref": "#/definitions/endpoint.AddressBatchRequest"
+            }
+        },
+        "endpoint.ErrorDetails": {
             "type": "object",
             "properties": {
                 "message": {
@@ -756,11 +776,43 @@ var doc = `{
                 }
             }
         },
-        "github.com_trustwallet_blockatlas_api_endpoint.ErrorResponse": {
+        "endpoint.ErrorResponse": {
             "type": "object",
             "properties": {
                 "error": {
-                    "$ref": "#/definitions/github.com_trustwallet_blockatlas_api_endpoint.ErrorDetails"
+                    "type": "object",
+                    "$ref": "#/definitions/endpoint.ErrorDetails"
+                }
+            }
+        },
+        "tokenindexer.Asset": {
+            "type": "object",
+            "properties": {
+                "asset": {
+                    "type": "string"
+                },
+                "decimals": {
+                    "type": "integer"
+                },
+                "name": {
+                    "type": "string"
+                },
+                "symbol": {
+                    "type": "string"
+                },
+                "type": {
+                    "type": "string"
+                }
+            }
+        },
+        "tokenindexer.Response": {
+            "type": "object",
+            "properties": {
+                "assets": {
+                    "type": "array",
+                    "items": {
+                        "$ref": "#/definitions/tokenindexer.Asset"
+                    }
                 }
             }
         }
diff --git a/docs/swagger.json b/docs/swagger.json
index eb5822d..322372f 100644
--- a/docs/swagger.json
+++ b/docs/swagger.json
@@ -1,7 +1,8 @@
 {
     "swagger": "2.0",
     "info": {
-        "contact": {}
+        "contact": {},
+        "license": {}
     },
     "paths": {
         "/v2/staking/delegations": {
@@ -25,10 +26,7 @@
                         "in": "body",
                         "required": true,
                         "schema": {
-                            "type": "array",
-                            "items": {
-                                "$ref": "#/definitions/api_endpoint.AddressBatchRequest"
-                            }
+                            "$ref": "#/definitions/endpoint.AddressesRequest"
                         }
                     }
                 ],
@@ -36,10 +34,7 @@
                     "200": {
                         "description": "OK",
                         "schema": {
-                            "type": "array",
-                            "items": {
-                                "$ref": "#/definitions/blockatlas.DelegationResponse"
-                            }
+                            "$ref": "#/definitions/blockatlas.DelegationsBatchPage"
                         }
                     }
                 }
@@ -66,10 +61,7 @@
                         "in": "body",
                         "required": true,
                         "schema": {
-                            "type": "array",
-                            "items": {
-                                "$ref": "#/definitions/api_endpoint.AddressBatchRequest"
-                            }
+                            "$ref": "#/definitions/endpoint.AddressesRequest"
                         }
                     }
                 ],
@@ -77,10 +69,7 @@
                     "200": {
                         "description": "OK",
                         "schema": {
-                            "type": "array",
-                            "items": {
-                                "$ref": "#/definitions/blockatlas.DelegationResponse"
-                            }
+                            "$ref": "#/definitions/blockatlas.DelegationsBatchPage"
                         }
                     }
                 }
@@ -158,7 +147,7 @@
                     "500": {
                         "description": "Internal Server Error",
                         "schema": {
-                            "$ref": "#/definitions/github.com_trustwallet_blockatlas_api_endpoint.ErrorResponse"
+                            "$ref": "#/definitions/endpoint.ErrorResponse"
                         }
                     }
                 }
@@ -206,7 +195,7 @@
                     "500": {
                         "description": "Internal Server Error",
                         "schema": {
-                            "$ref": "#/definitions/api_endpoint.ErrorResponse"
+                            "$ref": "#/definitions/endpoint.ErrorResponse"
                         }
                     }
                 }
@@ -246,7 +235,7 @@
                     "500": {
                         "description": "Internal Server Error",
                         "schema": {
-                            "$ref": "#/definitions/api_endpoint.ErrorResponse"
+                            "$ref": "#/definitions/endpoint.ErrorResponse"
                         }
                     }
                 }
@@ -288,16 +277,13 @@
                     "200": {
                         "description": "OK",
                         "schema": {
-                            "type": "array",
-                            "items": {
-                                "$ref": "#/definitions/blockatlas.Collection"
-                            }
+                            "$ref": "#/definitions/blockatlas.CollectionPage"
                         }
                     },
                     "500": {
                         "description": "Internal Server Error",
                         "schema": {
-                            "$ref": "#/definitions/github.com_trustwallet_blockatlas_api_endpoint.ErrorResponse"
+                            "$ref": "#/definitions/endpoint.ErrorResponse"
                         }
                     }
                 }
@@ -339,7 +325,7 @@
                     "500": {
                         "description": "Internal Server Error",
                         "schema": {
-                            "$ref": "#/definitions/github.com_trustwallet_blockatlas_api_endpoint.ErrorResponse"
+                            "$ref": "#/definitions/endpoint.ErrorResponse"
                         }
                     }
                 }
@@ -381,7 +367,7 @@
                     "500": {
                         "description": "Internal Server Error",
                         "schema": {
-                            "$ref": "#/definitions/github.com_trustwallet_blockatlas_api_endpoint.ErrorResponse"
+                            "$ref": "#/definitions/endpoint.ErrorResponse"
                         }
                     }
                 }
@@ -413,17 +399,53 @@
                         "schema": {
                             "type": "array",
                             "items": {
-                                "type": "array",
-                                "items": {
-                                    "$ref": "#/definitions/blockatlas.DelegationResponse"
-                                }
+                                "$ref": "#/definitions/blockatlas.DelegationsBatchPage"
                             }
                         }
                     },
                     "400": {
                         "description": "Bad Request",
                         "schema": {
-                            "$ref": "#/definitions/api_endpoint.ErrorResponse"
+                            "$ref": "#/definitions/endpoint.ErrorResponse"
+                        }
+                    }
+                }
+            }
+        },
+        "/v3/tokens/new": {
+            "get": {
+                "description": "Get new tokens",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "Transactions"
+                ],
+                "summary": "Get list of new tokens by coin from specific unix timstamp",
+                "operationId": "tokens_new_v3",
+                "parameters": [
+                    {
+                        "type": "integer",
+                        "description": "unix timestamp",
+                        "name": "from",
+                        "in": "query",
+                        "required": true
+                    },
+                    {
+                        "type": "integer",
+                        "description": "coin like 60",
+                        "name": "coin",
+                        "in": "query"
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "$ref": "#/definitions/tokenindexer.Response"
                         }
                     }
                 }
@@ -509,16 +531,13 @@
                     "200": {
                         "description": "OK",
                         "schema": {
-                            "type": "array",
-                            "items": {
-                                "$ref": "#/definitions/blockatlas.Collection"
-                            }
+                            "$ref": "#/definitions/blockatlas.CollectionPage"
                         }
                     },
                     "500": {
                         "description": "Internal Server Error",
                         "schema": {
-                            "$ref": "#/definitions/github.com_trustwallet_blockatlas_api_endpoint.ErrorResponse"
+                            "$ref": "#/definitions/endpoint.ErrorResponse"
                         }
                     }
                 }
@@ -526,33 +545,6 @@
         }
     },
     "definitions": {
-        "api_endpoint.AddressBatchRequest": {
-            "type": "object",
-            "properties": {
-                "address": {
-                    "type": "string"
-                },
-                "coin": {
-                    "type": "integer"
-                }
-            }
-        },
-        "api_endpoint.ErrorDetails": {
-            "type": "object",
-            "properties": {
-                "message": {
-                    "type": "string"
-                }
-            }
-        },
-        "api_endpoint.ErrorResponse": {
-            "type": "object",
-            "properties": {
-                "error": {
-                    "$ref": "#/definitions/api_endpoint.ErrorDetails"
-                }
-            }
-        },
         "blockatlas.Collection": {
             "type": "object",
             "properties": {
@@ -582,10 +574,17 @@
                 }
             }
         },
+        "blockatlas.CollectionPage": {
+            "type": "array",
+            "items": {
+                "$ref": "#/definitions/blockatlas.Collection"
+            }
+        },
         "blockatlas.Delegation": {
             "type": "object",
             "properties": {
                 "delegator": {
+                    "type": "object",
                     "$ref": "#/definitions/blockatlas.StakeValidator"
                 },
                 "metadata": {
@@ -609,19 +608,31 @@
                     "type": "string"
                 },
                 "coin": {
+                    "type": "object",
                     "$ref": "#/definitions/coin.ExternalCoin"
                 },
                 "delegations": {
-                    "type": "array",
-                    "items": {
-                        "$ref": "#/definitions/blockatlas.Delegation"
-                    }
+                    "type": "object",
+                    "$ref": "#/definitions/blockatlas.DelegationsPage"
                 },
                 "details": {
+                    "type": "object",
                     "$ref": "#/definitions/blockatlas.StakingDetails"
                 }
             }
         },
+        "blockatlas.DelegationsBatchPage": {
+            "type": "array",
+            "items": {
+                "$ref": "#/definitions/blockatlas.DelegationResponse"
+            }
+        },
+        "blockatlas.DelegationsPage": {
+            "type": "array",
+            "items": {
+                "$ref": "#/definitions/blockatlas.Delegation"
+            }
+        },
         "blockatlas.DocsResponse": {
             "type": "object",
             "properties": {
@@ -645,12 +656,14 @@
             "type": "object",
             "properties": {
                 "details": {
+                    "type": "object",
                     "$ref": "#/definitions/blockatlas.StakingDetails"
                 },
                 "id": {
                     "type": "string"
                 },
                 "info": {
+                    "type": "object",
                     "$ref": "#/definitions/blockatlas.StakeValidatorInfo"
                 },
                 "status": {
@@ -685,6 +698,7 @@
                     "type": "string"
                 },
                 "reward": {
+                    "type": "object",
                     "$ref": "#/definitions/blockatlas.StakingReward"
                 },
                 "type": {
@@ -717,7 +731,7 @@
                 }
             }
         },
-        "github.com_trustwallet_blockatlas_api_endpoint.AddressBatchRequest": {
+        "endpoint.AddressBatchRequest": {
             "type": "object",
             "properties": {
                 "address": {
@@ -728,7 +742,13 @@
                 }
             }
         },
-        "github.com_trustwallet_blockatlas_api_endpoint.ErrorDetails": {
+        "endpoint.AddressesRequest": {
+            "type": "array",
+            "items": {
+                "$ref": "#/definitions/endpoint.AddressBatchRequest"
+            }
+        },
+        "endpoint.ErrorDetails": {
             "type": "object",
             "properties": {
                 "message": {
@@ -736,11 +756,43 @@
                 }
             }
         },
-        "github.com_trustwallet_blockatlas_api_endpoint.ErrorResponse": {
+        "endpoint.ErrorResponse": {
             "type": "object",
             "properties": {
                 "error": {
-                    "$ref": "#/definitions/github.com_trustwallet_blockatlas_api_endpoint.ErrorDetails"
+                    "type": "object",
+                    "$ref": "#/definitions/endpoint.ErrorDetails"
+                }
+            }
+        },
+        "tokenindexer.Asset": {
+            "type": "object",
+            "properties": {
+                "asset": {
+                    "type": "string"
+                },
+                "decimals": {
+                    "type": "integer"
+                },
+                "name": {
+                    "type": "string"
+                },
+                "symbol": {
+                    "type": "string"
+                },
+                "type": {
+                    "type": "string"
+                }
+            }
+        },
+        "tokenindexer.Response": {
+            "type": "object",
+            "properties": {
+                "assets": {
+                    "type": "array",
+                    "items": {
+                        "$ref": "#/definitions/tokenindexer.Asset"
+                    }
                 }
             }
         }
diff --git a/docs/swagger.yaml b/docs/swagger.yaml
index f5111ea..47ae341 100644
--- a/docs/swagger.yaml
+++ b/docs/swagger.yaml
@@ -1,21 +1,4 @@
 definitions:
-  api_endpoint.AddressBatchRequest:
-    properties:
-      address:
-        type: string
-      coin:
-        type: integer
-    type: object
-  api_endpoint.ErrorDetails:
-    properties:
-      message:
-        type: string
-    type: object
-  api_endpoint.ErrorResponse:
-    properties:
-      error:
-        $ref: '#/definitions/api_endpoint.ErrorDetails'
-    type: object
   blockatlas.Collection:
     properties:
       address:
@@ -35,10 +18,15 @@ definitions:
       total:
         type: integer
     type: object
+  blockatlas.CollectionPage:
+    items:
+      $ref: '#/definitions/blockatlas.Collection'
+    type: array
   blockatlas.Delegation:
     properties:
       delegator:
         $ref: '#/definitions/blockatlas.StakeValidator'
+        type: object
       metadata:
         type: object
       status:
@@ -54,13 +42,22 @@ definitions:
         type: string
       coin:
         $ref: '#/definitions/coin.ExternalCoin'
+        type: object
       delegations:
-        items:
-          $ref: '#/definitions/blockatlas.Delegation'
-        type: array
+        $ref: '#/definitions/blockatlas.DelegationsPage'
+        type: object
       details:
         $ref: '#/definitions/blockatlas.StakingDetails'
+        type: object
     type: object
+  blockatlas.DelegationsBatchPage:
+    items:
+      $ref: '#/definitions/blockatlas.DelegationResponse'
+    type: array
+  blockatlas.DelegationsPage:
+    items:
+      $ref: '#/definitions/blockatlas.Delegation'
+    type: array
   blockatlas.DocsResponse:
     properties:
       docs:
@@ -77,10 +74,12 @@ definitions:
     properties:
       details:
         $ref: '#/definitions/blockatlas.StakingDetails'
+        type: object
       id:
         type: string
       info:
         $ref: '#/definitions/blockatlas.StakeValidatorInfo'
+        type: object
       status:
         type: boolean
     type: object
@@ -103,6 +102,7 @@ definitions:
         type: string
       reward:
         $ref: '#/definitions/blockatlas.StakingReward'
+        type: object
       type:
         type: string
     type: object
@@ -122,25 +122,51 @@ definitions:
       symbol:
         type: string
     type: object
-  github.com_trustwallet_blockatlas_api_endpoint.AddressBatchRequest:
+  endpoint.AddressBatchRequest:
     properties:
       address:
         type: string
       coin:
         type: integer
     type: object
-  github.com_trustwallet_blockatlas_api_endpoint.ErrorDetails:
+  endpoint.AddressesRequest:
+    items:
+      $ref: '#/definitions/endpoint.AddressBatchRequest'
+    type: array
+  endpoint.ErrorDetails:
     properties:
       message:
         type: string
     type: object
-  github.com_trustwallet_blockatlas_api_endpoint.ErrorResponse:
+  endpoint.ErrorResponse:
     properties:
       error:
-        $ref: '#/definitions/github.com_trustwallet_blockatlas_api_endpoint.ErrorDetails'
+        $ref: '#/definitions/endpoint.ErrorDetails'
+        type: object
+    type: object
+  tokenindexer.Asset:
+    properties:
+      asset:
+        type: string
+      decimals:
+        type: integer
+      name:
+        type: string
+      symbol:
+        type: string
+      type:
+        type: string
+    type: object
+  tokenindexer.Response:
+    properties:
+      assets:
+        items:
+          $ref: '#/definitions/tokenindexer.Asset'
+        type: array
     type: object
 info:
   contact: {}
+  license: {}
 paths:
   /v2/{coin}/blocks/{block}:
     get:
@@ -167,7 +193,7 @@ paths:
         "500":
           description: Internal Server Error
           schema:
-            $ref: '#/definitions/github.com_trustwallet_blockatlas_api_endpoint.ErrorResponse'
+            $ref: '#/definitions/endpoint.ErrorResponse'
       summary: Get Block
       tags:
       - Transactions
@@ -200,7 +226,7 @@ paths:
         "500":
           description: Internal Server Error
           schema:
-            $ref: '#/definitions/api_endpoint.ErrorResponse'
+            $ref: '#/definitions/endpoint.ErrorResponse'
       summary: Get Stake Delegations
       tags:
       - Staking
@@ -227,7 +253,7 @@ paths:
         "500":
           description: Internal Server Error
           schema:
-            $ref: '#/definitions/api_endpoint.ErrorResponse'
+            $ref: '#/definitions/endpoint.ErrorResponse'
       summary: Get Validators
       tags:
       - Staking
@@ -256,13 +282,11 @@ paths:
         "200":
           description: OK
           schema:
-            items:
-              $ref: '#/definitions/blockatlas.Collection'
-            type: array
+            $ref: '#/definitions/blockatlas.CollectionPage'
         "500":
           description: Internal Server Error
           schema:
-            $ref: '#/definitions/github.com_trustwallet_blockatlas_api_endpoint.ErrorResponse'
+            $ref: '#/definitions/endpoint.ErrorResponse'
       summary: Get Tokens
       tags:
       - Transactions
@@ -291,7 +315,7 @@ paths:
         "500":
           description: Internal Server Error
           schema:
-            $ref: '#/definitions/github.com_trustwallet_blockatlas_api_endpoint.ErrorResponse'
+            $ref: '#/definitions/endpoint.ErrorResponse'
       summary: Get Transactions
       tags:
       - Transactions
@@ -320,7 +344,7 @@ paths:
         "500":
           description: Internal Server Error
           schema:
-            $ref: '#/definitions/github.com_trustwallet_blockatlas_api_endpoint.ErrorResponse'
+            $ref: '#/definitions/endpoint.ErrorResponse'
       summary: Get Transactions by XPUB
       tags:
       - Transactions
@@ -336,18 +360,14 @@ paths:
         name: delegations
         required: true
         schema:
-          items:
-            $ref: '#/definitions/api_endpoint.AddressBatchRequest'
-          type: array
+          $ref: '#/definitions/endpoint.AddressesRequest'
       produces:
       - application/json
       responses:
         "200":
           description: OK
           schema:
-            items:
-              $ref: '#/definitions/blockatlas.DelegationResponse'
-            type: array
+            $ref: '#/definitions/blockatlas.DelegationsBatchPage'
       summary: Get Multiple Stake Delegations
       tags:
       - Staking
@@ -363,18 +383,14 @@ paths:
         name: delegations
         required: true
         schema:
-          items:
-            $ref: '#/definitions/api_endpoint.AddressBatchRequest'
-          type: array
+          $ref: '#/definitions/endpoint.AddressesRequest'
       produces:
       - application/json
       responses:
         "200":
           description: OK
           schema:
-            items:
-              $ref: '#/definitions/blockatlas.DelegationResponse'
-            type: array
+            $ref: '#/definitions/blockatlas.DelegationsBatchPage'
       summary: Get Multiple Stake Delegations
       tags:
       - Staking
@@ -419,17 +435,41 @@ paths:
           description: OK
           schema:
             items:
-              items:
-                $ref: '#/definitions/blockatlas.DelegationResponse'
-              type: array
+              $ref: '#/definitions/blockatlas.DelegationsBatchPage'
             type: array
         "400":
           description: Bad Request
           schema:
-            $ref: '#/definitions/api_endpoint.ErrorResponse'
+            $ref: '#/definitions/endpoint.ErrorResponse'
       summary: Get staking info by coin ID
       tags:
       - Staking
+  /v3/tokens/new:
+    get:
+      consumes:
+      - application/json
+      description: Get new tokens
+      operationId: tokens_new_v3
+      parameters:
+      - description: unix timestamp
+        in: query
+        name: from
+        required: true
+        type: integer
+      - description: coin like 60
+        in: query
+        name: coin
+        type: integer
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: OK
+          schema:
+            $ref: '#/definitions/tokenindexer.Response'
+      summary: Get list of new tokens by coin from specific unix timstamp
+      tags:
+      - Transactions
   /v4/{coin}/collections/{owner}/collection/{collection_id}:
     get:
       consumes:
@@ -461,13 +501,11 @@ paths:
         "200":
           description: OK
           schema:
-            items:
-              $ref: '#/definitions/blockatlas.Collection'
-            type: array
+            $ref: '#/definitions/blockatlas.CollectionPage'
         "500":
           description: Internal Server Error
           schema:
-            $ref: '#/definitions/github.com_trustwallet_blockatlas_api_endpoint.ErrorResponse'
+            $ref: '#/definitions/endpoint.ErrorResponse'
       summary: Get Collection
       tags:
       - Collections
diff --git a/pkg/blockatlas/tx.go b/pkg/blockatlas/tx.go
index ecfb566..2abea49 100644
--- a/pkg/blockatlas/tx.go
+++ b/pkg/blockatlas/tx.go
@@ -530,6 +530,7 @@ func (t Tx) AssetModel() (models.Asset, bool) {
 	if asset.Asset == "" {
 		return models.Asset{}, false
 	}
+	asset.Coin = t.Coin
 	return asset, true
 }
 
diff --git a/services/tokenindexer/api.go b/services/tokenindexer/api.go
index 3a4ba6a..7438b1f 100644
--- a/services/tokenindexer/api.go
+++ b/services/tokenindexer/api.go
@@ -17,7 +17,7 @@ func Init(database *db.Instance) Instance {
 
 func (i Instance) HandleNewTokensRequest(r Request, ctx context.Context) (Response, error) {
 	from := time.Unix(r.From, 0)
-	result, err := i.database.GetAssetsFrom(from, ctx)
+	result, err := i.database.GetAssetsFrom(from, r.Coin, ctx)
 	if err != nil {
 		return Response{}, err
 	}
diff --git a/services/tokenindexer/models.go b/services/tokenindexer/models.go
index c6aeb28..a2852b2 100644
--- a/services/tokenindexer/models.go
+++ b/services/tokenindexer/models.go
@@ -2,6 +2,7 @@ package tokenindexer
 
 type Request struct {
 	From int64
+	Coin int
 }
 
 type Response struct {


Test patch:
diff --git a/services/tokensearcher/association_test.go b/services/tokensearcher/association_test.go
index 7d79f6c..5d3bb42 100644
--- a/services/tokensearcher/association_test.go
+++ b/services/tokensearcher/association_test.go
@@ -40,12 +40,12 @@ func Test_assetsMap(t *testing.T) {
 	}
 
 	result := assetsMap(blockatlas.Txs{tx1, tx2, tx3}, "60")
-	assert.Equal(t, result["60_A"], []models.Asset{{Asset: "c60_tABC", Type: "ERC20"}})
-	assert.Equal(t, result["60_C"], []models.Asset{{Asset: "c60_tABC", Type: "ERC20"}})
-	assert.Equal(t, result["60_D"], []models.Asset{{Asset: "c60_tEFG", Type: "ERC20"}})
-	assert.Equal(t, result["60_F"], []models.Asset{{Asset: "c60_tEFG", Type: "ERC20"}})
-	assert.Equal(t, result["60_Q"], []models.Asset{{Asset: "c60_tHIJ", Type: "ERC20"}})
-	assert.Equal(t, result["60_L"], []models.Asset{{Asset: "c60_tHIJ", Type: "ERC20"}})
+	assert.Equal(t, result["60_A"], []models.Asset{{Asset: "c60_tABC", Type: "ERC20", Coin: 60}})
+	assert.Equal(t, result["60_C"], []models.Asset{{Asset: "c60_tABC", Type: "ERC20", Coin: 60}})
+	assert.Equal(t, result["60_D"], []models.Asset{{Asset: "c60_tEFG", Type: "ERC20", Coin: 60}})
+	assert.Equal(t, result["60_F"], []models.Asset{{Asset: "c60_tEFG", Type: "ERC20", Coin: 60}})
+	assert.Equal(t, result["60_Q"], []models.Asset{{Asset: "c60_tHIJ", Type: "ERC20", Coin: 60}})
+	assert.Equal(t, result["60_L"], []models.Asset{{Asset: "c60_tHIJ", Type: "ERC20", Coin: 60}})
 }
 
 func Test_associationsToAdd(t *testing.T) {
diff --git a/tests/integration/db_test/tokenindexer_test.go b/tests/integration/db_test/tokenindexer_test.go
index 7a83724..dbe6464 100644
--- a/tests/integration/db_test/tokenindexer_test.go
+++ b/tests/integration/db_test/tokenindexer_test.go
@@ -11,6 +11,7 @@ import (
 	"github.com/trustwallet/blockatlas/tests/integration/setup"
 	"sort"
 	"testing"
+	"time"
 )
 
 func Test_AddNewAssets_Simple(t *testing.T) {
@@ -57,6 +58,37 @@ func Test_AddNewAssets_Simple(t *testing.T) {
 	assert.Equal(t, 0, len(assets))
 }
 
+func Test_GetAssetsFrom_Simple(t *testing.T) {
+	setup.CleanupPgContainer(database.Gorm)
+	database.MemoryCache = gocache.New(gocache.NoExpiration, gocache.NoExpiration)
+	a := []models.Asset{
+		{
+			Asset:    "c714_a",
+			Coin:     714,
+			Decimals: 18,
+			Name:     "A",
+			Symbol:   "ABC",
+			Type:     "BEP20",
+		},
+		{
+			Asset:    "c714_b",
+			Decimals: 18,
+			Coin:     60,
+			Name:     "B",
+			Symbol:   "BCD",
+			Type:     "BEP20",
+		},
+	}
+	err := database.AddNewAssets(a, context.Background())
+	assert.Nil(t, err)
+	assets, err := database.GetAssetsFrom(time.Unix(0, 0), -1, context.Background())
+	assert.Nil(t, err)
+	assert.NotNil(t, assets)
+	assets, err = database.GetAssetsFrom(time.Unix(0, 0), 60, context.Background())
+	assert.Nil(t, err)
+	assert.Equal(t, 1, len(assets))
+}
+
 func Test_AddNewAssets(t *testing.T) {
 	setup.CleanupPgContainer(database.Gorm)
 	database.MemoryCache = gocache.New(gocache.NoExpiration, gocache.NoExpiration)