From 74c8675faebc0dc498a5cd341bfa7062d8d200e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=90=E8=B6=85=E8=B6=8A?= <993921@qq.com> Date: Tue, 5 Mar 2024 20:36:10 +0800 Subject: [PATCH] try pay user operation request model validator --- common/model/api_request.go | 16 +++ common/model/user_operation.go | 18 ++-- docs/docs.go | 103 +++++++++++++++++++- docs/swagger.json | 98 ++++++++++++++++++- docs/swagger.yaml | 68 ++++++++++++- rpc_server/api/auth.go | 2 +- rpc_server/api/health.go | 3 +- rpc_server/api/v1/try_pay_user_operation.go | 8 +- 8 files changed, 295 insertions(+), 21 deletions(-) diff --git a/common/model/api_request.go b/common/model/api_request.go index 45ec599a..c23fac63 100644 --- a/common/model/api_request.go +++ b/common/model/api_request.go @@ -1,5 +1,7 @@ package model +import "errors" + type TryPayUserOpRequest struct { ForceStrategyId string `json:"strategy_id"` ForceNetWork string `json:"force_network"` @@ -9,3 +11,17 @@ type TryPayUserOpRequest struct { Apikey string `json:"apikey"` Extra interface{} `json:"extra"` } + +func (sender *TryPayUserOpRequest) Validate() error { + if len(sender.Apikey) == 0 { + return errors.New("apikey mustn't empty") + } + + if len(sender.ForceStrategyId) == 0 { + if len(sender.ForceNetWork) == 0 || len(sender.ForceTokens) == 0 || len(sender.ForceEntryPointAddress) == 0 { + return errors.New("strategy configuration illegal") + } + } + + return nil +} diff --git a/common/model/user_operation.go b/common/model/user_operation.go index 5b7c7e6b..c13b4fb1 100644 --- a/common/model/user_operation.go +++ b/common/model/user_operation.go @@ -1,14 +1,14 @@ package model type UserOperationItem struct { - Sender string `json:"sender"` - Nonce string `json:"nonce"` - InitCode string `json:"init_code"` - CallGasLimit string `json:"call_gas_limit"` - VerificationGasList string `json:"verification_gas_list"` - PerVerificationGas string `json:"per_verification_gas"` - MaxFeePerGas string `json:"max_fee_per_gas"` - MaxPriorityFeePerGas string `json:"max_priority_fee_per_gas"` + Sender string `json:"sender" binding:"required"` + Nonce string `json:"nonce" binding:"required"` + InitCode string `json:"init_code" binding:"required"` + CallGasLimit string `json:"call_gas_limit" binding:"required"` + VerificationGasList string `json:"verification_gas_list" binding:"required"` + PerVerificationGas string `json:"per_verification_gas" binding:"required"` + MaxFeePerGas string `json:"max_fee_per_gas" binding:"required"` + MaxPriorityFeePerGas string `json:"max_priority_fee_per_gas" binding:"required"` + Signature string `json:"signature" binding:"required"` //paymasterAndData string `json:"paymaster_and_data"` - Signature string `json:"signature"` } diff --git a/docs/docs.go b/docs/docs.go index 89631010..85fa5d6a 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -1,5 +1,4 @@ -// Package docs GENERATED BY SWAG; DO NOT EDIT -// This file was generated by swaggo/swag +// Package docs Code generated by swaggo/swag. DO NOT EDIT package docs import "github.com/swaggo/swag" @@ -35,7 +34,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/models.ClientCredential" + "$ref": "#/definitions/model.ClientCredential" } } ], @@ -46,6 +45,22 @@ const docTemplate = `{ } } }, + "/api/health": { + "get": { + "description": "Get Healthz", + "consumes": [ + "application/json" + ], + "tags": [ + "Healthz" + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, "/api/v1/get-support-entrypoint": { "get": { "security": [ @@ -105,6 +120,17 @@ const docTemplate = `{ "tags": [ "Sponsor" ], + "parameters": [ + { + "description": "UserOp Request", + "name": "tryPay", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.TryPayUserOpRequest" + } + } + ], "responses": { "200": { "description": "OK" @@ -114,13 +140,80 @@ const docTemplate = `{ } }, "definitions": { - "models.ClientCredential": { + "model.ClientCredential": { "type": "object", "properties": { "apiKey": { "type": "string" } } + }, + "model.TryPayUserOpRequest": { + "type": "object", + "properties": { + "apikey": { + "type": "string" + }, + "extra": {}, + "force_entry_point_address": { + "type": "string" + }, + "force_network": { + "type": "string" + }, + "force_tokens": { + "type": "string" + }, + "strategy_id": { + "type": "string" + }, + "user_operation": { + "$ref": "#/definitions/model.UserOperationItem" + } + } + }, + "model.UserOperationItem": { + "type": "object", + "required": [ + "call_gas_limit", + "init_code", + "max_fee_per_gas", + "max_priority_fee_per_gas", + "nonce", + "per_verification_gas", + "sender", + "signature", + "verification_gas_list" + ], + "properties": { + "call_gas_limit": { + "type": "string" + }, + "init_code": { + "type": "string" + }, + "max_fee_per_gas": { + "type": "string" + }, + "max_priority_fee_per_gas": { + "type": "string" + }, + "nonce": { + "type": "string" + }, + "per_verification_gas": { + "type": "string" + }, + "sender": { + "type": "string" + }, + "signature": { + "type": "string" + }, + "verification_gas_list": { + "type": "string" + } + } } }, "securityDefinitions": { @@ -143,6 +236,8 @@ var SwaggerInfo = &swag.Spec{ Description: "", InfoInstanceName: "swagger", SwaggerTemplate: docTemplate, + LeftDelim: "{{", + RightDelim: "}}", } func init() { diff --git a/docs/swagger.json b/docs/swagger.json index a50f25ab..d680a121 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -23,7 +23,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/models.ClientCredential" + "$ref": "#/definitions/model.ClientCredential" } } ], @@ -34,6 +34,22 @@ } } }, + "/api/health": { + "get": { + "description": "Get Healthz", + "consumes": [ + "application/json" + ], + "tags": [ + "Healthz" + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, "/api/v1/get-support-entrypoint": { "get": { "security": [ @@ -93,6 +109,17 @@ "tags": [ "Sponsor" ], + "parameters": [ + { + "description": "UserOp Request", + "name": "tryPay", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.TryPayUserOpRequest" + } + } + ], "responses": { "200": { "description": "OK" @@ -102,13 +129,80 @@ } }, "definitions": { - "models.ClientCredential": { + "model.ClientCredential": { "type": "object", "properties": { "apiKey": { "type": "string" } } + }, + "model.TryPayUserOpRequest": { + "type": "object", + "properties": { + "apikey": { + "type": "string" + }, + "extra": {}, + "force_entry_point_address": { + "type": "string" + }, + "force_network": { + "type": "string" + }, + "force_tokens": { + "type": "string" + }, + "strategy_id": { + "type": "string" + }, + "user_operation": { + "$ref": "#/definitions/model.UserOperationItem" + } + } + }, + "model.UserOperationItem": { + "type": "object", + "required": [ + "call_gas_limit", + "init_code", + "max_fee_per_gas", + "max_priority_fee_per_gas", + "nonce", + "per_verification_gas", + "sender", + "signature", + "verification_gas_list" + ], + "properties": { + "call_gas_limit": { + "type": "string" + }, + "init_code": { + "type": "string" + }, + "max_fee_per_gas": { + "type": "string" + }, + "max_priority_fee_per_gas": { + "type": "string" + }, + "nonce": { + "type": "string" + }, + "per_verification_gas": { + "type": "string" + }, + "sender": { + "type": "string" + }, + "signature": { + "type": "string" + }, + "verification_gas_list": { + "type": "string" + } + } } }, "securityDefinitions": { diff --git a/docs/swagger.yaml b/docs/swagger.yaml index ab6e309b..73f33967 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -1,9 +1,56 @@ definitions: - models.ClientCredential: + model.ClientCredential: properties: apiKey: type: string type: object + model.TryPayUserOpRequest: + properties: + apikey: + type: string + extra: {} + force_entry_point_address: + type: string + force_network: + type: string + force_tokens: + type: string + strategy_id: + type: string + user_operation: + $ref: '#/definitions/model.UserOperationItem' + type: object + model.UserOperationItem: + properties: + call_gas_limit: + type: string + init_code: + type: string + max_fee_per_gas: + type: string + max_priority_fee_per_gas: + type: string + nonce: + type: string + per_verification_gas: + type: string + sender: + type: string + signature: + type: string + verification_gas_list: + type: string + required: + - call_gas_limit + - init_code + - max_fee_per_gas + - max_priority_fee_per_gas + - nonce + - per_verification_gas + - sender + - signature + - verification_gas_list + type: object info: contact: name: AAStar Support @@ -20,12 +67,22 @@ paths: name: credential required: true schema: - $ref: '#/definitions/models.ClientCredential' + $ref: '#/definitions/model.ClientCredential' responses: "200": description: OK tags: - Auth + /api/health: + get: + consumes: + - application/json + description: Get Healthz + responses: + "200": + description: OK + tags: + - Healthz /api/v1/get-support-entrypoint: get: consumes: @@ -57,6 +114,13 @@ paths: consumes: - application/json description: sponsor the userOp + parameters: + - description: UserOp Request + in: body + name: tryPay + required: true + schema: + $ref: '#/definitions/model.TryPayUserOpRequest' responses: "200": description: OK diff --git a/rpc_server/api/auth.go b/rpc_server/api/auth.go index 21e39341..cad8302f 100644 --- a/rpc_server/api/auth.go +++ b/rpc_server/api/auth.go @@ -10,7 +10,7 @@ import ( // @Description Get AccessToken By ApiKey // @Accept json // @Product json -// @Param credential body models.ClientCredential true "AccessToken Model" +// @Param credential body model.ClientCredential true "AccessToken Model" // @Router /api/auth [post] // @Success 200 func Auth(ctx *gin.Context) { diff --git a/rpc_server/api/health.go b/rpc_server/api/health.go index ec543049..8037073d 100644 --- a/rpc_server/api/health.go +++ b/rpc_server/api/health.go @@ -12,8 +12,7 @@ import ( // @Description Get Healthz // @Accept json // @Product json -// @Param -// @Router /api/health [post,get,put,delete] +// @Router /api/health [get] // @Success 200 func Healthz(c *gin.Context) { response := model.GetResponse() diff --git a/rpc_server/api/v1/try_pay_user_operation.go b/rpc_server/api/v1/try_pay_user_operation.go index 3e7f2c6d..65e61c93 100644 --- a/rpc_server/api/v1/try_pay_user_operation.go +++ b/rpc_server/api/v1/try_pay_user_operation.go @@ -14,6 +14,7 @@ import ( // @Accept json // @Product json // @Router /api/v1/try-pay-user-operation [POST] +// @Param tryPay body model.TryPayUserOpRequest true "UserOp Request" // @Success 200 // @Security JWT func TryPayUserOperation(c *gin.Context) { @@ -23,7 +24,12 @@ func TryPayUserOperation(c *gin.Context) { response := model.GetResponse() if err := c.ShouldBindJSON(&request); err != nil { - errStr := fmt.Sprintf("Conver Request Error [%v]", err) + errStr := fmt.Sprintf("Request Error [%v]", err) + response.SetHttpCode(http.StatusBadRequest).FailCode(c, http.StatusBadRequest, errStr) + } + + if err := request.Validate(); err != nil { + errStr := fmt.Sprintf("Request Error [%v]", err) response.SetHttpCode(http.StatusBadRequest).FailCode(c, http.StatusBadRequest, errStr) }