diff --git a/cmd/api/docs/docs.go b/cmd/api/docs/docs.go index 2684f75b7..d269124e6 100644 --- a/cmd/api/docs/docs.go +++ b/cmd/api/docs/docs.go @@ -2410,6 +2410,16 @@ const docTemplate = `{ "name": "address", "in": "path", "required": true + }, + { + "enum": [ + "on-chain", + "off-chain" + ], + "type": "string", + "description": "Views kind", + "name": "kind", + "in": "query" } ], "responses": { @@ -2800,9 +2810,9 @@ const docTemplate = `{ } } }, - "/v1/json_schema": { + "/v1/off_chain_view": { "post": { - "description": "Get JSON schema from micheline", + "description": "Get JSON schema for off-chain view", "consumes": [ "application/json" ], @@ -2812,8 +2822,8 @@ const docTemplate = `{ "tags": [ "contract" ], - "summary": "Get JSON schema from micheline", - "operationId": "get-json-schema", + "summary": "Get JSON schema for off-chain view", + "operationId": "get-off-chain-view", "parameters": [ { "description": "Micheline. Limit: 1MB", @@ -2832,7 +2842,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/ast.JSONSchema" + "$ref": "#/definitions/handlers.ViewSchema" } }, "400": { diff --git a/cmd/api/docs/swagger.json b/cmd/api/docs/swagger.json index a8333b809..7aac07911 100644 --- a/cmd/api/docs/swagger.json +++ b/cmd/api/docs/swagger.json @@ -2400,6 +2400,16 @@ "name": "address", "in": "path", "required": true + }, + { + "enum": [ + "on-chain", + "off-chain" + ], + "type": "string", + "description": "Views kind", + "name": "kind", + "in": "query" } ], "responses": { @@ -2790,9 +2800,9 @@ } } }, - "/v1/json_schema": { + "/v1/off_chain_view": { "post": { - "description": "Get JSON schema from micheline", + "description": "Get JSON schema for off-chain view", "consumes": [ "application/json" ], @@ -2802,8 +2812,8 @@ "tags": [ "contract" ], - "summary": "Get JSON schema from micheline", - "operationId": "get-json-schema", + "summary": "Get JSON schema for off-chain view", + "operationId": "get-off-chain-view", "parameters": [ { "description": "Micheline. Limit: 1MB", @@ -2822,7 +2832,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/ast.JSONSchema" + "$ref": "#/definitions/handlers.ViewSchema" } }, "400": { diff --git a/cmd/api/docs/swagger.yaml b/cmd/api/docs/swagger.yaml index 2ca98a168..ae4a2256d 100644 --- a/cmd/api/docs/swagger.yaml +++ b/cmd/api/docs/swagger.yaml @@ -3010,6 +3010,13 @@ paths: name: address required: true type: string + - description: Views kind + enum: + - on-chain + - off-chain + in: query + name: kind + type: string produces: - application/json responses: @@ -3276,12 +3283,12 @@ paths: summary: Get implicit operation tags: - operations - /v1/json_schema: + /v1/off_chain_view: post: consumes: - application/json - description: Get JSON schema from micheline - operationId: get-json-schema + description: Get JSON schema for off-chain view + operationId: get-off-chain-view parameters: - description: 'Micheline. Limit: 1MB' in: body @@ -3297,7 +3304,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/ast.JSONSchema' + $ref: '#/definitions/handlers.ViewSchema' "400": description: Bad Request schema: @@ -3306,7 +3313,7 @@ paths: description: Internal Server Error schema: $ref: '#/definitions/handlers.Error' - summary: Get JSON schema from micheline + summary: Get JSON schema for off-chain view tags: - contract /v1/operation/{network}/{id}/diff: diff --git a/cmd/api/handlers/requests.go b/cmd/api/handlers/requests.go index 5f7c00b72..120b02478 100644 --- a/cmd/api/handlers/requests.go +++ b/cmd/api/handlers/requests.go @@ -342,3 +342,7 @@ type globalConstantsContractsRequest struct { getGlobalConstantRequest pageableRequest } + +type getViewsArgs struct { + Kind ViewSchemaKind `form:"kind" binding:"omitempty,oneof=off-chain on-chain"` +} diff --git a/cmd/api/handlers/views.go b/cmd/api/handlers/views.go index 5341760d0..938594795 100644 --- a/cmd/api/handlers/views.go +++ b/cmd/api/handlers/views.go @@ -4,7 +4,6 @@ import ( "context" "errors" "io" - "io/ioutil" "net/http" "time" @@ -23,7 +22,6 @@ var ( errNoViews = errors.New("there aren't views in the metadata") errInvalidImplementation = errors.New("invalid implementation index") errEmptyImplementation = errors.New("empty implementation") - errInvalidMicheline = errors.New("invalid micheline") ) // GetViewsSchema godoc @@ -33,6 +31,7 @@ var ( // @ID get-contract-tzip-views-schema // @Param network path string true "Network" // @Param address path string true "KT address" minlength(36) maxlength(36) +// @Param kind query string false "Views kind" Enums(on-chain, off-chain) // @Accept json // @Produce json // @Success 200 {array} ViewSchema @@ -49,69 +48,98 @@ func GetViewsSchema() gin.HandlerFunc { return } - offChain, err := getOffChainViewsSchema(ctx.ContractMetadata, req.Address) - if err != nil { - if !ctx.Storage.IsRecordNotFound(err) { - handleError(c, ctx.Storage, err, 0) - return - } + var args getViewsArgs + if err := c.BindQuery(&args); handleError(c, ctx.Storage, err, http.StatusNotFound) { + return } - onChain, err := getOnChainViewsSchema(ctx.Contracts, ctx.Blocks, req.Address) - if err != nil { - if !ctx.Storage.IsRecordNotFound(err) { - handleError(c, ctx.Storage, err, 0) - return + views := make([]ViewSchema, 0) + + if args.Kind == EmptyView || args.Kind == OffchainView { + offChain, err := getOffChainViewsSchema(ctx.ContractMetadata, req.Address) + if err != nil { + if !ctx.Storage.IsRecordNotFound(err) { + handleError(c, ctx.Storage, err, 0) + return + } } + views = append(views, offChain...) } - if len(onChain) == 0 && len(offChain) == 0 { - c.SecureJSON(http.StatusOK, []ViewSchema{}) - return + if args.Kind == EmptyView || args.Kind == OnchainView { + onChain, err := getOnChainViewsSchema(ctx.Contracts, ctx.Blocks, req.Address) + if err != nil { + if !ctx.Storage.IsRecordNotFound(err) { + handleError(c, ctx.Storage, err, 0) + return + } + } + views = append(views, onChain...) } - c.SecureJSON(http.StatusOK, append(offChain, onChain...)) + c.SecureJSON(http.StatusOK, views) } } -// JSONSchema godoc -// @Summary Get JSON schema from micheline -// @Description Get JSON schema from micheline +// OffChainView godoc +// @Summary Get JSON schema for off-chain view +// @Description Get JSON schema for off-chain view // @Tags contract -// @ID get-json-schema +// @ID get-off-chain-view // @Param body body json.RawMessage true "Micheline. Limit: 1MB" // @Accept json // @Produce json -// @Success 200 {object} ast.JSONSchema +// @Success 200 {object} ViewSchema // @Failure 400 {object} Error // @Failure 500 {object} Error -// @Router /v1/json_schema [post] -func JSONSchema() gin.HandlerFunc { +// @Router /v1/off_chain_view [post] +func OffChainView() gin.HandlerFunc { return func(c *gin.Context) { ctx := c.MustGet("context").(*config.Context) - body, err := ioutil.ReadAll(io.LimitReader(c.Request.Body, 1024*1024)) - if handleError(c, ctx.Storage, err, http.StatusBadRequest) { + var view contract_metadata.View + if err := json.NewDecoder(io.LimitReader(c.Request.Body, 1024*1024)).Decode(&view); handleError(c, ctx.Storage, err, http.StatusBadRequest) { return } - if !json.Valid(body) { - handleError(c, ctx.Storage, errInvalidMicheline, http.StatusBadRequest) - return - } + c.SecureJSON(http.StatusOK, getOffChainViewSchema(view)) + } +} - tree, err := ast.NewTypedAstFromBytes(body) - if handleError(c, ctx.Storage, err, http.StatusInternalServerError) { - return +func getOffChainViewSchema(view contract_metadata.View) *ViewSchema { + var schema ViewSchema + for i, impl := range view.Implementations { + if impl.MichelsonStorageView.Empty() { + continue } - schema, err := tree.ToJSONSchema() - if handleError(c, ctx.Storage, err, http.StatusInternalServerError) { - return - } + schema.Name = view.Name + schema.Description = view.Description + schema.Implementation = i + schema.Kind = OffchainView - c.SecureJSON(http.StatusOK, schema) + tree, err := getOffChainViewTree(impl) + if err != nil { + schema.Error = err.Error() + return &schema + } + entrypoints, err := tree.GetEntrypointsDocs() + if err != nil { + schema.Error = err.Error() + return &schema + } + if len(entrypoints) != 1 { + continue + } + schema.Type = entrypoints[0].Type + schema.Schema, err = tree.ToJSONSchema() + if err != nil { + schema.Error = err.Error() + } + return &schema } + + return nil } func getOffChainViewsSchema(contractMetadata contract_metadata.Repository, address string) ([]ViewSchema, error) { @@ -123,41 +151,8 @@ func getOffChainViewsSchema(contractMetadata contract_metadata.Repository, addre schemas := make([]ViewSchema, 0) for _, view := range tzip.Views { - for i, impl := range view.Implementations { - if impl.MichelsonStorageView.Empty() { - continue - } - - schema := ViewSchema{ - Name: view.Name, - Description: view.Description, - Implementation: i, - Kind: OffchainView, - } - - tree, err := getOffChainViewTree(impl) - if err != nil { - schema.Error = err.Error() - schemas = append(schemas, schema) - continue - } - entrypoints, err := tree.GetEntrypointsDocs() - if err != nil { - schema.Error = err.Error() - schemas = append(schemas, schema) - continue - } - if len(entrypoints) != 1 { - continue - } - schema.Type = entrypoints[0].Type - schema.Schema, err = tree.ToJSONSchema() - if err != nil { - schema.Error = err.Error() - schemas = append(schemas, schema) - continue - } - schemas = append(schemas, schema) + if schema := getOffChainViewSchema(view); schema != nil { + schemas = append(schemas, *schema) } } diff --git a/cmd/api/main.go b/cmd/api/main.go index e50d40859..d119e3961 100644 --- a/cmd/api/main.go +++ b/cmd/api/main.go @@ -98,7 +98,7 @@ func (api *app) makeRouter() { } v1.GET("implicit/:network/:counter", handlers.NetworkMiddleware(api.Contexts), handlers.GetImplicitOperation()) v1.GET("search", handlers.ContextsMiddleware(api.Contexts), handlers.Search()) - v1.POST("json_schema", handlers.MainnetMiddleware(api.Contexts), handlers.JSONSchema()) + v1.POST("off_chain_view", handlers.MainnetMiddleware(api.Contexts), handlers.OffChainView()) v1.POST("michelson", handlers.ContextsMiddleware(api.Contexts), handlers.CodeFromMichelson()) v1.POST("fork", handlers.ForkContract(api.Contexts)) diff --git a/internal/models/contract_metadata/tzip20.go b/internal/models/contract_metadata/tzip20.go index c81325796..e2119f29e 100644 --- a/internal/models/contract_metadata/tzip20.go +++ b/internal/models/contract_metadata/tzip20.go @@ -61,7 +61,7 @@ func (s Sections) Empty() bool { // IsParameterEmpty - func (s Sections) IsParameterEmpty() bool { - return bytes.HasSuffix(s.Parameter, null) + return s.Parameter == nil || bytes.HasSuffix(s.Parameter, null) } // MichelsonInitialStorageEvent -