From a900bb1c2e4cc209cc922bbfb2fd1df1d8a6af18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20Men=C3=A9ndez?= Date: Tue, 19 Sep 2023 10:57:46 +0200 Subject: [PATCH] Bug/api bugs (#76) * API endpoints resources path renamed to plural * API endpoints timeouts defined on single file * `.env` renamed to `example.env` and `.env` excluded from git * Unused database tables removed * Panic during census creation, when the desired strategy has not any tokens fixed * API endpoints result attributes name as 'xxId' or 'id' renamed to 'ID' and `tag` to `tags` * Debug API endpoints removed * API docs updated --- .gitignore | 3 +- README.md | 8 +- api/README.md | 118 +++++++++++++++-------------- api/api.go | 4 - api/censuses.go | 27 ++++--- api/const.go | 15 +++- api/debug.go | 104 ------------------------- api/errors.go | 2 +- api/{strategy.go => strategies.go} | 15 ++-- api/tokens.go | 32 ++++---- api/types.go | 24 +++--- census/census.go | 4 +- db/migrations/0001_census3.sql | 15 +--- db/queries/censuses.sql | 25 ------ db/queries/tokens.sql | 4 +- db/sqlc/censuses.sql.go | 105 ------------------------- db/sqlc/holders.sql.go | 8 +- db/sqlc/models.go | 7 +- db/sqlc/tokens.sql.go | 38 +++++----- .env => example.env | 0 example.sh | 28 +++---- service/holders_scanner.go | 4 +- 22 files changed, 172 insertions(+), 418 deletions(-) delete mode 100644 api/debug.go rename api/{strategy.go => strategies.go} (93%) rename .env => example.env (100%) diff --git a/.gitignore b/.gitignore index a5c89361..d0fa8181 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ .vscode -.env \ No newline at end of file +.env +.trash/ \ No newline at end of file diff --git a/README.md b/README.md index 33d6550e..9b209de5 100644 --- a/README.md +++ b/README.md @@ -117,25 +117,25 @@ docker compose up -d ```sh curl -X POST \ --json '{"id": "0xFE67A4450907459c3e1FFf623aA927dD4e28c67a", "type": "erc20", "chainID": 1}' \ - http://localhost:7788/api/token + http://localhost:7788/api/tokens ``` 2. Wait to that the API service completes the token sync. It could take up to 10-20 minutes, even more, based on the number of holders and transactions. You can check the token sync status getting the token info: ```sh curl -X GET \ - http://localhost:7788/api/token/0xFE67A4450907459c3e1FFf623aA927dD4e28c67a + http://localhost:7788/api/tokens/0xFE67A4450907459c3e1FFf623aA927dD4e28c67a ``` 3. When the API ends, and the token reaches `synced` status (`token.status.synced = true`), its time to create a new census based on the default token strategy. This strategy is created during the token registration and just contains the holders of this token. To create the census with token holders, you need to know the `token.defaultStrategy` (from token info endpoint): ```sh curl -X POST \ --json '{"strategyId": , "anonymous": true}" \ - http://localhost:7788/api/census + http://localhost:7788/api/censuses ``` 4. The last request will return a `queueId` which identifies the census creation and publication processes on the API queue. It will be completed in background. We can check if the task is done, it raised an error or was succesfully completed: ```sh curl -X GET \ - http://localhost:7788/census/queue/ + http://localhost:7788/censuses/queue/ ``` You can check and run the example using the [`example.sh` file](./example.sh): diff --git a/api/README.md b/api/README.md index 444a8ce1..de1696a1 100644 --- a/api/README.md +++ b/api/README.md @@ -28,7 +28,7 @@ Show information about the API service. ## Tokens -### GET `/token` +### GET `/tokens` List of already added tokens. - 📥 response: @@ -37,18 +37,19 @@ List of already added tokens. { "tokens": [ { - "id": "0x1234", + "ID": "0x1234", "name": "Wrapped Aragon Network Token", "type": "erc20|erc721|erc777|erc1155|nation3|wANT", "startBlock": 123456, "symbol": "wANT", - "tag": "testTag1,testTag2" + "tags": "testTag1,testTag2", + "chainID": 1 } ] } ``` -> If `tag` is empty, it will be ommited. +> If `tags` is empty, it will be ommited. - ⚠️ errors: @@ -58,7 +59,7 @@ List of already added tokens. | 500 | `error getting tokens information` | 5005 | | 500 | `error encoding tokens` | 5011 | -### GET `/token/types` +### GET `/tokens/types` List the supported token types. - 📥 response: @@ -78,21 +79,21 @@ List the supported token types. |:---:|:---|:---:| | 500 | `error encoding supported tokens types` | 5012 | -### POST `/token` +### POST `/tokens` Triggers a new scan for the provided token, starting from the defined block. - 📤 request: ```json { - "id": "0x1234", + "ID": "0x1234", "type": "erc20|erc721|erc777|erc1155|nation3|wANT", - "tag": "testTag1,testTag2", + "tags": "testTag1,testTag2", "chainID": 1 } ``` -> `tag` attribute is *optional*. +> `tags` attribute is *optional*. - ⚠️ errors: @@ -105,14 +106,14 @@ Triggers a new scan for the provided token, starting from the defined block. | 500 | `error getting token information` | 5004 | | 500 | `error initialising web3 client` | 5019 | -### GET `/token/{tokenID}` +### GET `/tokens/{tokenID}` Returns the information about the token referenced by the provided ID. - 📥 response: ```json { - "id": "0x1324", + "ID": "0x1324", "type": "erc20", "decimals": 18, "startBlock": 123456, @@ -125,12 +126,12 @@ Returns the information about the token referenced by the provided ID. "progress": 87 }, "defaultStrategy": 1, - "tag": "testTag1,testTag2", + "tags": "testTag1,testTag2", "chainID": 1 } ``` -> If `tag` is empty, it will be ommited. +> If `tags` is empty, it will be ommited. - ⚠️ errors: @@ -138,15 +139,17 @@ Returns the information about the token referenced by the provided ID. |:---:|:---|:---:| | 404 | `no token found` | 4003 | | 500 | `error getting token information` | 5004 | -| 500 | `error initialising web3 client` | 5018 | +| 500 | `error encoding token` | 5010 | +| 500 | `chain ID provided not supported` | 5013 | +| 500 | `error initialising web3 client` | 5019 | +| 500 | `error getting number of token holders` | 5020 | | 500 | `error getting last block number from web3 endpoint` | 5021 | -| 500 | `error encoding tokens` | 5011 | **MVP Warn**: If `defaultStrategy` is `0`, no strategy (neither the dummy strategy) is associated to the given token. ## Strategies -### POST `/strategy` +### POST `/strategies` Stores a new strategy based on the defined combination of tokens provided, these tokens must be registered previously. - 📤 request: @@ -155,19 +158,19 @@ Stores a new strategy based on the defined combination of tokens provided, these { "tokens": [ { - "id": "0x1324", + "ID": "0x1324", "name": "wANT", "minBalance": "10000", "method": "0x8230" }, { - "id": "0x5678", + "ID": "0x5678", "name": "USDC", "minBalance": "20000", "method": "0x3241" }, { - "id": "0x9da2", + "ID": "0x9da2", "name": "ANT", "minBalance": "1", "method": "0x9db1" @@ -181,7 +184,7 @@ Stores a new strategy based on the defined combination of tokens provided, these ```json { - "strategyId": 1 + "strategyID": 1 } ``` @@ -193,7 +196,7 @@ Stores a new strategy based on the defined combination of tokens provided, these | 500 | `error getting strategies information` | 5008 | | 500 | `error encoding strategies` | 5016 | -### GET `/strategy` +### GET `/strategies` Returns the ID's list of the strategies registered. - 📥 response: @@ -212,7 +215,7 @@ Returns the ID's list of the strategies registered. | 500 | `error getting strategies information` | 5008 | | 500 | `error encoding strategies` | 5016 | -### GET `/strategy/{strategyId}` +### GET `/strategies/{strategyID}` Returns the information of the strategy related to the provided ID. - 📥 response: @@ -222,19 +225,19 @@ Returns the information of the strategy related to the provided ID. "id": 2, "tokens": [ { - "id": "0x1324", + "ID": "0x1324", "name": "wANT", "minBalance": "10000", "method": "0x8230" }, { - "id": "0x5678", + "ID": "0x5678", "name": "USDC", "minBalance": "20000", "method": "0x3241" }, { - "id": "0x9da2", + "ID": "0x9da2", "name": "ANT", "minBalance": "1", "method": "0x9db1" @@ -248,13 +251,13 @@ Returns the information of the strategy related to the provided ID. | HTTP Status | Message | Internal error | |:---:|:---|:---:| -| 204 | `-` | 4002 | +| 400 | `malformed strategy ID, it must be an integer` | 4002 | | 404 | `no strategy found with the ID provided` | 4005 | | 500 | `error getting tokens information` | 5005 | | 500 | `error getting strategy information` | 5007 | | 500 | `error encoding strategy` | 5015 | -### GET `/strategy/token/{tokenID}` +### GET `/strategies/token/{tokenID}` Returns ID's of the already created strategies including the `tokenAddress` provided. - 📥 response: @@ -273,36 +276,16 @@ Returns ID's of the already created strategies including the `tokenAddress` prov | 500 | `error getting strategies information` | 5008 | | 500 | `error encoding strategies` | 5016 | -### GET `/census/strategy/{strategyId}` -Returns a list of censusID for the strategy provided. - -- 📥 response: - -```json -{ - "censuses": [ 3, 5 ] -} -``` - -- ⚠️ errors: - -| HTTP Status | Message | Internal error | -|:---:|:---|:---:| -| 204 | `-` | 4007 | -| 404 | `census not found` | 4006 | -| 500 | `error getting census information` | 5009 | -| 500 | `error encoding censuses` | 5018 | - ## Censuses -### POST `/census` +### POST `/censuses` Request the creation of a new census with the strategy provided for the `blockNumber` provided and returns the census ID. - 📤 request: ```json { - "strategyId": 1, + "strategyID": 1, "blockNumber": 123456, "anonymous": false } @@ -312,7 +295,7 @@ Request the creation of a new census with the strategy provided for the `blockNu ```json { - "queueId": "0123456789abcdef0123456789abcdef01234567" + "queueID": "0123456789abcdef0123456789abcdef01234567" } ``` @@ -321,21 +304,20 @@ Request the creation of a new census with the strategy provided for the `blockNu | HTTP Status | Message | Internal error | |:---:|:---|:---:| | 400 | `malformed strategy ID, it must be an integer` | 4002 | -| 500 | `error encoding strategy holders` | 5014 | +| 500 | `error encoding census` | 5017 | -### GET `/census/{censusId}` +### GET `/censuses/{censusID}` Returns the information of the snapshots related to the provided ID. - 📥 response: ```json { - "censusId": 2, - "strategyId": 1, + "censusID": 2, + "strategyID": 1, "merkleRoot": "e3cb8941e25dcdb36fc21acbe5f6c5a42e0d4f89839ae94952f0ebbd9acd04ac", "uri": "ipfs://Qma....", "size": 1000, "weight": "200000000000000000000", - "chainId": 1, "anonymous": true } ``` @@ -344,13 +326,12 @@ Returns the information of the snapshots related to the provided ID. | HTTP Status | Message | Internal error | |:---:|:---|:---:| -| 204 | `-` | 4007 | | 400 | `malformed census ID, it must be a integer` | 4001 | | 404 | `census not found` | 4006 | | 500 | `error getting census information` | 5009 | | 500 | `error encoding census` | 5017 | -### GET `/census/queue/{queueId}` +### GET `/census/queue/{queueID}` Returns the information of the census that are in the creation queue. - 📥 response: @@ -369,7 +350,28 @@ Returns the information of the census that are in the creation queue. | HTTP Status | Message | Internal error | |:---:|:---|:---:| -| 400 | `malformed queue ID` | 4010 | | 404 | `census not found` | 4006 | +| 400 | `malformed queue ID` | 4011 | | 500 | `error getting census information` | 5009 | | 500 | `error encoding census queue item` | 5022 | + +### GET `/census/strategy/{strategyID}` +Returns a list of censusID for the strategy provided. + +- 📥 response: + +```json +{ + "censuses": [ 3, 5 ] +} +``` + +- ⚠️ errors: + +| HTTP Status | Message | Internal error | +|:---:|:---|:---:| +| 204 | `-` | 4007 | +| 400 | `malformed census ID, it must be a integer` | 4001 | +| 404 | `census not found` | 4006 | +| 500 | `error getting census information` | 5009 | +| 500 | `error encoding censuses` | 5018 | \ No newline at end of file diff --git a/api/api.go b/api/api.go index 6d5ae1a4..2e7b56d3 100644 --- a/api/api.go +++ b/api/api.go @@ -65,10 +65,6 @@ func Init(db *db.DB, conf Census3APIConf) error { if err := newAPI.initStrategiesHandlers(); err != nil { return err } - // TODO: Only for the MVP, remove it. - if err := newAPI.initDebugHandlers(); err != nil { - return err - } return nil } diff --git a/api/censuses.go b/api/censuses.go index e37c0f58..dd32bbbc 100644 --- a/api/censuses.go +++ b/api/censuses.go @@ -7,7 +7,6 @@ import ( "errors" "math/big" "strconv" - "time" "github.com/ethereum/go-ethereum/common" "github.com/vocdoni/census3/census" @@ -18,19 +17,19 @@ import ( ) func (capi *census3API) initCensusHandlers() error { - if err := capi.endpoint.RegisterMethod("/census/{censusID}", "GET", + if err := capi.endpoint.RegisterMethod("/censuses/{censusID}", "GET", api.MethodAccessTypePublic, capi.getCensus); err != nil { return err } - if err := capi.endpoint.RegisterMethod("/census", "POST", + if err := capi.endpoint.RegisterMethod("/censuses", "POST", api.MethodAccessTypePublic, capi.launchCensusCreation); err != nil { return err } - if err := capi.endpoint.RegisterMethod("/census/queue/{queueID}", "GET", + if err := capi.endpoint.RegisterMethod("/censuses/queue/{queueID}", "GET", api.MethodAccessTypePublic, capi.enqueueCensus); err != nil { return err } - return capi.endpoint.RegisterMethod("/census/strategy/{strategyID}", "GET", + return capi.endpoint.RegisterMethod("/censuses/strategy/{strategyID}", "GET", api.MethodAccessTypePublic, capi.getStrategyCensuses) } @@ -42,7 +41,7 @@ func (capi *census3API) getCensus(msg *api.APIdata, ctx *httprouter.HTTPContext) return ErrMalformedCensusID } censusID := uint64(iCensusID) - internalCtx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + internalCtx, cancel := context.WithTimeout(context.Background(), getCensusTimeout) defer cancel() currentCensus, err := capi.db.QueriesRO.CensusByID(internalCtx, censusID) if err != nil { @@ -111,10 +110,10 @@ func (capi *census3API) launchCensusCreation(msg *api.APIdata, ctx *httprouter.H // the census merkle tree on IPFS. Then saves the resulting information of the // census tree in the database. func (capi *census3API) createAndPublishCensus(req *CreateCensusRequest, qID string) (uint64, error) { - bgCtx, cancel := context.WithTimeout(context.Background(), censusCreationTimeout) + internalCtx, cancel := context.WithTimeout(context.Background(), createAndPublishCensusTimeout) defer cancel() // begin a transaction for group sql queries - tx, err := capi.db.RW.BeginTx(bgCtx, nil) + tx, err := capi.db.RW.BeginTx(internalCtx, nil) if err != nil { return 0, ErrCantCreateCensus.WithErr(err) } @@ -125,7 +124,7 @@ func (capi *census3API) createAndPublishCensus(req *CreateCensusRequest, qID str }() qtx := capi.db.QueriesRW.WithTx(tx) - strategyTokens, err := qtx.TokensByStrategyID(bgCtx, req.StrategyID) + strategyTokens, err := qtx.TokensByStrategyID(internalCtx, req.StrategyID) if err != nil { if errors.Is(sql.ErrNoRows, err) { return 0, ErrNoStrategyTokens.WithErr(err) @@ -139,7 +138,7 @@ func (capi *census3API) createAndPublishCensus(req *CreateCensusRequest, qID str // compute the new censusId and censusType newCensusID := census.InnerCensusID(req.BlockNumber, req.StrategyID, req.Anonymous) // check if the census already exists - _, err = qtx.CensusByID(bgCtx, newCensusID) + _, err = qtx.CensusByID(internalCtx, newCensusID) if err != nil { if !errors.Is(sql.ErrNoRows, err) { return 0, ErrCantCreateCensus.WithErr(err) @@ -158,7 +157,7 @@ func (capi *census3API) createAndPublishCensus(req *CreateCensusRequest, qID str censusWeight := new(big.Int) strategyHolders := map[common.Address]*big.Int{} for _, token := range strategyTokens { - holders, err := qtx.TokenHoldersByTokenID(bgCtx, token.ID) + holders, err := qtx.TokenHoldersByTokenID(internalCtx, token.ID) if err != nil { if errors.Is(sql.ErrNoRows, err) { continue @@ -199,7 +198,7 @@ func (capi *census3API) createAndPublishCensus(req *CreateCensusRequest, qID str if err := sqlCensusWeight.Scan(censusWeight.String()); err != nil { return 0, ErrCantCreateCensus.WithErr(err) } - _, err = qtx.CreateCensus(bgCtx, queries.CreateCensusParams{ + _, err = qtx.CreateCensus(internalCtx, queries.CreateCensusParams{ ID: newCensus.ID, StrategyID: req.StrategyID, CensusType: uint64(censusType), @@ -241,7 +240,7 @@ func (capi *census3API) enqueueCensus(msg *api.APIdata, ctx *httprouter.HTTPCont // check if it is not finished or some error occurred if done && err == nil { // if everything is ok, get the census information an return it - internalCtx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + internalCtx, cancel := context.WithTimeout(context.Background(), enqueueCensusCreationTimeout) defer cancel() censusID, ok := data["censusID"].(uint64) if !ok { @@ -289,7 +288,7 @@ func (capi *census3API) getStrategyCensuses(msg *api.APIdata, ctx *httprouter.HT return ErrMalformedCensusID.WithErr(err) } // get censuses by this strategy ID - internalCtx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + internalCtx, cancel := context.WithTimeout(context.Background(), getStrategyCensusesTimeout) defer cancel() rows, err := capi.db.QueriesRO.CensusByStrategyID(internalCtx, uint64(strategyID)) if err != nil { diff --git a/api/const.go b/api/const.go index 6169f169..e954005f 100644 --- a/api/const.go +++ b/api/const.go @@ -3,5 +3,18 @@ package api import "time" const ( - censusCreationTimeout = 10 * time.Minute + // censuses + getCensusTimeout = time.Second * 10 + createAndPublishCensusTimeout = time.Minute * 10 + enqueueCensusCreationTimeout = time.Second * 10 + getStrategyCensusesTimeout = time.Second * 10 + // strategies + createDummyStrategyTimeout = time.Second * 10 + getStrategiesTimeout = time.Second * 10 + getStrategyTimeout = time.Second * 10 + getTokensStrategyTimeout = time.Second * 10 + // tokens + getTokensTimeout = time.Second * 10 + createTokenTimeout = time.Second * 10 + getTokenTimeout = time.Second * 15 ) diff --git a/api/debug.go b/api/debug.go deleted file mode 100644 index e81287f0..00000000 --- a/api/debug.go +++ /dev/null @@ -1,104 +0,0 @@ -package api - -import ( - "context" - "database/sql" - "encoding/json" - "errors" - "math/big" - "time" - - "github.com/ethereum/go-ethereum/common" - "go.vocdoni.io/dvote/httprouter" - api "go.vocdoni.io/dvote/httprouter/apirest" - "go.vocdoni.io/dvote/log" -) - -// TODO: Only for the MVP, remove it. -func (capi *census3API) initDebugHandlers() error { - if err := capi.endpoint.RegisterMethod("/debug/token/{address}/holders", "GET", - api.MethodAccessTypePublic, capi.getTokenHolders); err != nil { - return err - } - if err := capi.endpoint.RegisterMethod("/debug/token/{address}/holders/count", "GET", - api.MethodAccessTypePublic, capi.countHolders); err != nil { - return err - } - return nil -} - -// getTokenHolders handler function gets the token holders states from the -// database, of the token identified by the contract address provided. -// -// TODO: Only for the MVP, remove it. -func (capi *census3API) getTokenHolders(msg *api.APIdata, ctx *httprouter.HTTPContext) error { - ctx2, cancel := context.WithTimeout(context.Background(), 10*time.Second) - defer cancel() - - // get token holders from the database - addr := common.HexToAddress(ctx.URLParam("address")) - dbHolders, err := capi.db.QueriesRO.TokenHoldersByTokenID(ctx2, addr.Bytes()) - if err != nil { - // if database does not contain any token holder for this token, return - // no content, else return generic error. - if errors.Is(sql.ErrNoRows, err) { - log.Errorf("no holders found for address %s: %s", addr, err.Error()) - return ctx.Send(nil, api.HTTPstatusNoContent) - } - log.Errorf("error getting token with address %s: %s", addr, err.Error()) - return ErrCantGetTokenHolders.Withf("error getting token with address %s", addr) - } - // if no error but the results are empty, return no content - if len(dbHolders) == 0 { - log.Errorf("no holders found for address %s", addr) - return ctx.Send(nil, api.HTTPstatusNoContent) - } - // encode the response with the token holders addresses - holders := TokenHoldersResponse{Holders: map[string]string{}} - for _, holder := range dbHolders { - addr := common.BytesToAddress(holder.ID).String() - balance := new(big.Int).SetBytes(holder.Balance) - holders.Holders[addr] = balance.String() - } - response, err := json.Marshal(holders) - if err != nil { - log.Errorf("error marshalling holder of %s: %s", addr, err.Error()) - return ErrEncodeTokenHolders.Withf("error marshalling holder of %s", addr) - } - return ctx.Send(response, api.HTTPstatusOK) -} - -// countHolders handler function returns the current number of token holders -// for the provided token address in the current database. -// -// TODO: Only for the MVP, remove it. -func (capi *census3API) countHolders(msg *api.APIdata, ctx *httprouter.HTTPContext) error { - ctx2, cancel := context.WithTimeout(context.Background(), 10*time.Second) - defer cancel() - - addr := common.HexToAddress(ctx.URLParam("address")) - numberOfHolders, err := capi.db.QueriesRO.CountTokenHoldersByTokenID(ctx2, addr.Bytes()) - if err != nil { - if errors.Is(sql.ErrNoRows, err) { - log.Errorf("no holders found for address %s: %s", addr, err.Error()) - return ctx.Send(nil, api.HTTPstatusNoContent) - } - log.Errorf("error getting holders of %s: %s", addr, err.Error()) - return ErrCantGetTokenHolders.Withf("token address: %s", addr) - } - // if no error but the results are empty, return no content - if numberOfHolders == 0 { - log.Errorf("no holders found for address %s: %s", addr, err.Error()) - return ctx.Send(nil, api.HTTPstatusNoContent) - } - response, err := json.Marshal(struct { - Count int64 `json:"count"` - }{ - Count: numberOfHolders, - }) - if err != nil { - log.Errorf("error marshalling holder of %s: %s", addr, err.Error()) - return ErrEncodeTokenHolders.Withf("token address: %s", addr) - } - return ctx.Send(response, api.HTTPstatusOK) -} diff --git a/api/errors.go b/api/errors.go index 807d6677..2b58c489 100644 --- a/api/errors.go +++ b/api/errors.go @@ -181,7 +181,7 @@ var ( ErrCantGetTokenCount = apirest.APIerror{ Code: 5020, HTTPstatus: apirest.HTTPstatusInternalErr, - Err: fmt.Errorf("error counting census size"), + Err: fmt.Errorf("error getting number of token holders"), } ErrCantGetLastBlockNumber = apirest.APIerror{ Code: 5021, diff --git a/api/strategy.go b/api/strategies.go similarity index 93% rename from api/strategy.go rename to api/strategies.go index 84e879a0..e15ca818 100644 --- a/api/strategy.go +++ b/api/strategies.go @@ -7,7 +7,6 @@ import ( "errors" "math/big" "strconv" - "time" "github.com/ethereum/go-ethereum/common" queries "github.com/vocdoni/census3/db/sqlc" @@ -16,15 +15,15 @@ import ( ) func (capi *census3API) initStrategiesHandlers() error { - if err := capi.endpoint.RegisterMethod("/strategy/", "GET", + if err := capi.endpoint.RegisterMethod("/strategies", "GET", api.MethodAccessTypePublic, capi.getStrategies); err != nil { return err } - if err := capi.endpoint.RegisterMethod("/strategy/{strategyID}", "GET", + if err := capi.endpoint.RegisterMethod("/strategies/{strategyID}", "GET", api.MethodAccessTypePublic, capi.getStrategy); err != nil { return err } - return capi.endpoint.RegisterMethod("/strategy/token/{tokenID}", "GET", + return capi.endpoint.RegisterMethod("/strategies/token/{tokenID}", "GET", api.MethodAccessTypePublic, capi.getTokenStrategies) } @@ -34,7 +33,7 @@ func (capi *census3API) initStrategiesHandlers() error { // // TODO: Only for the MVP, remove it. func (capi *census3API) createDummyStrategy(tokenID []byte) error { - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + ctx, cancel := context.WithTimeout(context.Background(), createDummyStrategyTimeout) defer cancel() res, err := capi.db.QueriesRW.CreateStategy(ctx, "test") if err != nil { @@ -57,7 +56,7 @@ func (capi *census3API) createDummyStrategy(tokenID []byte) error { // the database. It returns a 204 response if any strategy is registered or a // 500 error if something fails. func (capi *census3API) getStrategies(msg *api.APIdata, ctx *httprouter.HTTPContext) error { - internalCtx, cancel := context.WithTimeout(context.Background(), time.Second*10) + internalCtx, cancel := context.WithTimeout(context.Background(), getStrategiesTimeout) defer cancel() // TODO: Support for pagination // get strategies from the database @@ -95,7 +94,7 @@ func (capi *census3API) getStrategy(msg *api.APIdata, ctx *httprouter.HTTPContex } strategyID := uint64(iStrategyID) // get strategy from the database - internalCtx, cancel := context.WithTimeout(context.Background(), time.Second*10) + internalCtx, cancel := context.WithTimeout(context.Background(), getStrategyTimeout) defer cancel() strategyData, err := capi.db.QueriesRO.StrategyByID(internalCtx, strategyID) if err != nil { @@ -138,7 +137,7 @@ func (capi *census3API) getStrategy(msg *api.APIdata, ctx *httprouter.HTTPContex func (capi *census3API) getTokenStrategies(msg *api.APIdata, ctx *httprouter.HTTPContext) error { // get the tokenID provided tokenID := ctx.URLParam("tokenID") - internalCtx, cancel := context.WithTimeout(context.Background(), time.Second*10) + internalCtx, cancel := context.WithTimeout(context.Background(), getTokensStrategyTimeout) defer cancel() // get strategies associated to the token provided rows, err := capi.db.QueriesRO.StrategiesByTokenID(internalCtx, common.HexToAddress(tokenID).Bytes()) diff --git a/api/tokens.go b/api/tokens.go index 48e9cad2..a0ecf724 100644 --- a/api/tokens.go +++ b/api/tokens.go @@ -7,7 +7,6 @@ import ( "errors" "math/big" "strings" - "time" "github.com/ethereum/go-ethereum/common" queries "github.com/vocdoni/census3/db/sqlc" @@ -18,19 +17,19 @@ import ( ) func (capi *census3API) initTokenHandlers() error { - if err := capi.endpoint.RegisterMethod("/token", "GET", + if err := capi.endpoint.RegisterMethod("/tokens", "GET", api.MethodAccessTypePublic, capi.getTokens); err != nil { return err } - if err := capi.endpoint.RegisterMethod("/token", "POST", + if err := capi.endpoint.RegisterMethod("/tokens", "POST", api.MethodAccessTypePublic, capi.createToken); err != nil { return err } - if err := capi.endpoint.RegisterMethod("/token/{tokenID}", "GET", + if err := capi.endpoint.RegisterMethod("/tokens/{tokenID}", "GET", api.MethodAccessTypePublic, capi.getToken); err != nil { return err } - return capi.endpoint.RegisterMethod("/token/types", "GET", + return capi.endpoint.RegisterMethod("/tokens/types", "GET", api.MethodAccessTypePublic, capi.getTokenTypes) } @@ -38,7 +37,7 @@ func (capi *census3API) initTokenHandlers() error { // database. It returns a 204 response if no tokens are registered or a 500 // error if something fails. func (capi *census3API) getTokens(msg *api.APIdata, ctx *httprouter.HTTPContext) error { - internalCtx, cancel := context.WithTimeout(context.Background(), time.Second*10) + internalCtx, cancel := context.WithTimeout(context.Background(), getTokensTimeout) defer cancel() // TODO: Support for pagination // get tokens from the database @@ -60,8 +59,9 @@ func (capi *census3API) getTokens(msg *api.APIdata, ctx *httprouter.HTTPContext) Type: state.TokenType(int(tokenData.TypeID)).String(), Name: tokenData.Name.String, StartBlock: tokenData.CreationBlock.Int64, - Tag: tokenData.Tag.String, + Tags: tokenData.Tags.String, Symbol: tokenData.Symbol.String, + ChainID: tokenData.ChainID, } tokens.Tokens = append(tokens.Tokens, tokenResponse) } @@ -88,7 +88,7 @@ func (capi *census3API) createToken(msg *api.APIdata, ctx *httprouter.HTTPContex // init web3 client to get the token information before register in the // database w3 := state.Web3{} - internalCtx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + internalCtx, cancel := context.WithTimeout(context.Background(), createTokenTimeout) defer cancel() // get correct web3 uri provider w3uri, exists := capi.w3p[req.ChainID] @@ -108,7 +108,7 @@ func (capi *census3API) createToken(msg *api.APIdata, ctx *httprouter.HTTPContex symbol = new(sql.NullString) creationBlock = new(sql.NullInt64) totalSupply = new(big.Int) - tag = new(sql.NullString) + tags = new(sql.NullString) ) if err := name.Scan(info.Name); err != nil { return ErrCantGetToken.WithErr(err) @@ -119,8 +119,8 @@ func (capi *census3API) createToken(msg *api.APIdata, ctx *httprouter.HTTPContex if info.TotalSupply != nil { totalSupply = info.TotalSupply } - if req.Tag != "" { - if err := tag.Scan(req.Tag); err != nil { + if req.Tags != "" { + if err := tags.Scan(req.Tags); err != nil { return ErrCantGetToken.WithErr(err) } } @@ -133,7 +133,7 @@ func (capi *census3API) createToken(msg *api.APIdata, ctx *httprouter.HTTPContex CreationBlock: *creationBlock, TypeID: uint64(tokenType), Synced: false, - Tag: *tag, + Tags: *tags, ChainID: req.ChainID, }) if err != nil { @@ -155,7 +155,7 @@ func (capi *census3API) createToken(msg *api.APIdata, ctx *httprouter.HTTPContex // fails. func (capi *census3API) getToken(msg *api.APIdata, ctx *httprouter.HTTPContext) error { address := common.HexToAddress(ctx.URLParam("tokenID")) - internalCtx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + internalCtx, cancel := context.WithTimeout(context.Background(), getTokenTimeout) defer cancel() tokenData, err := capi.db.QueriesRO.TokenByID(internalCtx, address.Bytes()) if err != nil { @@ -204,9 +204,7 @@ func (capi *census3API) getToken(msg *api.APIdata, ctx *httprouter.HTTPContext) } // get token holders count - countHoldersCtx, cancel2 := context.WithTimeout(context.Background(), 5*time.Second) - defer cancel2() - holders, err := capi.db.QueriesRO.CountTokenHoldersByTokenID(countHoldersCtx, address.Bytes()) + holders, err := capi.db.QueriesRO.CountTokenHoldersByTokenID(internalCtx, address.Bytes()) if err != nil { return ErrCantGetTokenCount.WithErr(err) } @@ -225,8 +223,8 @@ func (capi *census3API) getToken(msg *api.APIdata, ctx *httprouter.HTTPContext) Synced: tokenData.Synced, Progress: tokenProgress, }, + Tags: tokenData.Tags.String, // TODO: Only for the MVP, consider to remove it - Tag: tokenData.Tag.String, DefaultStrategy: defaultStrategyID, ChainID: tokenData.ChainID, } diff --git a/api/types.go b/api/types.go index d5803180..9b625a99 100644 --- a/api/types.go +++ b/api/types.go @@ -1,9 +1,9 @@ package api type CreateTokenRequest struct { - ID string `json:"id"` + ID string `json:"ID"` Type string `json:"type"` - Tag string `json:"tag"` + Tags string `json:"tags"` ChainID uint64 `json:"chainID"` } @@ -14,7 +14,7 @@ type GetTokenStatusResponse struct { } type GetTokenResponse struct { - ID string `json:"id"` + ID string `json:"ID"` Type string `json:"type"` Decimals uint64 `json:"decimals"` StartBlock uint64 `json:"startBlock"` @@ -24,17 +24,17 @@ type GetTokenResponse struct { Status *GetTokenStatusResponse `json:"status"` Size uint64 `json:"size"` DefaultStrategy uint64 `json:"defaultStrategy,omitempty"` - Tag string `json:"tag,omitempty"` + Tags string `json:"tags,omitempty"` ChainID uint64 `json:"chainID"` } type GetTokensItem struct { - ID string `json:"id"` + ID string `json:"ID"` Type string `json:"type"` StartBlock int64 `json:"startBlock"` Name string `json:"name"` Symbol string `json:"symbol"` - Tag string `json:"tag,omitempty"` + Tags string `json:"tags,omitempty"` ChainID uint64 `json:"chainID"` } @@ -51,18 +51,18 @@ type TokenHoldersResponse struct { } type CreateCensusRequest struct { - StrategyID uint64 `json:"strategyId"` + StrategyID uint64 `json:"strategyID"` BlockNumber uint64 `json:"blockNumber"` Anonymous bool `json:"anonymous"` } type CreateCensusResponse struct { - QueueID string `json:"queueId"` + QueueID string `json:"queueID"` } type GetCensusResponse struct { - CensusID uint64 `json:"censusId"` - StrategyID uint64 `json:"strategyId"` + CensusID uint64 `json:"ID"` + StrategyID uint64 `json:"strategyID"` MerkleRoot string `json:"merkleRoot"` URI string `json:"uri"` Size uint64 `json:"size"` @@ -79,14 +79,14 @@ type GetStrategiesResponse struct { } type GetStrategyToken struct { - ID string `json:"id"` + ID string `json:"ID"` Name string `json:"name"` MinBalance string `json:"minBalance"` Method string `json:"method"` } type GetStrategyResponse struct { - ID uint64 `json:"id"` + ID uint64 `json:"ID"` Tokens []GetStrategyToken `json:"tokens"` Predicate string `json:"strategy"` } diff --git a/census/census.go b/census/census.go index 7e9d985f..15cd49ca 100644 --- a/census/census.go +++ b/census/census.go @@ -249,10 +249,8 @@ func censusDBKey(censusID uint64) string { // represented as 1 for true and 0 for false. This concatenated string is then converted // to a uint64 to create a unique identifier. func InnerCensusID(blockNumber, strategyID uint64, anonymous bool) uint64 { - // Force this to ensurte that can be stored in an int64 max but store into a uint64 - // Convert the boolean to a uint32: 1 for true, 0 for false - var anonymousUint uint32 + var anonymousUint uint64 if anonymous { anonymousUint = 1 } diff --git a/db/migrations/0001_census3.sql b/db/migrations/0001_census3.sql index c2875df5..5e9b995b 100644 --- a/db/migrations/0001_census3.sql +++ b/db/migrations/0001_census3.sql @@ -25,7 +25,7 @@ CREATE TABLE tokens ( creation_block BIGINT, type_id INTEGER NOT NULL, synced BOOLEAN NOT NULL, - tag TEXT, + tags TEXT, chain_id INTEGER NOT NULL, UNIQUE (id, chain_id), FOREIGN KEY (type_id) REFERENCES token_types(id) ON DELETE CASCADE @@ -82,19 +82,7 @@ CREATE TABLE strategy_tokens ( CREATE INDEX idx_strategy_tokens_strategy_id ON strategy_tokens(strategy_id); CREATE INDEX idx_strategy_tokens_token_id ON strategy_tokens(token_id); -CREATE TABLE census_blocks ( - census_id INTEGER NOT NULL, - block_id INTEGER NOT NULL, - PRIMARY KEY (census_id, block_id), - FOREIGN KEY (census_id) REFERENCES censuses(id) ON DELETE CASCADE, - FOREIGN KEY (block_id) REFERENCES blocks(id) ON DELETE CASCADE -); -CREATE INDEX idx_census_blocks_census_id ON census_blocks(census_id); -CREATE INDEX idx_census_blocks_block_id ON census_blocks(block_id); - -- +goose Down -DROP INDEX IF EXISTS idx_census_blocks_block_id; -DROP INDEX IF EXISTS idx_census_blocks_census_id; DROP INDEX IF EXISTS idx_strategy_tokens_token_id; DROP INDEX IF EXISTS idx_strategy_tokens_strategy_id; DROP INDEX IF EXISTS idx_token_holders_block_id; @@ -103,7 +91,6 @@ DROP INDEX IF EXISTS idx_token_holders_token_id; DROP INDEX IF EXISTS idx_censuses_strategy_id; DROP INDEX IF EXISTS idx_tokens_type_id; -DROP TABLE IF EXISTS census_blocks; DROP TABLE IF EXISTS strategy_tokens; DROP TABLE IF EXISTS token_holders; DROP TABLE IF EXISTS holders; diff --git a/db/queries/censuses.sql b/db/queries/censuses.sql index 20f98e4e..726e421f 100644 --- a/db/queries/censuses.sql +++ b/db/queries/censuses.sql @@ -21,12 +21,6 @@ SELECT * FROM censuses WHERE queue_id = ? LIMIT 1; --- name: CensusesByStrategyIDAndBlockID :many -SELECT c.* FROM censuses c -JOIN census_blocks cb ON c.id = cb.census_id -WHERE c.strategy_id = sqlc.arg(strategy_id) AND cb.block_id = sqlc.arg(block_id) -LIMIT ? OFFSET ?; - -- name: CensusByURI :one SELECT * FROM censuses WHERE uri = ? @@ -77,22 +71,3 @@ SET merkle_root = sqlc.arg(merkle_root), size = sqlc.arg(size), weight = sqlc.arg(weight) WHERE id = sqlc.arg(id); - --- name: CreateCensusBlock :execresult -INSERT INTO census_blocks ( - census_id, - block_id -) -VALUES ( - ?, ? -); - --- name: DeleteCensusBlock :execresult -DELETE FROM census_blocks -WHERE census_id = ? AND block_id = ?; - --- name: UpdateCensusBlock :execresult -UPDATE census_blocks -SET census_id = sqlc.arg(census_id), - block_id = sqlc.arg(block_id) -WHERE census_id = sqlc.arg(census_id) AND block_id = sqlc.arg(block_id); \ No newline at end of file diff --git a/db/queries/tokens.sql b/db/queries/tokens.sql index b21a3b21..0bc45ca7 100644 --- a/db/queries/tokens.sql +++ b/db/queries/tokens.sql @@ -38,7 +38,7 @@ INSERT INTO tokens ( creation_block, type_id, synced, - tag, + tags, chain_id ) VALUES ( @@ -54,7 +54,7 @@ SET name = sqlc.arg(name), creation_block = sqlc.arg(creation_block), type_id = sqlc.arg(type_id), synced = sqlc.arg(synced), - tag = sqlc.arg(tag) + tags = sqlc.arg(tags) WHERE id = sqlc.arg(id); -- name: UpdateTokenStatus :execresult diff --git a/db/sqlc/censuses.sql.go b/db/sqlc/censuses.sql.go index aa93df2d..c73c30bf 100644 --- a/db/sqlc/censuses.sql.go +++ b/db/sqlc/censuses.sql.go @@ -137,57 +137,6 @@ func (q *Queries) CensusByURI(ctx context.Context, uri sql.NullString) (Censuse, return i, err } -const censusesByStrategyIDAndBlockID = `-- name: CensusesByStrategyIDAndBlockID :many -SELECT c.id, c.strategy_id, c.merkle_root, c.uri, c.size, c.weight, c.census_type, c.queue_id FROM censuses c -JOIN census_blocks cb ON c.id = cb.census_id -WHERE c.strategy_id = ? AND cb.block_id = ? -LIMIT ? OFFSET ? -` - -type CensusesByStrategyIDAndBlockIDParams struct { - StrategyID uint64 - BlockID uint64 - Limit int32 - Offset int32 -} - -func (q *Queries) CensusesByStrategyIDAndBlockID(ctx context.Context, arg CensusesByStrategyIDAndBlockIDParams) ([]Censuse, error) { - rows, err := q.db.QueryContext(ctx, censusesByStrategyIDAndBlockID, - arg.StrategyID, - arg.BlockID, - arg.Limit, - arg.Offset, - ) - if err != nil { - return nil, err - } - defer rows.Close() - var items []Censuse - for rows.Next() { - var i Censuse - if err := rows.Scan( - &i.ID, - &i.StrategyID, - &i.MerkleRoot, - &i.Uri, - &i.Size, - &i.Weight, - &i.CensusType, - &i.QueueID, - ); err != nil { - return nil, err - } - items = append(items, i) - } - if err := rows.Close(); err != nil { - return nil, err - } - if err := rows.Err(); err != nil { - return nil, err - } - return items, nil -} - const censusesByTokenID = `-- name: CensusesByTokenID :many SELECT c.id, c.strategy_id, c.merkle_root, c.uri, c.size, c.weight, c.census_type, c.queue_id FROM censuses AS c JOIN strategy_tokens AS st ON c.strategy_id = st.strategy_id @@ -313,25 +262,6 @@ func (q *Queries) CreateCensus(ctx context.Context, arg CreateCensusParams) (sql ) } -const createCensusBlock = `-- name: CreateCensusBlock :execresult -INSERT INTO census_blocks ( - census_id, - block_id -) -VALUES ( - ?, ? -) -` - -type CreateCensusBlockParams struct { - CensusID uint64 - BlockID uint64 -} - -func (q *Queries) CreateCensusBlock(ctx context.Context, arg CreateCensusBlockParams) (sql.Result, error) { - return q.db.ExecContext(ctx, createCensusBlock, arg.CensusID, arg.BlockID) -} - const deleteCensus = `-- name: DeleteCensus :execresult DELETE FROM censuses WHERE id = ? @@ -341,20 +271,6 @@ func (q *Queries) DeleteCensus(ctx context.Context, id uint64) (sql.Result, erro return q.db.ExecContext(ctx, deleteCensus, id) } -const deleteCensusBlock = `-- name: DeleteCensusBlock :execresult -DELETE FROM census_blocks -WHERE census_id = ? AND block_id = ? -` - -type DeleteCensusBlockParams struct { - CensusID uint64 - BlockID uint64 -} - -func (q *Queries) DeleteCensusBlock(ctx context.Context, arg DeleteCensusBlockParams) (sql.Result, error) { - return q.db.ExecContext(ctx, deleteCensusBlock, arg.CensusID, arg.BlockID) -} - const lastCensusID = `-- name: LastCensusID :one SELECT id FROM censuses @@ -432,24 +348,3 @@ func (q *Queries) UpdateCensus(ctx context.Context, arg UpdateCensusParams) (sql arg.ID, ) } - -const updateCensusBlock = `-- name: UpdateCensusBlock :execresult -UPDATE census_blocks -SET census_id = ?, - block_id = ? -WHERE census_id = ? AND block_id = ? -` - -type UpdateCensusBlockParams struct { - CensusID uint64 - BlockID uint64 -} - -func (q *Queries) UpdateCensusBlock(ctx context.Context, arg UpdateCensusBlockParams) (sql.Result, error) { - return q.db.ExecContext(ctx, updateCensusBlock, - arg.CensusID, - arg.BlockID, - arg.CensusID, - arg.BlockID, - ) -} diff --git a/db/sqlc/holders.sql.go b/db/sqlc/holders.sql.go index 95dc982e..c03e5c52 100644 --- a/db/sqlc/holders.sql.go +++ b/db/sqlc/holders.sql.go @@ -373,7 +373,7 @@ func (q *Queries) TokenHoldersByTokenIDAndMinBalance(ctx context.Context, arg To } const tokensByHolderID = `-- name: TokensByHolderID :many -SELECT tokens.id, tokens.name, tokens.symbol, tokens.decimals, tokens.total_supply, tokens.creation_block, tokens.type_id, tokens.synced, tokens.tag, tokens.chain_id +SELECT tokens.id, tokens.name, tokens.symbol, tokens.decimals, tokens.total_supply, tokens.creation_block, tokens.type_id, tokens.synced, tokens.tags, tokens.chain_id FROM Tokens JOIN token_holders ON tokens.id = token_holders.token_id WHERE token_holders.holder_id = ? @@ -397,7 +397,7 @@ func (q *Queries) TokensByHolderID(ctx context.Context, holderID []byte) ([]Toke &i.CreationBlock, &i.TypeID, &i.Synced, - &i.Tag, + &i.Tags, &i.ChainID, ); err != nil { return nil, err @@ -414,7 +414,7 @@ func (q *Queries) TokensByHolderID(ctx context.Context, holderID []byte) ([]Toke } const tokensByHolderIDAndBlockID = `-- name: TokensByHolderIDAndBlockID :many -SELECT tokens.id, tokens.name, tokens.symbol, tokens.decimals, tokens.total_supply, tokens.creation_block, tokens.type_id, tokens.synced, tokens.tag, tokens.chain_id +SELECT tokens.id, tokens.name, tokens.symbol, tokens.decimals, tokens.total_supply, tokens.creation_block, tokens.type_id, tokens.synced, tokens.tags, tokens.chain_id FROM Tokens JOIN token_holders ON tokens.id = token_holders.token_id WHERE token_holders.holder_id = ? AND token_holders.block_id = ? @@ -443,7 +443,7 @@ func (q *Queries) TokensByHolderIDAndBlockID(ctx context.Context, arg TokensByHo &i.CreationBlock, &i.TypeID, &i.Synced, - &i.Tag, + &i.Tags, &i.ChainID, ); err != nil { return nil, err diff --git a/db/sqlc/models.go b/db/sqlc/models.go index 4d48416f..c198a019 100644 --- a/db/sqlc/models.go +++ b/db/sqlc/models.go @@ -16,11 +16,6 @@ type Block struct { RootHash annotations.Hash } -type CensusBlock struct { - CensusID uint64 - BlockID uint64 -} - type Censuse struct { ID uint64 StrategyID uint64 @@ -57,7 +52,7 @@ type Token struct { CreationBlock sql.NullInt64 TypeID uint64 Synced bool - Tag sql.NullString + Tags sql.NullString ChainID uint64 } diff --git a/db/sqlc/tokens.sql.go b/db/sqlc/tokens.sql.go index 018d7704..ca099bd6 100644 --- a/db/sqlc/tokens.sql.go +++ b/db/sqlc/tokens.sql.go @@ -22,7 +22,7 @@ INSERT INTO tokens ( creation_block, type_id, synced, - tag, + tags, chain_id ) VALUES ( @@ -39,7 +39,7 @@ type CreateTokenParams struct { CreationBlock sql.NullInt64 TypeID uint64 Synced bool - Tag sql.NullString + Tags sql.NullString ChainID uint64 } @@ -53,7 +53,7 @@ func (q *Queries) CreateToken(ctx context.Context, arg CreateTokenParams) (sql.R arg.CreationBlock, arg.TypeID, arg.Synced, - arg.Tag, + arg.Tags, arg.ChainID, ) } @@ -82,7 +82,7 @@ func (q *Queries) ExistsToken(ctx context.Context, id annotations.Address) (bool } const listTokens = `-- name: ListTokens :many -SELECT id, name, symbol, decimals, total_supply, creation_block, type_id, synced, tag, chain_id FROM tokens +SELECT id, name, symbol, decimals, total_supply, creation_block, type_id, synced, tags, chain_id FROM tokens ORDER BY type_id, name ` @@ -104,7 +104,7 @@ func (q *Queries) ListTokens(ctx context.Context) ([]Token, error) { &i.CreationBlock, &i.TypeID, &i.Synced, - &i.Tag, + &i.Tags, &i.ChainID, ); err != nil { return nil, err @@ -121,7 +121,7 @@ func (q *Queries) ListTokens(ctx context.Context) ([]Token, error) { } const tokenByID = `-- name: TokenByID :one -SELECT id, name, symbol, decimals, total_supply, creation_block, type_id, synced, tag, chain_id FROM tokens +SELECT id, name, symbol, decimals, total_supply, creation_block, type_id, synced, tags, chain_id FROM tokens WHERE id = ? LIMIT 1 ` @@ -138,14 +138,14 @@ func (q *Queries) TokenByID(ctx context.Context, id annotations.Address) (Token, &i.CreationBlock, &i.TypeID, &i.Synced, - &i.Tag, + &i.Tags, &i.ChainID, ) return i, err } const tokenByName = `-- name: TokenByName :one -SELECT id, name, symbol, decimals, total_supply, creation_block, type_id, synced, tag, chain_id FROM tokens +SELECT id, name, symbol, decimals, total_supply, creation_block, type_id, synced, tags, chain_id FROM tokens WHERE name = ? LIMIT 1 ` @@ -162,14 +162,14 @@ func (q *Queries) TokenByName(ctx context.Context, name sql.NullString) (Token, &i.CreationBlock, &i.TypeID, &i.Synced, - &i.Tag, + &i.Tags, &i.ChainID, ) return i, err } const tokenBySymbol = `-- name: TokenBySymbol :one -SELECT id, name, symbol, decimals, total_supply, creation_block, type_id, synced, tag, chain_id FROM tokens +SELECT id, name, symbol, decimals, total_supply, creation_block, type_id, synced, tags, chain_id FROM tokens WHERE symbol = ? LIMIT 1 ` @@ -186,14 +186,14 @@ func (q *Queries) TokenBySymbol(ctx context.Context, symbol sql.NullString) (Tok &i.CreationBlock, &i.TypeID, &i.Synced, - &i.Tag, + &i.Tags, &i.ChainID, ) return i, err } const tokensByStrategyID = `-- name: TokensByStrategyID :many -SELECT t.id, t.name, t.symbol, t.decimals, t.total_supply, t.creation_block, t.type_id, t.synced, t.tag, t.chain_id, st.strategy_id, st.token_id, st.min_balance, st.method_hash FROM tokens t +SELECT t.id, t.name, t.symbol, t.decimals, t.total_supply, t.creation_block, t.type_id, t.synced, t.tags, t.chain_id, st.strategy_id, st.token_id, st.min_balance, st.method_hash FROM tokens t JOIN strategy_tokens st ON st.token_id = t.id WHERE st.strategy_id = ? ORDER BY t.name @@ -208,7 +208,7 @@ type TokensByStrategyIDRow struct { CreationBlock sql.NullInt64 TypeID uint64 Synced bool - Tag sql.NullString + Tags sql.NullString ChainID uint64 StrategyID uint64 TokenID []byte @@ -234,7 +234,7 @@ func (q *Queries) TokensByStrategyID(ctx context.Context, strategyID uint64) ([] &i.CreationBlock, &i.TypeID, &i.Synced, - &i.Tag, + &i.Tags, &i.ChainID, &i.StrategyID, &i.TokenID, @@ -255,7 +255,7 @@ func (q *Queries) TokensByStrategyID(ctx context.Context, strategyID uint64) ([] } const tokensByType = `-- name: TokensByType :many -SELECT id, name, symbol, decimals, total_supply, creation_block, type_id, synced, tag, chain_id FROM tokens +SELECT id, name, symbol, decimals, total_supply, creation_block, type_id, synced, tags, chain_id FROM tokens WHERE type_id = ? ORDER BY name ` @@ -278,7 +278,7 @@ func (q *Queries) TokensByType(ctx context.Context, typeID uint64) ([]Token, err &i.CreationBlock, &i.TypeID, &i.Synced, - &i.Tag, + &i.Tags, &i.ChainID, ); err != nil { return nil, err @@ -303,7 +303,7 @@ SET name = ?, creation_block = ?, type_id = ?, synced = ?, - tag = ? + tags = ? WHERE id = ? ` @@ -315,7 +315,7 @@ type UpdateTokenParams struct { CreationBlock sql.NullInt64 TypeID uint64 Synced bool - Tag sql.NullString + Tags sql.NullString ID annotations.Address } @@ -328,7 +328,7 @@ func (q *Queries) UpdateToken(ctx context.Context, arg UpdateTokenParams) (sql.R arg.CreationBlock, arg.TypeID, arg.Synced, - arg.Tag, + arg.Tags, arg.ID, ) } diff --git a/.env b/example.env similarity index 100% rename from .env rename to example.env diff --git a/example.sh b/example.sh index 59c64f39..a46be123 100644 --- a/example.sh +++ b/example.sh @@ -8,24 +8,24 @@ readonly API_ENDPOINT="127.0.0.1:7788/api" create_token() { curl -X POST \ - --json "{\"id\": \"$CONTRACT_ADDRESS\",\"type\": \"$CONTRACT_TYPE\",\"chainID\": 1}" \ - http://$API_ENDPOINT/token + --json "{\"ID\": \"$CONTRACT_ADDRESS\",\"type\": \"$CONTRACT_TYPE\",\"chainID\": 1}" \ + http://$API_ENDPOINT/tokens } get_token() { curl -X GET \ - http://$API_ENDPOINT/token/$CONTRACT_ADDRESS + http://$API_ENDPOINT/tokens/$CONTRACT_ADDRESS } create_census() { curl -X POST \ - --json "{\"strategyId\": $1,\"anonymous\": true}" \ - http://$API_ENDPOINT/census + --json "{\"strategyID\": $1,\"anonymous\": true}" \ + http://$API_ENDPOINT/censuses } get_census() { curl -X GET \ - http://$API_ENDPOINT/census/queue/$1 + http://$API_ENDPOINT/censuses/queue/$1 } main() { @@ -33,21 +33,21 @@ main() { echo "-> creating token..." create_token # wait to be synced (can be checked getting token info) - echo "-> created, waiting 4m to token scan" - sleep 240 + echo "-> created, waiting 2m to token scan" + sleep 120 # get token info after some scan and store the 'defaultStrategy' id. echo "-> getting token info..." get_token # create the census with the token 'defaultStrategy' id and store the # resulting 'queueId'. - echo "-> enter the strategyId:" - read strategyId + echo "-> enter the strategyID:" + read strategyID echo "-> creating census..." - create_census $strategyId - echo "-> waiting 1m to census publication" - sleep 60 + create_census $strategyID + echo "-> waiting 30s to census publication" + sleep 30 # get the enqueue census creation process with the 'queueId' - echo "-> enter the enqueue census:" + echo "-> enter the enqueue census ID:" read queueId get_census $queueId } diff --git a/service/holders_scanner.go b/service/holders_scanner.go index 53c6c0b2..1654e92c 100644 --- a/service/holders_scanner.go +++ b/service/holders_scanner.go @@ -356,8 +356,8 @@ func (s *HoldersScanner) scanHolders(ctx context.Context, addr common.Address) ( return th.IsSynced(), s.saveHolders(th) } // if unexpected error raises, log it as error and return it. - log.Error("warning scanning contract", "token", th.Address().Hex(), - "block", th.LastBlock(), "error", err) + log.Errorw(fmt.Errorf("warning scanning contract: %v", err), + fmt.Sprintf("token=%s block%d", th.Address().Hex(), th.LastBlock())) return th.IsSynced(), err } // save TokesHolders state into the database before exit of the function