From b6b855c422fc036d0c5f3955c91e997e8c9eceb8 Mon Sep 17 00:00:00 2001 From: Denis Subbotin Date: Fri, 3 Nov 2023 15:09:05 +0300 Subject: [PATCH] add address parser --- api/openapi.json | 78 ++ api/openapi.yml | 56 +- pkg/api/account_handlers.go | 27 + pkg/oas/oas_handlers_gen.go | 117 +++ pkg/oas/oas_json_gen.go | 386 ++++++++ pkg/oas/oas_parameters_gen.go | 66 ++ pkg/oas/oas_response_encoders_gen.go | 14 + pkg/oas/oas_router_gen.go | 1228 ++++++++++++++------------ pkg/oas/oas_schemas_gen.go | 108 +++ pkg/oas/oas_server_gen.go | 6 + pkg/oas/oas_unimplemented_gen.go | 9 + tonapi/oas_client_gen.go | 97 ++ tonapi/oas_json_gen.go | 386 ++++++++ tonapi/oas_parameters_gen.go | 6 + tonapi/oas_response_decoders_gen.go | 83 ++ tonapi/oas_schemas_gen.go | 108 +++ 16 files changed, 2214 insertions(+), 561 deletions(-) diff --git a/api/openapi.json b/api/openapi.json index a22686df..2cfe129c 100644 --- a/api/openapi.json +++ b/api/openapi.json @@ -5684,6 +5684,84 @@ ] } }, + "/v2/address/{account_id}/parse": { + "get": { + "description": "parse address and display in all formats", + "operationId": "addressParse", + "parameters": [ + { + "$ref": "#/components/parameters/accountIDParameter" + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "properties": { + "bounceable": { + "properties": { + "b64": { + "type": "string" + }, + "b64url": { + "type": "string" + } + }, + "required": [ + "b64", + "b64url" + ], + "type": "object" + }, + "given_type": { + "type": "string" + }, + "non_bounceable": { + "properties": { + "b64": { + "type": "string" + }, + "b64url": { + "type": "string" + } + }, + "required": [ + "b64", + "b64url" + ], + "type": "object" + }, + "raw_form": { + "example": "0:6e731f2e28b73539a7f85ac47ca104d5840b229351189977bb6151d36b5e3f5e", + "type": "string" + }, + "test_only": { + "type": "boolean" + } + }, + "required": [ + "raw_form", + "bounceable", + "non_bounceable", + "given_type", + "test_only" + ], + "type": "object" + } + } + }, + "description": "all forms and info" + }, + "default": { + "$ref": "#/components/responses/Error" + } + }, + "tags": [ + "Accounts" + ] + } + }, "/v2/blockchain/accounts/{account_id}": { "get": { "description": "Get low-level information about an account taken directly from the blockchain.", diff --git a/api/openapi.yml b/api/openapi.yml index 276c263a..9e986136 100644 --- a/api/openapi.yml +++ b/api/openapi.yml @@ -293,7 +293,61 @@ paths: $ref: '#/components/schemas/BlockchainAccountInspect' 'default': $ref: '#/components/responses/Error' - + /v2/address/{account_id}/parse: + get: + description: parse address and display in all formats + operationId: addressParse + tags: + - Accounts + parameters: + - $ref: '#/components/parameters/accountIDParameter' + responses: + '200': + description: all forms and info + content: + application/json: + schema: + type: object + required: + - raw_form + - bounceable + - non_bounceable + - given_type + - test_only + properties: + raw_form: + type: string + example: "0:6e731f2e28b73539a7f85ac47ca104d5840b229351189977bb6151d36b5e3f5e" + bounceable: + required: + - b64 + - b64url + type: object + properties: + b64: + type: string + b64url: + type: string + non_bounceable: + required: + - b64 + - b64url + type: object + properties: + b64: + type: string + b64url: + type: string + given_type: + type: string + test_only: + type: boolean + + default: + $ref: '#/components/responses/Error' + + + /v2/events/emulate: post: description: Emulate sending message to blockchain diff --git a/pkg/api/account_handlers.go b/pkg/api/account_handlers.go index 9d974122..0c7192e1 100644 --- a/pkg/api/account_handlers.go +++ b/pkg/api/account_handlers.go @@ -2,12 +2,14 @@ package api import ( "context" + "encoding/base64" "encoding/hex" "encoding/json" "errors" "fmt" "net/http" "sort" + "strings" "github.com/tonkeeper/opentonapi/internal/g" @@ -439,3 +441,28 @@ func pubkeyFromCodeData(code, data []byte) ([]byte, error) { return nil, fmt.Errorf("unknown wallet version") } } + +func (h *Handler) AddressParse(ctx context.Context, params oas.AddressParseParams) (*oas.AddressParseOK, error) { + address, err := tongo.ParseAddress(params.AccountID) + if err != nil { + return nil, toError(http.StatusBadRequest, err) + } + var res oas.AddressParseOK + res.RawForm = address.ID.ToRaw() + res.Bounceable.B64url = address.ID.ToHuman(true, false) + res.NonBounceable.B64url = address.ID.ToHuman(false, false) + b, _ := base64.URLEncoding.DecodeString(res.Bounceable.B64url) + res.Bounceable.B64 = base64.StdEncoding.EncodeToString(b) + b, _ = base64.URLEncoding.DecodeString(res.NonBounceable.B64url) + res.NonBounceable.B64 = base64.StdEncoding.EncodeToString(b) + if strings.Contains(params.AccountID, ":") { + res.GivenType = "raw_form" + } else if strings.Contains(params.AccountID, ".") { + res.GivenType = "dns" + } else if address.Bounce { + res.GivenType = "friendly_bounceable" + } else { + res.GivenType = "friendly_non_bounceable" + } + return &res, nil //todo: add testnet_only +} diff --git a/pkg/oas/oas_handlers_gen.go b/pkg/oas/oas_handlers_gen.go index b041ec97..4a4acc32 100644 --- a/pkg/oas/oas_handlers_gen.go +++ b/pkg/oas/oas_handlers_gen.go @@ -137,6 +137,123 @@ func (s *Server) handleAccountDnsBackResolveRequest(args [1]string, argsEscaped } } +// handleAddressParseRequest handles addressParse operation. +// +// Parse address and display in all formats. +// +// GET /v2/address/{account_id}/parse +func (s *Server) handleAddressParseRequest(args [1]string, argsEscaped bool, w http.ResponseWriter, r *http.Request) { + otelAttrs := []attribute.KeyValue{ + otelogen.OperationID("addressParse"), + semconv.HTTPMethodKey.String("GET"), + semconv.HTTPRouteKey.String("/v2/address/{account_id}/parse"), + } + + // Start a span for this request. + ctx, span := s.cfg.Tracer.Start(r.Context(), "AddressParse", + trace.WithAttributes(otelAttrs...), + serverSpanKind, + ) + defer span.End() + + // Run stopwatch. + startTime := time.Now() + defer func() { + elapsedDuration := time.Since(startTime) + // Use floating point division here for higher precision (instead of Millisecond method). + s.duration.Record(ctx, float64(float64(elapsedDuration)/float64(time.Millisecond)), metric.WithAttributes(otelAttrs...)) + }() + + // Increment request counter. + s.requests.Add(ctx, 1, metric.WithAttributes(otelAttrs...)) + + var ( + recordError = func(stage string, err error) { + span.RecordError(err) + span.SetStatus(codes.Error, stage) + s.errors.Add(ctx, 1, metric.WithAttributes(otelAttrs...)) + } + err error + opErrContext = ogenerrors.OperationContext{ + Name: "AddressParse", + ID: "addressParse", + } + ) + params, err := decodeAddressParseParams(args, argsEscaped, r) + if err != nil { + err = &ogenerrors.DecodeParamsError{ + OperationContext: opErrContext, + Err: err, + } + recordError("DecodeParams", err) + s.cfg.ErrorHandler(ctx, w, r, err) + return + } + + var response *AddressParseOK + if m := s.cfg.Middleware; m != nil { + mreq := middleware.Request{ + Context: ctx, + OperationName: "AddressParse", + OperationSummary: "", + OperationID: "addressParse", + Body: nil, + Params: middleware.Parameters{ + { + Name: "account_id", + In: "path", + }: params.AccountID, + }, + Raw: r, + } + + type ( + Request = struct{} + Params = AddressParseParams + Response = *AddressParseOK + ) + response, err = middleware.HookMiddleware[ + Request, + Params, + Response, + ]( + m, + mreq, + unpackAddressParseParams, + func(ctx context.Context, request Request, params Params) (response Response, err error) { + response, err = s.h.AddressParse(ctx, params) + return response, err + }, + ) + } else { + response, err = s.h.AddressParse(ctx, params) + } + if err != nil { + if errRes, ok := errors.Into[*ErrorStatusCode](err); ok { + if err := encodeErrorResponse(errRes, w, span); err != nil { + recordError("Internal", err) + } + return + } + if errors.Is(err, ht.ErrNotImplemented) { + s.cfg.ErrorHandler(ctx, w, r, err) + return + } + if err := encodeErrorResponse(s.h.NewError(ctx, err), w, span); err != nil { + recordError("Internal", err) + } + return + } + + if err := encodeAddressParseResponse(response, w, span); err != nil { + recordError("EncodeResponse", err) + if !errors.Is(err, ht.ErrInternalServerErrorResponse) { + s.cfg.ErrorHandler(ctx, w, r, err) + } + return + } +} + // handleBlockchainAccountInspectRequest handles blockchainAccountInspect operation. // // Blockchain account inspect. diff --git a/pkg/oas/oas_json_gen.go b/pkg/oas/oas_json_gen.go index efc334b8..107c67b4 100644 --- a/pkg/oas/oas_json_gen.go +++ b/pkg/oas/oas_json_gen.go @@ -2452,6 +2452,392 @@ func (s *ActionType) UnmarshalJSON(data []byte) error { return s.Decode(d) } +// Encode implements json.Marshaler. +func (s *AddressParseOK) Encode(e *jx.Encoder) { + e.ObjStart() + s.encodeFields(e) + e.ObjEnd() +} + +// encodeFields encodes fields. +func (s *AddressParseOK) encodeFields(e *jx.Encoder) { + { + e.FieldStart("raw_form") + e.Str(s.RawForm) + } + { + e.FieldStart("bounceable") + s.Bounceable.Encode(e) + } + { + e.FieldStart("non_bounceable") + s.NonBounceable.Encode(e) + } + { + e.FieldStart("given_type") + e.Str(s.GivenType) + } + { + e.FieldStart("test_only") + e.Bool(s.TestOnly) + } +} + +var jsonFieldsNameOfAddressParseOK = [5]string{ + 0: "raw_form", + 1: "bounceable", + 2: "non_bounceable", + 3: "given_type", + 4: "test_only", +} + +// Decode decodes AddressParseOK from json. +func (s *AddressParseOK) Decode(d *jx.Decoder) error { + if s == nil { + return errors.New("invalid: unable to decode AddressParseOK to nil") + } + var requiredBitSet [1]uint8 + + if err := d.ObjBytes(func(d *jx.Decoder, k []byte) error { + switch string(k) { + case "raw_form": + requiredBitSet[0] |= 1 << 0 + if err := func() error { + v, err := d.Str() + s.RawForm = string(v) + if err != nil { + return err + } + return nil + }(); err != nil { + return errors.Wrap(err, "decode field \"raw_form\"") + } + case "bounceable": + requiredBitSet[0] |= 1 << 1 + if err := func() error { + if err := s.Bounceable.Decode(d); err != nil { + return err + } + return nil + }(); err != nil { + return errors.Wrap(err, "decode field \"bounceable\"") + } + case "non_bounceable": + requiredBitSet[0] |= 1 << 2 + if err := func() error { + if err := s.NonBounceable.Decode(d); err != nil { + return err + } + return nil + }(); err != nil { + return errors.Wrap(err, "decode field \"non_bounceable\"") + } + case "given_type": + requiredBitSet[0] |= 1 << 3 + if err := func() error { + v, err := d.Str() + s.GivenType = string(v) + if err != nil { + return err + } + return nil + }(); err != nil { + return errors.Wrap(err, "decode field \"given_type\"") + } + case "test_only": + requiredBitSet[0] |= 1 << 4 + if err := func() error { + v, err := d.Bool() + s.TestOnly = bool(v) + if err != nil { + return err + } + return nil + }(); err != nil { + return errors.Wrap(err, "decode field \"test_only\"") + } + default: + return d.Skip() + } + return nil + }); err != nil { + return errors.Wrap(err, "decode AddressParseOK") + } + // Validate required fields. + var failures []validate.FieldError + for i, mask := range [1]uint8{ + 0b00011111, + } { + if result := (requiredBitSet[i] & mask) ^ mask; result != 0 { + // Mask only required fields and check equality to mask using XOR. + // + // If XOR result is not zero, result is not equal to expected, so some fields are missed. + // Bits of fields which would be set are actually bits of missed fields. + missed := bits.OnesCount8(result) + for bitN := 0; bitN < missed; bitN++ { + bitIdx := bits.TrailingZeros8(result) + fieldIdx := i*8 + bitIdx + var name string + if fieldIdx < len(jsonFieldsNameOfAddressParseOK) { + name = jsonFieldsNameOfAddressParseOK[fieldIdx] + } else { + name = strconv.Itoa(fieldIdx) + } + failures = append(failures, validate.FieldError{ + Name: name, + Error: validate.ErrFieldRequired, + }) + // Reset bit. + result &^= 1 << bitIdx + } + } + } + if len(failures) > 0 { + return &validate.Error{Fields: failures} + } + + return nil +} + +// MarshalJSON implements stdjson.Marshaler. +func (s *AddressParseOK) MarshalJSON() ([]byte, error) { + e := jx.Encoder{} + s.Encode(&e) + return e.Bytes(), nil +} + +// UnmarshalJSON implements stdjson.Unmarshaler. +func (s *AddressParseOK) UnmarshalJSON(data []byte) error { + d := jx.DecodeBytes(data) + return s.Decode(d) +} + +// Encode implements json.Marshaler. +func (s *AddressParseOKBounceable) Encode(e *jx.Encoder) { + e.ObjStart() + s.encodeFields(e) + e.ObjEnd() +} + +// encodeFields encodes fields. +func (s *AddressParseOKBounceable) encodeFields(e *jx.Encoder) { + { + e.FieldStart("b64") + e.Str(s.B64) + } + { + e.FieldStart("b64url") + e.Str(s.B64url) + } +} + +var jsonFieldsNameOfAddressParseOKBounceable = [2]string{ + 0: "b64", + 1: "b64url", +} + +// Decode decodes AddressParseOKBounceable from json. +func (s *AddressParseOKBounceable) Decode(d *jx.Decoder) error { + if s == nil { + return errors.New("invalid: unable to decode AddressParseOKBounceable to nil") + } + var requiredBitSet [1]uint8 + + if err := d.ObjBytes(func(d *jx.Decoder, k []byte) error { + switch string(k) { + case "b64": + requiredBitSet[0] |= 1 << 0 + if err := func() error { + v, err := d.Str() + s.B64 = string(v) + if err != nil { + return err + } + return nil + }(); err != nil { + return errors.Wrap(err, "decode field \"b64\"") + } + case "b64url": + requiredBitSet[0] |= 1 << 1 + if err := func() error { + v, err := d.Str() + s.B64url = string(v) + if err != nil { + return err + } + return nil + }(); err != nil { + return errors.Wrap(err, "decode field \"b64url\"") + } + default: + return d.Skip() + } + return nil + }); err != nil { + return errors.Wrap(err, "decode AddressParseOKBounceable") + } + // Validate required fields. + var failures []validate.FieldError + for i, mask := range [1]uint8{ + 0b00000011, + } { + if result := (requiredBitSet[i] & mask) ^ mask; result != 0 { + // Mask only required fields and check equality to mask using XOR. + // + // If XOR result is not zero, result is not equal to expected, so some fields are missed. + // Bits of fields which would be set are actually bits of missed fields. + missed := bits.OnesCount8(result) + for bitN := 0; bitN < missed; bitN++ { + bitIdx := bits.TrailingZeros8(result) + fieldIdx := i*8 + bitIdx + var name string + if fieldIdx < len(jsonFieldsNameOfAddressParseOKBounceable) { + name = jsonFieldsNameOfAddressParseOKBounceable[fieldIdx] + } else { + name = strconv.Itoa(fieldIdx) + } + failures = append(failures, validate.FieldError{ + Name: name, + Error: validate.ErrFieldRequired, + }) + // Reset bit. + result &^= 1 << bitIdx + } + } + } + if len(failures) > 0 { + return &validate.Error{Fields: failures} + } + + return nil +} + +// MarshalJSON implements stdjson.Marshaler. +func (s *AddressParseOKBounceable) MarshalJSON() ([]byte, error) { + e := jx.Encoder{} + s.Encode(&e) + return e.Bytes(), nil +} + +// UnmarshalJSON implements stdjson.Unmarshaler. +func (s *AddressParseOKBounceable) UnmarshalJSON(data []byte) error { + d := jx.DecodeBytes(data) + return s.Decode(d) +} + +// Encode implements json.Marshaler. +func (s *AddressParseOKNonBounceable) Encode(e *jx.Encoder) { + e.ObjStart() + s.encodeFields(e) + e.ObjEnd() +} + +// encodeFields encodes fields. +func (s *AddressParseOKNonBounceable) encodeFields(e *jx.Encoder) { + { + e.FieldStart("b64") + e.Str(s.B64) + } + { + e.FieldStart("b64url") + e.Str(s.B64url) + } +} + +var jsonFieldsNameOfAddressParseOKNonBounceable = [2]string{ + 0: "b64", + 1: "b64url", +} + +// Decode decodes AddressParseOKNonBounceable from json. +func (s *AddressParseOKNonBounceable) Decode(d *jx.Decoder) error { + if s == nil { + return errors.New("invalid: unable to decode AddressParseOKNonBounceable to nil") + } + var requiredBitSet [1]uint8 + + if err := d.ObjBytes(func(d *jx.Decoder, k []byte) error { + switch string(k) { + case "b64": + requiredBitSet[0] |= 1 << 0 + if err := func() error { + v, err := d.Str() + s.B64 = string(v) + if err != nil { + return err + } + return nil + }(); err != nil { + return errors.Wrap(err, "decode field \"b64\"") + } + case "b64url": + requiredBitSet[0] |= 1 << 1 + if err := func() error { + v, err := d.Str() + s.B64url = string(v) + if err != nil { + return err + } + return nil + }(); err != nil { + return errors.Wrap(err, "decode field \"b64url\"") + } + default: + return d.Skip() + } + return nil + }); err != nil { + return errors.Wrap(err, "decode AddressParseOKNonBounceable") + } + // Validate required fields. + var failures []validate.FieldError + for i, mask := range [1]uint8{ + 0b00000011, + } { + if result := (requiredBitSet[i] & mask) ^ mask; result != 0 { + // Mask only required fields and check equality to mask using XOR. + // + // If XOR result is not zero, result is not equal to expected, so some fields are missed. + // Bits of fields which would be set are actually bits of missed fields. + missed := bits.OnesCount8(result) + for bitN := 0; bitN < missed; bitN++ { + bitIdx := bits.TrailingZeros8(result) + fieldIdx := i*8 + bitIdx + var name string + if fieldIdx < len(jsonFieldsNameOfAddressParseOKNonBounceable) { + name = jsonFieldsNameOfAddressParseOKNonBounceable[fieldIdx] + } else { + name = strconv.Itoa(fieldIdx) + } + failures = append(failures, validate.FieldError{ + Name: name, + Error: validate.ErrFieldRequired, + }) + // Reset bit. + result &^= 1 << bitIdx + } + } + } + if len(failures) > 0 { + return &validate.Error{Fields: failures} + } + + return nil +} + +// MarshalJSON implements stdjson.Marshaler. +func (s *AddressParseOKNonBounceable) MarshalJSON() ([]byte, error) { + e := jx.Encoder{} + s.Encode(&e) + return e.Bytes(), nil +} + +// UnmarshalJSON implements stdjson.Unmarshaler. +func (s *AddressParseOKNonBounceable) UnmarshalJSON(data []byte) error { + d := jx.DecodeBytes(data) + return s.Decode(d) +} + // Encode implements json.Marshaler. func (s *ApyHistory) Encode(e *jx.Encoder) { e.ObjStart() diff --git a/pkg/oas/oas_parameters_gen.go b/pkg/oas/oas_parameters_gen.go index be544cda..7d9deb13 100644 --- a/pkg/oas/oas_parameters_gen.go +++ b/pkg/oas/oas_parameters_gen.go @@ -81,6 +81,72 @@ func decodeAccountDnsBackResolveParams(args [1]string, argsEscaped bool, r *http return params, nil } +// AddressParseParams is parameters of addressParse operation. +type AddressParseParams struct { + // Account ID. + AccountID string +} + +func unpackAddressParseParams(packed middleware.Parameters) (params AddressParseParams) { + { + key := middleware.ParameterKey{ + Name: "account_id", + In: "path", + } + params.AccountID = packed[key].(string) + } + return params +} + +func decodeAddressParseParams(args [1]string, argsEscaped bool, r *http.Request) (params AddressParseParams, _ error) { + // Decode path: account_id. + if err := func() error { + param := args[0] + if argsEscaped { + unescaped, err := url.PathUnescape(args[0]) + if err != nil { + return errors.Wrap(err, "unescape path") + } + param = unescaped + } + if len(param) > 0 { + d := uri.NewPathDecoder(uri.PathDecoderConfig{ + Param: "account_id", + Value: param, + Style: uri.PathStyleSimple, + Explode: false, + }) + + if err := func() error { + val, err := d.DecodeValue() + if err != nil { + return err + } + + c, err := conv.ToString(val) + if err != nil { + return err + } + + params.AccountID = c + return nil + }(); err != nil { + return err + } + } else { + return validate.ErrFieldRequired + } + return nil + }(); err != nil { + return params, &ogenerrors.DecodeParamError{ + Name: "account_id", + In: "path", + Err: err, + } + } + return params, nil +} + // BlockchainAccountInspectParams is parameters of blockchainAccountInspect operation. type BlockchainAccountInspectParams struct { // Account ID. diff --git a/pkg/oas/oas_response_encoders_gen.go b/pkg/oas/oas_response_encoders_gen.go index c9f02f3f..5706a909 100644 --- a/pkg/oas/oas_response_encoders_gen.go +++ b/pkg/oas/oas_response_encoders_gen.go @@ -27,6 +27,20 @@ func encodeAccountDnsBackResolveResponse(response *DomainNames, w http.ResponseW return nil } +func encodeAddressParseResponse(response *AddressParseOK, w http.ResponseWriter, span trace.Span) error { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(200) + span.SetStatus(codes.Ok, http.StatusText(200)) + + e := jx.GetEncoder() + response.Encode(e) + if _, err := e.WriteTo(w); err != nil { + return errors.Wrap(err, "write") + } + + return nil +} + func encodeBlockchainAccountInspectResponse(response *BlockchainAccountInspect, w http.ResponseWriter, span trace.Span) error { w.Header().Set("Content-Type", "application/json") w.WriteHeader(200) diff --git a/pkg/oas/oas_router_gen.go b/pkg/oas/oas_router_gen.go index f6e2ab51..558d41a4 100644 --- a/pkg/oas/oas_router_gen.go +++ b/pkg/oas/oas_router_gen.go @@ -60,8 +60,8 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { break } switch elem[0] { - case 'a': // Prefix: "accounts/" - if l := len("accounts/"); len(elem) >= l && elem[0:l] == "accounts/" { + case 'a': // Prefix: "a" + if l := len("a"); len(elem) >= l && elem[0:l] == "a" { elem = elem[l:] } else { break @@ -71,78 +71,78 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { break } switch elem[0] { - case '_': // Prefix: "_bulk" - if l := len("_bulk"); len(elem) >= l && elem[0:l] == "_bulk" { + case 'c': // Prefix: "ccounts/" + if l := len("ccounts/"); len(elem) >= l && elem[0:l] == "ccounts/" { elem = elem[l:] } else { break } if len(elem) == 0 { - // Leaf node. - switch r.Method { - case "POST": - s.handleGetAccountsRequest([0]string{}, elemIsEscaped, w, r) - default: - s.notAllowed(w, r, "POST") + break + } + switch elem[0] { + case '_': // Prefix: "_bulk" + if l := len("_bulk"); len(elem) >= l && elem[0:l] == "_bulk" { + elem = elem[l:] + } else { + break } - return + if len(elem) == 0 { + // Leaf node. + switch r.Method { + case "POST": + s.handleGetAccountsRequest([0]string{}, elemIsEscaped, w, r) + default: + s.notAllowed(w, r, "POST") + } + + return + } + case 's': // Prefix: "search" + if l := len("search"); len(elem) >= l && elem[0:l] == "search" { + elem = elem[l:] + } else { + break + } + + if len(elem) == 0 { + // Leaf node. + switch r.Method { + case "GET": + s.handleSearchAccountsRequest([0]string{}, elemIsEscaped, w, r) + default: + s.notAllowed(w, r, "GET") + } + + return + } } - case 's': // Prefix: "search" - if l := len("search"); len(elem) >= l && elem[0:l] == "search" { - elem = elem[l:] - } else { - break + // Param: "account_id" + // Match until "/" + idx := strings.IndexByte(elem, '/') + if idx < 0 { + idx = len(elem) } + args[0] = elem[:idx] + elem = elem[idx:] if len(elem) == 0 { - // Leaf node. switch r.Method { case "GET": - s.handleSearchAccountsRequest([0]string{}, elemIsEscaped, w, r) + s.handleGetAccountRequest([1]string{ + args[0], + }, elemIsEscaped, w, r) default: s.notAllowed(w, r, "GET") } return } - } - // Param: "account_id" - // Match until "/" - idx := strings.IndexByte(elem, '/') - if idx < 0 { - idx = len(elem) - } - args[0] = elem[:idx] - elem = elem[idx:] - - if len(elem) == 0 { - switch r.Method { - case "GET": - s.handleGetAccountRequest([1]string{ - args[0], - }, elemIsEscaped, w, r) - default: - s.notAllowed(w, r, "GET") - } - - return - } - switch elem[0] { - case '/': // Prefix: "/" - if l := len("/"); len(elem) >= l && elem[0:l] == "/" { - elem = elem[l:] - } else { - break - } - - if len(elem) == 0 { - break - } switch elem[0] { - case 'd': // Prefix: "d" - if l := len("d"); len(elem) >= l && elem[0:l] == "d" { + case '/': // Prefix: "/" + if l := len("/"); len(elem) >= l && elem[0:l] == "/" { elem = elem[l:] } else { break @@ -152,28 +152,8 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { break } switch elem[0] { - case 'i': // Prefix: "iff" - if l := len("iff"); len(elem) >= l && elem[0:l] == "iff" { - elem = elem[l:] - } else { - break - } - - if len(elem) == 0 { - // Leaf node. - switch r.Method { - case "GET": - s.handleGetAccountDiffRequest([1]string{ - args[0], - }, elemIsEscaped, w, r) - default: - s.notAllowed(w, r, "GET") - } - - return - } - case 'n': // Prefix: "ns/" - if l := len("ns/"); len(elem) >= l && elem[0:l] == "ns/" { + case 'd': // Prefix: "d" + if l := len("d"); len(elem) >= l && elem[0:l] == "d" { elem = elem[l:] } else { break @@ -183,8 +163,8 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { break } switch elem[0] { - case 'b': // Prefix: "backresolve" - if l := len("backresolve"); len(elem) >= l && elem[0:l] == "backresolve" { + case 'i': // Prefix: "iff" + if l := len("iff"); len(elem) >= l && elem[0:l] == "iff" { elem = elem[l:] } else { break @@ -194,7 +174,7 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { // Leaf node. switch r.Method { case "GET": - s.handleAccountDnsBackResolveRequest([1]string{ + s.handleGetAccountDiffRequest([1]string{ args[0], }, elemIsEscaped, w, r) default: @@ -203,92 +183,143 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { return } - case 'e': // Prefix: "expiring" - if l := len("expiring"); len(elem) >= l && elem[0:l] == "expiring" { + case 'n': // Prefix: "ns/" + if l := len("ns/"); len(elem) >= l && elem[0:l] == "ns/" { elem = elem[l:] } else { break } if len(elem) == 0 { - // Leaf node. - switch r.Method { - case "GET": - s.handleGetAccountDnsExpiringRequest([1]string{ - args[0], - }, elemIsEscaped, w, r) - default: - s.notAllowed(w, r, "GET") + break + } + switch elem[0] { + case 'b': // Prefix: "backresolve" + if l := len("backresolve"); len(elem) >= l && elem[0:l] == "backresolve" { + elem = elem[l:] + } else { + break } - return - } - } - } - case 'e': // Prefix: "events" - if l := len("events"); len(elem) >= l && elem[0:l] == "events" { - elem = elem[l:] - } else { - break - } + if len(elem) == 0 { + // Leaf node. + switch r.Method { + case "GET": + s.handleAccountDnsBackResolveRequest([1]string{ + args[0], + }, elemIsEscaped, w, r) + default: + s.notAllowed(w, r, "GET") + } - if len(elem) == 0 { - switch r.Method { - case "GET": - s.handleGetAccountEventsRequest([1]string{ - args[0], - }, elemIsEscaped, w, r) - default: - s.notAllowed(w, r, "GET") - } + return + } + case 'e': // Prefix: "expiring" + if l := len("expiring"); len(elem) >= l && elem[0:l] == "expiring" { + elem = elem[l:] + } else { + break + } - return - } - switch elem[0] { - case '/': // Prefix: "/" - if l := len("/"); len(elem) >= l && elem[0:l] == "/" { + if len(elem) == 0 { + // Leaf node. + switch r.Method { + case "GET": + s.handleGetAccountDnsExpiringRequest([1]string{ + args[0], + }, elemIsEscaped, w, r) + default: + s.notAllowed(w, r, "GET") + } + + return + } + } + } + case 'e': // Prefix: "events" + if l := len("events"); len(elem) >= l && elem[0:l] == "events" { elem = elem[l:] } else { break } if len(elem) == 0 { - break + switch r.Method { + case "GET": + s.handleGetAccountEventsRequest([1]string{ + args[0], + }, elemIsEscaped, w, r) + default: + s.notAllowed(w, r, "GET") + } + + return } switch elem[0] { - case 'e': // Prefix: "emulate" - if l := len("emulate"); len(elem) >= l && elem[0:l] == "emulate" { + case '/': // Prefix: "/" + if l := len("/"); len(elem) >= l && elem[0:l] == "/" { elem = elem[l:] } else { break } + if len(elem) == 0 { + break + } + switch elem[0] { + case 'e': // Prefix: "emulate" + if l := len("emulate"); len(elem) >= l && elem[0:l] == "emulate" { + elem = elem[l:] + } else { + break + } + + if len(elem) == 0 { + // Leaf node. + switch r.Method { + case "POST": + s.handleEmulateMessageToAccountEventRequest([1]string{ + args[0], + }, elemIsEscaped, w, r) + default: + s.notAllowed(w, r, "POST") + } + + return + } + } + // Param: "event_id" + // Leaf parameter + args[1] = elem + elem = "" + if len(elem) == 0 { // Leaf node. switch r.Method { - case "POST": - s.handleEmulateMessageToAccountEventRequest([1]string{ + case "GET": + s.handleGetAccountEventRequest([2]string{ args[0], + args[1], }, elemIsEscaped, w, r) default: - s.notAllowed(w, r, "POST") + s.notAllowed(w, r, "GET") } return } } - // Param: "event_id" - // Leaf parameter - args[1] = elem - elem = "" + case 'j': // Prefix: "jettons" + if l := len("jettons"); len(elem) >= l && elem[0:l] == "jettons" { + elem = elem[l:] + } else { + break + } if len(elem) == 0 { - // Leaf node. switch r.Method { case "GET": - s.handleGetAccountEventRequest([2]string{ + s.handleGetAccountJettonsBalancesRequest([1]string{ args[0], - args[1], }, elemIsEscaped, w, r) default: s.notAllowed(w, r, "GET") @@ -296,70 +327,93 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { return } - } - case 'j': // Prefix: "jettons" - if l := len("jettons"); len(elem) >= l && elem[0:l] == "jettons" { - elem = elem[l:] - } else { - break - } - - if len(elem) == 0 { - switch r.Method { - case "GET": - s.handleGetAccountJettonsBalancesRequest([1]string{ - args[0], - }, elemIsEscaped, w, r) - default: - s.notAllowed(w, r, "GET") - } - - return - } - switch elem[0] { - case '/': // Prefix: "/" - if l := len("/"); len(elem) >= l && elem[0:l] == "/" { - elem = elem[l:] - } else { - break - } - - if len(elem) == 0 { - break - } switch elem[0] { - case 'h': // Prefix: "history" - if l := len("history"); len(elem) >= l && elem[0:l] == "history" { + case '/': // Prefix: "/" + if l := len("/"); len(elem) >= l && elem[0:l] == "/" { elem = elem[l:] } else { break } if len(elem) == 0 { - // Leaf node. - switch r.Method { - case "GET": - s.handleGetAccountJettonsHistoryRequest([1]string{ - args[0], - }, elemIsEscaped, w, r) - default: - s.notAllowed(w, r, "GET") + break + } + switch elem[0] { + case 'h': // Prefix: "history" + if l := len("history"); len(elem) >= l && elem[0:l] == "history" { + elem = elem[l:] + } else { + break } - return + if len(elem) == 0 { + // Leaf node. + switch r.Method { + case "GET": + s.handleGetAccountJettonsHistoryRequest([1]string{ + args[0], + }, elemIsEscaped, w, r) + default: + s.notAllowed(w, r, "GET") + } + + return + } + } + // Param: "jetton_id" + // Match until "/" + idx := strings.IndexByte(elem, '/') + if idx < 0 { + idx = len(elem) + } + args[1] = elem[:idx] + elem = elem[idx:] + + if len(elem) == 0 { + break + } + switch elem[0] { + case '/': // Prefix: "/history" + if l := len("/history"); len(elem) >= l && elem[0:l] == "/history" { + elem = elem[l:] + } else { + break + } + + if len(elem) == 0 { + // Leaf node. + switch r.Method { + case "GET": + s.handleGetAccountJettonHistoryByIDRequest([2]string{ + args[0], + args[1], + }, elemIsEscaped, w, r) + default: + s.notAllowed(w, r, "GET") + } + + return + } } } - // Param: "jetton_id" - // Match until "/" - idx := strings.IndexByte(elem, '/') - if idx < 0 { - idx = len(elem) + case 'n': // Prefix: "nfts" + if l := len("nfts"); len(elem) >= l && elem[0:l] == "nfts" { + elem = elem[l:] + } else { + break } - args[1] = elem[:idx] - elem = elem[idx:] if len(elem) == 0 { - break + switch r.Method { + case "GET": + s.handleGetAccountNftItemsRequest([1]string{ + args[0], + }, elemIsEscaped, w, r) + default: + s.notAllowed(w, r, "GET") + } + + return } switch elem[0] { case '/': // Prefix: "/history" @@ -373,9 +427,8 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { // Leaf node. switch r.Method { case "GET": - s.handleGetAccountJettonHistoryByIDRequest([2]string{ + s.handleGetAccountNftHistoryRequest([1]string{ args[0], - args[1], }, elemIsEscaped, w, r) default: s.notAllowed(w, r, "GET") @@ -384,29 +437,48 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { return } } - } - case 'n': // Prefix: "nfts" - if l := len("nfts"); len(elem) >= l && elem[0:l] == "nfts" { - elem = elem[l:] - } else { - break - } + case 'p': // Prefix: "publickey" + if l := len("publickey"); len(elem) >= l && elem[0:l] == "publickey" { + elem = elem[l:] + } else { + break + } - if len(elem) == 0 { - switch r.Method { - case "GET": - s.handleGetAccountNftItemsRequest([1]string{ - args[0], - }, elemIsEscaped, w, r) - default: - s.notAllowed(w, r, "GET") + if len(elem) == 0 { + // Leaf node. + switch r.Method { + case "GET": + s.handleGetAccountPublicKeyRequest([1]string{ + args[0], + }, elemIsEscaped, w, r) + default: + s.notAllowed(w, r, "GET") + } + + return + } + case 'r': // Prefix: "reindex" + if l := len("reindex"); len(elem) >= l && elem[0:l] == "reindex" { + elem = elem[l:] + } else { + break } - return - } - switch elem[0] { - case '/': // Prefix: "/history" - if l := len("/history"); len(elem) >= l && elem[0:l] == "/history" { + if len(elem) == 0 { + // Leaf node. + switch r.Method { + case "POST": + s.handleReindexAccountRequest([1]string{ + args[0], + }, elemIsEscaped, w, r) + default: + s.notAllowed(w, r, "POST") + } + + return + } + case 's': // Prefix: "subscriptions" + if l := len("subscriptions"); len(elem) >= l && elem[0:l] == "subscriptions" { elem = elem[l:] } else { break @@ -416,7 +488,7 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { // Leaf node. switch r.Method { case "GET": - s.handleGetAccountNftHistoryRequest([1]string{ + s.handleGetAccountSubscriptionsRequest([1]string{ args[0], }, elemIsEscaped, w, r) default: @@ -425,69 +497,50 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { return } - } - case 'p': // Prefix: "publickey" - if l := len("publickey"); len(elem) >= l && elem[0:l] == "publickey" { - elem = elem[l:] - } else { - break - } - - if len(elem) == 0 { - // Leaf node. - switch r.Method { - case "GET": - s.handleGetAccountPublicKeyRequest([1]string{ - args[0], - }, elemIsEscaped, w, r) - default: - s.notAllowed(w, r, "GET") + case 't': // Prefix: "traces" + if l := len("traces"); len(elem) >= l && elem[0:l] == "traces" { + elem = elem[l:] + } else { + break } - return - } - case 'r': // Prefix: "reindex" - if l := len("reindex"); len(elem) >= l && elem[0:l] == "reindex" { - elem = elem[l:] - } else { - break - } + if len(elem) == 0 { + // Leaf node. + switch r.Method { + case "GET": + s.handleGetAccountTracesRequest([1]string{ + args[0], + }, elemIsEscaped, w, r) + default: + s.notAllowed(w, r, "GET") + } - if len(elem) == 0 { - // Leaf node. - switch r.Method { - case "POST": - s.handleReindexAccountRequest([1]string{ - args[0], - }, elemIsEscaped, w, r) - default: - s.notAllowed(w, r, "POST") + return } - - return - } - case 's': // Prefix: "subscriptions" - if l := len("subscriptions"); len(elem) >= l && elem[0:l] == "subscriptions" { - elem = elem[l:] - } else { - break } + } + case 'd': // Prefix: "ddress/" + if l := len("ddress/"); len(elem) >= l && elem[0:l] == "ddress/" { + elem = elem[l:] + } else { + break + } - if len(elem) == 0 { - // Leaf node. - switch r.Method { - case "GET": - s.handleGetAccountSubscriptionsRequest([1]string{ - args[0], - }, elemIsEscaped, w, r) - default: - s.notAllowed(w, r, "GET") - } + // Param: "account_id" + // Match until "/" + idx := strings.IndexByte(elem, '/') + if idx < 0 { + idx = len(elem) + } + args[0] = elem[:idx] + elem = elem[idx:] - return - } - case 't': // Prefix: "traces" - if l := len("traces"); len(elem) >= l && elem[0:l] == "traces" { + if len(elem) == 0 { + break + } + switch elem[0] { + case '/': // Prefix: "/parse" + if l := len("/parse"); len(elem) >= l && elem[0:l] == "/parse" { elem = elem[l:] } else { break @@ -497,7 +550,7 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { // Leaf node. switch r.Method { case "GET": - s.handleGetAccountTracesRequest([1]string{ + s.handleAddressParseRequest([1]string{ args[0], }, elemIsEscaped, w, r) default: @@ -2302,8 +2355,8 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) { break } switch elem[0] { - case 'a': // Prefix: "accounts/" - if l := len("accounts/"); len(elem) >= l && elem[0:l] == "accounts/" { + case 'a': // Prefix: "a" + if l := len("a"); len(elem) >= l && elem[0:l] == "a" { elem = elem[l:] } else { break @@ -2313,88 +2366,88 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) { break } switch elem[0] { - case '_': // Prefix: "_bulk" - if l := len("_bulk"); len(elem) >= l && elem[0:l] == "_bulk" { + case 'c': // Prefix: "ccounts/" + if l := len("ccounts/"); len(elem) >= l && elem[0:l] == "ccounts/" { elem = elem[l:] } else { break } if len(elem) == 0 { - switch method { - case "POST": - // Leaf: GetAccounts - r.name = "GetAccounts" - r.summary = "" - r.operationID = "getAccounts" - r.pathPattern = "/v2/accounts/_bulk" - r.args = args - r.count = 0 - return r, true - default: - return + break + } + switch elem[0] { + case '_': // Prefix: "_bulk" + if l := len("_bulk"); len(elem) >= l && elem[0:l] == "_bulk" { + elem = elem[l:] + } else { + break + } + + if len(elem) == 0 { + switch method { + case "POST": + // Leaf: GetAccounts + r.name = "GetAccounts" + r.summary = "" + r.operationID = "getAccounts" + r.pathPattern = "/v2/accounts/_bulk" + r.args = args + r.count = 0 + return r, true + default: + return + } + } + case 's': // Prefix: "search" + if l := len("search"); len(elem) >= l && elem[0:l] == "search" { + elem = elem[l:] + } else { + break + } + + if len(elem) == 0 { + switch method { + case "GET": + // Leaf: SearchAccounts + r.name = "SearchAccounts" + r.summary = "" + r.operationID = "searchAccounts" + r.pathPattern = "/v2/accounts/search" + r.args = args + r.count = 0 + return r, true + default: + return + } } } - case 's': // Prefix: "search" - if l := len("search"); len(elem) >= l && elem[0:l] == "search" { - elem = elem[l:] - } else { - break + // Param: "account_id" + // Match until "/" + idx := strings.IndexByte(elem, '/') + if idx < 0 { + idx = len(elem) } + args[0] = elem[:idx] + elem = elem[idx:] if len(elem) == 0 { switch method { case "GET": - // Leaf: SearchAccounts - r.name = "SearchAccounts" + r.name = "GetAccount" r.summary = "" - r.operationID = "searchAccounts" - r.pathPattern = "/v2/accounts/search" + r.operationID = "getAccount" + r.pathPattern = "/v2/accounts/{account_id}" r.args = args - r.count = 0 + r.count = 1 return r, true default: return } } - } - // Param: "account_id" - // Match until "/" - idx := strings.IndexByte(elem, '/') - if idx < 0 { - idx = len(elem) - } - args[0] = elem[:idx] - elem = elem[idx:] - - if len(elem) == 0 { - switch method { - case "GET": - r.name = "GetAccount" - r.summary = "" - r.operationID = "getAccount" - r.pathPattern = "/v2/accounts/{account_id}" - r.args = args - r.count = 1 - return r, true - default: - return - } - } - switch elem[0] { - case '/': // Prefix: "/" - if l := len("/"); len(elem) >= l && elem[0:l] == "/" { - elem = elem[l:] - } else { - break - } - - if len(elem) == 0 { - break - } switch elem[0] { - case 'd': // Prefix: "d" - if l := len("d"); len(elem) >= l && elem[0:l] == "d" { + case '/': // Prefix: "/" + if l := len("/"); len(elem) >= l && elem[0:l] == "/" { elem = elem[l:] } else { break @@ -2404,30 +2457,8 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) { break } switch elem[0] { - case 'i': // Prefix: "iff" - if l := len("iff"); len(elem) >= l && elem[0:l] == "iff" { - elem = elem[l:] - } else { - break - } - - if len(elem) == 0 { - switch method { - case "GET": - // Leaf: GetAccountDiff - r.name = "GetAccountDiff" - r.summary = "" - r.operationID = "getAccountDiff" - r.pathPattern = "/v2/accounts/{account_id}/diff" - r.args = args - r.count = 1 - return r, true - default: - return - } - } - case 'n': // Prefix: "ns/" - if l := len("ns/"); len(elem) >= l && elem[0:l] == "ns/" { + case 'd': // Prefix: "d" + if l := len("d"); len(elem) >= l && elem[0:l] == "d" { elem = elem[l:] } else { break @@ -2437,8 +2468,8 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) { break } switch elem[0] { - case 'b': // Prefix: "backresolve" - if l := len("backresolve"); len(elem) >= l && elem[0:l] == "backresolve" { + case 'i': // Prefix: "iff" + if l := len("iff"); len(elem) >= l && elem[0:l] == "iff" { elem = elem[l:] } else { break @@ -2447,11 +2478,11 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) { if len(elem) == 0 { switch method { case "GET": - // Leaf: AccountDnsBackResolve - r.name = "AccountDnsBackResolve" + // Leaf: GetAccountDiff + r.name = "GetAccountDiff" r.summary = "" - r.operationID = "accountDnsBackResolve" - r.pathPattern = "/v2/accounts/{account_id}/dns/backresolve" + r.operationID = "getAccountDiff" + r.pathPattern = "/v2/accounts/{account_id}/diff" r.args = args r.count = 1 return r, true @@ -2459,174 +2490,253 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) { return } } - case 'e': // Prefix: "expiring" - if l := len("expiring"); len(elem) >= l && elem[0:l] == "expiring" { + case 'n': // Prefix: "ns/" + if l := len("ns/"); len(elem) >= l && elem[0:l] == "ns/" { elem = elem[l:] } else { break } if len(elem) == 0 { - switch method { - case "GET": - // Leaf: GetAccountDnsExpiring - r.name = "GetAccountDnsExpiring" - r.summary = "" - r.operationID = "getAccountDnsExpiring" - r.pathPattern = "/v2/accounts/{account_id}/dns/expiring" - r.args = args - r.count = 1 - return r, true - default: - return - } + break } - } - } - case 'e': // Prefix: "events" - if l := len("events"); len(elem) >= l && elem[0:l] == "events" { - elem = elem[l:] - } else { - break - } + switch elem[0] { + case 'b': // Prefix: "backresolve" + if l := len("backresolve"); len(elem) >= l && elem[0:l] == "backresolve" { + elem = elem[l:] + } else { + break + } - if len(elem) == 0 { - switch method { - case "GET": - r.name = "GetAccountEvents" - r.summary = "" - r.operationID = "getAccountEvents" - r.pathPattern = "/v2/accounts/{account_id}/events" - r.args = args - r.count = 1 - return r, true - default: - return + if len(elem) == 0 { + switch method { + case "GET": + // Leaf: AccountDnsBackResolve + r.name = "AccountDnsBackResolve" + r.summary = "" + r.operationID = "accountDnsBackResolve" + r.pathPattern = "/v2/accounts/{account_id}/dns/backresolve" + r.args = args + r.count = 1 + return r, true + default: + return + } + } + case 'e': // Prefix: "expiring" + if l := len("expiring"); len(elem) >= l && elem[0:l] == "expiring" { + elem = elem[l:] + } else { + break + } + + if len(elem) == 0 { + switch method { + case "GET": + // Leaf: GetAccountDnsExpiring + r.name = "GetAccountDnsExpiring" + r.summary = "" + r.operationID = "getAccountDnsExpiring" + r.pathPattern = "/v2/accounts/{account_id}/dns/expiring" + r.args = args + r.count = 1 + return r, true + default: + return + } + } + } } - } - switch elem[0] { - case '/': // Prefix: "/" - if l := len("/"); len(elem) >= l && elem[0:l] == "/" { + case 'e': // Prefix: "events" + if l := len("events"); len(elem) >= l && elem[0:l] == "events" { elem = elem[l:] } else { break } if len(elem) == 0 { - break + switch method { + case "GET": + r.name = "GetAccountEvents" + r.summary = "" + r.operationID = "getAccountEvents" + r.pathPattern = "/v2/accounts/{account_id}/events" + r.args = args + r.count = 1 + return r, true + default: + return + } } switch elem[0] { - case 'e': // Prefix: "emulate" - if l := len("emulate"); len(elem) >= l && elem[0:l] == "emulate" { + case '/': // Prefix: "/" + if l := len("/"); len(elem) >= l && elem[0:l] == "/" { elem = elem[l:] } else { break } + if len(elem) == 0 { + break + } + switch elem[0] { + case 'e': // Prefix: "emulate" + if l := len("emulate"); len(elem) >= l && elem[0:l] == "emulate" { + elem = elem[l:] + } else { + break + } + + if len(elem) == 0 { + switch method { + case "POST": + // Leaf: EmulateMessageToAccountEvent + r.name = "EmulateMessageToAccountEvent" + r.summary = "" + r.operationID = "emulateMessageToAccountEvent" + r.pathPattern = "/v2/accounts/{account_id}/events/emulate" + r.args = args + r.count = 1 + return r, true + default: + return + } + } + } + // Param: "event_id" + // Leaf parameter + args[1] = elem + elem = "" + if len(elem) == 0 { switch method { - case "POST": - // Leaf: EmulateMessageToAccountEvent - r.name = "EmulateMessageToAccountEvent" + case "GET": + // Leaf: GetAccountEvent + r.name = "GetAccountEvent" r.summary = "" - r.operationID = "emulateMessageToAccountEvent" - r.pathPattern = "/v2/accounts/{account_id}/events/emulate" + r.operationID = "getAccountEvent" + r.pathPattern = "/v2/accounts/{account_id}/events/{event_id}" r.args = args - r.count = 1 + r.count = 2 return r, true default: return } } } - // Param: "event_id" - // Leaf parameter - args[1] = elem - elem = "" + case 'j': // Prefix: "jettons" + if l := len("jettons"); len(elem) >= l && elem[0:l] == "jettons" { + elem = elem[l:] + } else { + break + } if len(elem) == 0 { switch method { case "GET": - // Leaf: GetAccountEvent - r.name = "GetAccountEvent" + r.name = "GetAccountJettonsBalances" r.summary = "" - r.operationID = "getAccountEvent" - r.pathPattern = "/v2/accounts/{account_id}/events/{event_id}" + r.operationID = "getAccountJettonsBalances" + r.pathPattern = "/v2/accounts/{account_id}/jettons" r.args = args - r.count = 2 + r.count = 1 return r, true default: return } } - } - case 'j': // Prefix: "jettons" - if l := len("jettons"); len(elem) >= l && elem[0:l] == "jettons" { - elem = elem[l:] - } else { - break - } - - if len(elem) == 0 { - switch method { - case "GET": - r.name = "GetAccountJettonsBalances" - r.summary = "" - r.operationID = "getAccountJettonsBalances" - r.pathPattern = "/v2/accounts/{account_id}/jettons" - r.args = args - r.count = 1 - return r, true - default: - return - } - } - switch elem[0] { - case '/': // Prefix: "/" - if l := len("/"); len(elem) >= l && elem[0:l] == "/" { - elem = elem[l:] - } else { - break - } - - if len(elem) == 0 { - break - } switch elem[0] { - case 'h': // Prefix: "history" - if l := len("history"); len(elem) >= l && elem[0:l] == "history" { + case '/': // Prefix: "/" + if l := len("/"); len(elem) >= l && elem[0:l] == "/" { elem = elem[l:] } else { break } if len(elem) == 0 { - switch method { - case "GET": - // Leaf: GetAccountJettonsHistory - r.name = "GetAccountJettonsHistory" - r.summary = "" - r.operationID = "getAccountJettonsHistory" - r.pathPattern = "/v2/accounts/{account_id}/jettons/history" - r.args = args - r.count = 1 - return r, true - default: - return + break + } + switch elem[0] { + case 'h': // Prefix: "history" + if l := len("history"); len(elem) >= l && elem[0:l] == "history" { + elem = elem[l:] + } else { + break + } + + if len(elem) == 0 { + switch method { + case "GET": + // Leaf: GetAccountJettonsHistory + r.name = "GetAccountJettonsHistory" + r.summary = "" + r.operationID = "getAccountJettonsHistory" + r.pathPattern = "/v2/accounts/{account_id}/jettons/history" + r.args = args + r.count = 1 + return r, true + default: + return + } + } + } + // Param: "jetton_id" + // Match until "/" + idx := strings.IndexByte(elem, '/') + if idx < 0 { + idx = len(elem) + } + args[1] = elem[:idx] + elem = elem[idx:] + + if len(elem) == 0 { + break + } + switch elem[0] { + case '/': // Prefix: "/history" + if l := len("/history"); len(elem) >= l && elem[0:l] == "/history" { + elem = elem[l:] + } else { + break + } + + if len(elem) == 0 { + switch method { + case "GET": + // Leaf: GetAccountJettonHistoryByID + r.name = "GetAccountJettonHistoryByID" + r.summary = "" + r.operationID = "getAccountJettonHistoryByID" + r.pathPattern = "/v2/accounts/{account_id}/jettons/{jetton_id}/history" + r.args = args + r.count = 2 + return r, true + default: + return + } } } } - // Param: "jetton_id" - // Match until "/" - idx := strings.IndexByte(elem, '/') - if idx < 0 { - idx = len(elem) + case 'n': // Prefix: "nfts" + if l := len("nfts"); len(elem) >= l && elem[0:l] == "nfts" { + elem = elem[l:] + } else { + break } - args[1] = elem[:idx] - elem = elem[idx:] if len(elem) == 0 { - break + switch method { + case "GET": + r.name = "GetAccountNftItems" + r.summary = "" + r.operationID = "getAccountNftItems" + r.pathPattern = "/v2/accounts/{account_id}/nfts" + r.args = args + r.count = 1 + return r, true + default: + return + } } switch elem[0] { case '/': // Prefix: "/history" @@ -2639,44 +2749,21 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) { if len(elem) == 0 { switch method { case "GET": - // Leaf: GetAccountJettonHistoryByID - r.name = "GetAccountJettonHistoryByID" + // Leaf: GetAccountNftHistory + r.name = "GetAccountNftHistory" r.summary = "" - r.operationID = "getAccountJettonHistoryByID" - r.pathPattern = "/v2/accounts/{account_id}/jettons/{jetton_id}/history" + r.operationID = "getAccountNftHistory" + r.pathPattern = "/v2/accounts/{account_id}/nfts/history" r.args = args - r.count = 2 + r.count = 1 return r, true default: return } } } - } - case 'n': // Prefix: "nfts" - if l := len("nfts"); len(elem) >= l && elem[0:l] == "nfts" { - elem = elem[l:] - } else { - break - } - - if len(elem) == 0 { - switch method { - case "GET": - r.name = "GetAccountNftItems" - r.summary = "" - r.operationID = "getAccountNftItems" - r.pathPattern = "/v2/accounts/{account_id}/nfts" - r.args = args - r.count = 1 - return r, true - default: - return - } - } - switch elem[0] { - case '/': // Prefix: "/history" - if l := len("/history"); len(elem) >= l && elem[0:l] == "/history" { + case 'p': // Prefix: "publickey" + if l := len("publickey"); len(elem) >= l && elem[0:l] == "publickey" { elem = elem[l:] } else { break @@ -2685,11 +2772,11 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) { if len(elem) == 0 { switch method { case "GET": - // Leaf: GetAccountNftHistory - r.name = "GetAccountNftHistory" + // Leaf: GetAccountPublicKey + r.name = "GetAccountPublicKey" r.summary = "" - r.operationID = "getAccountNftHistory" - r.pathPattern = "/v2/accounts/{account_id}/nfts/history" + r.operationID = "getAccountPublicKey" + r.pathPattern = "/v2/accounts/{account_id}/publickey" r.args = args r.count = 1 return r, true @@ -2697,75 +2784,96 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) { return } } - } - case 'p': // Prefix: "publickey" - if l := len("publickey"); len(elem) >= l && elem[0:l] == "publickey" { - elem = elem[l:] - } else { - break - } + case 'r': // Prefix: "reindex" + if l := len("reindex"); len(elem) >= l && elem[0:l] == "reindex" { + elem = elem[l:] + } else { + break + } - if len(elem) == 0 { - switch method { - case "GET": - // Leaf: GetAccountPublicKey - r.name = "GetAccountPublicKey" - r.summary = "" - r.operationID = "getAccountPublicKey" - r.pathPattern = "/v2/accounts/{account_id}/publickey" - r.args = args - r.count = 1 - return r, true - default: - return + if len(elem) == 0 { + switch method { + case "POST": + // Leaf: ReindexAccount + r.name = "ReindexAccount" + r.summary = "" + r.operationID = "reindexAccount" + r.pathPattern = "/v2/accounts/{account_id}/reindex" + r.args = args + r.count = 1 + return r, true + default: + return + } + } + case 's': // Prefix: "subscriptions" + if l := len("subscriptions"); len(elem) >= l && elem[0:l] == "subscriptions" { + elem = elem[l:] + } else { + break } - } - case 'r': // Prefix: "reindex" - if l := len("reindex"); len(elem) >= l && elem[0:l] == "reindex" { - elem = elem[l:] - } else { - break - } - if len(elem) == 0 { - switch method { - case "POST": - // Leaf: ReindexAccount - r.name = "ReindexAccount" - r.summary = "" - r.operationID = "reindexAccount" - r.pathPattern = "/v2/accounts/{account_id}/reindex" - r.args = args - r.count = 1 - return r, true - default: - return + if len(elem) == 0 { + switch method { + case "GET": + // Leaf: GetAccountSubscriptions + r.name = "GetAccountSubscriptions" + r.summary = "" + r.operationID = "getAccountSubscriptions" + r.pathPattern = "/v2/accounts/{account_id}/subscriptions" + r.args = args + r.count = 1 + return r, true + default: + return + } + } + case 't': // Prefix: "traces" + if l := len("traces"); len(elem) >= l && elem[0:l] == "traces" { + elem = elem[l:] + } else { + break } - } - case 's': // Prefix: "subscriptions" - if l := len("subscriptions"); len(elem) >= l && elem[0:l] == "subscriptions" { - elem = elem[l:] - } else { - break - } - if len(elem) == 0 { - switch method { - case "GET": - // Leaf: GetAccountSubscriptions - r.name = "GetAccountSubscriptions" - r.summary = "" - r.operationID = "getAccountSubscriptions" - r.pathPattern = "/v2/accounts/{account_id}/subscriptions" - r.args = args - r.count = 1 - return r, true - default: - return + if len(elem) == 0 { + switch method { + case "GET": + // Leaf: GetAccountTraces + r.name = "GetAccountTraces" + r.summary = "" + r.operationID = "getAccountTraces" + r.pathPattern = "/v2/accounts/{account_id}/traces" + r.args = args + r.count = 1 + return r, true + default: + return + } } } - case 't': // Prefix: "traces" - if l := len("traces"); len(elem) >= l && elem[0:l] == "traces" { + } + case 'd': // Prefix: "ddress/" + if l := len("ddress/"); len(elem) >= l && elem[0:l] == "ddress/" { + elem = elem[l:] + } else { + break + } + + // Param: "account_id" + // Match until "/" + idx := strings.IndexByte(elem, '/') + if idx < 0 { + idx = len(elem) + } + args[0] = elem[:idx] + elem = elem[idx:] + + if len(elem) == 0 { + break + } + switch elem[0] { + case '/': // Prefix: "/parse" + if l := len("/parse"); len(elem) >= l && elem[0:l] == "/parse" { elem = elem[l:] } else { break @@ -2774,11 +2882,11 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) { if len(elem) == 0 { switch method { case "GET": - // Leaf: GetAccountTraces - r.name = "GetAccountTraces" + // Leaf: AddressParse + r.name = "AddressParse" r.summary = "" - r.operationID = "getAccountTraces" - r.pathPattern = "/v2/accounts/{account_id}/traces" + r.operationID = "addressParse" + r.pathPattern = "/v2/address/{account_id}/parse" r.args = args r.count = 1 return r, true diff --git a/pkg/oas/oas_schemas_gen.go b/pkg/oas/oas_schemas_gen.go index f146c85b..ef3fff20 100644 --- a/pkg/oas/oas_schemas_gen.go +++ b/pkg/oas/oas_schemas_gen.go @@ -1168,6 +1168,114 @@ func (s *ActionType) UnmarshalText(data []byte) error { } } +type AddressParseOK struct { + RawForm string `json:"raw_form"` + Bounceable AddressParseOKBounceable `json:"bounceable"` + NonBounceable AddressParseOKNonBounceable `json:"non_bounceable"` + GivenType string `json:"given_type"` + TestOnly bool `json:"test_only"` +} + +// GetRawForm returns the value of RawForm. +func (s *AddressParseOK) GetRawForm() string { + return s.RawForm +} + +// GetBounceable returns the value of Bounceable. +func (s *AddressParseOK) GetBounceable() AddressParseOKBounceable { + return s.Bounceable +} + +// GetNonBounceable returns the value of NonBounceable. +func (s *AddressParseOK) GetNonBounceable() AddressParseOKNonBounceable { + return s.NonBounceable +} + +// GetGivenType returns the value of GivenType. +func (s *AddressParseOK) GetGivenType() string { + return s.GivenType +} + +// GetTestOnly returns the value of TestOnly. +func (s *AddressParseOK) GetTestOnly() bool { + return s.TestOnly +} + +// SetRawForm sets the value of RawForm. +func (s *AddressParseOK) SetRawForm(val string) { + s.RawForm = val +} + +// SetBounceable sets the value of Bounceable. +func (s *AddressParseOK) SetBounceable(val AddressParseOKBounceable) { + s.Bounceable = val +} + +// SetNonBounceable sets the value of NonBounceable. +func (s *AddressParseOK) SetNonBounceable(val AddressParseOKNonBounceable) { + s.NonBounceable = val +} + +// SetGivenType sets the value of GivenType. +func (s *AddressParseOK) SetGivenType(val string) { + s.GivenType = val +} + +// SetTestOnly sets the value of TestOnly. +func (s *AddressParseOK) SetTestOnly(val bool) { + s.TestOnly = val +} + +type AddressParseOKBounceable struct { + B64 string `json:"b64"` + B64url string `json:"b64url"` +} + +// GetB64 returns the value of B64. +func (s *AddressParseOKBounceable) GetB64() string { + return s.B64 +} + +// GetB64url returns the value of B64url. +func (s *AddressParseOKBounceable) GetB64url() string { + return s.B64url +} + +// SetB64 sets the value of B64. +func (s *AddressParseOKBounceable) SetB64(val string) { + s.B64 = val +} + +// SetB64url sets the value of B64url. +func (s *AddressParseOKBounceable) SetB64url(val string) { + s.B64url = val +} + +type AddressParseOKNonBounceable struct { + B64 string `json:"b64"` + B64url string `json:"b64url"` +} + +// GetB64 returns the value of B64. +func (s *AddressParseOKNonBounceable) GetB64() string { + return s.B64 +} + +// GetB64url returns the value of B64url. +func (s *AddressParseOKNonBounceable) GetB64url() string { + return s.B64url +} + +// SetB64 sets the value of B64. +func (s *AddressParseOKNonBounceable) SetB64(val string) { + s.B64 = val +} + +// SetB64url sets the value of B64url. +func (s *AddressParseOKNonBounceable) SetB64url(val string) { + s.B64url = val +} + // Ref: #/components/schemas/ApyHistory type ApyHistory struct { Apy float64 `json:"apy"` diff --git a/pkg/oas/oas_server_gen.go b/pkg/oas/oas_server_gen.go index 7d11e403..e010cc7e 100644 --- a/pkg/oas/oas_server_gen.go +++ b/pkg/oas/oas_server_gen.go @@ -14,6 +14,12 @@ type Handler interface { // // GET /v2/accounts/{account_id}/dns/backresolve AccountDnsBackResolve(ctx context.Context, params AccountDnsBackResolveParams) (*DomainNames, error) + // AddressParse implements addressParse operation. + // + // Parse address and display in all formats. + // + // GET /v2/address/{account_id}/parse + AddressParse(ctx context.Context, params AddressParseParams) (*AddressParseOK, error) // BlockchainAccountInspect implements blockchainAccountInspect operation. // // Blockchain account inspect. diff --git a/pkg/oas/oas_unimplemented_gen.go b/pkg/oas/oas_unimplemented_gen.go index b51d568f..e6352aae 100644 --- a/pkg/oas/oas_unimplemented_gen.go +++ b/pkg/oas/oas_unimplemented_gen.go @@ -22,6 +22,15 @@ func (UnimplementedHandler) AccountDnsBackResolve(ctx context.Context, params Ac return r, ht.ErrNotImplemented } +// AddressParse implements addressParse operation. +// +// Parse address and display in all formats. +// +// GET /v2/address/{account_id}/parse +func (UnimplementedHandler) AddressParse(ctx context.Context, params AddressParseParams) (r *AddressParseOK, _ error) { + return r, ht.ErrNotImplemented +} + // BlockchainAccountInspect implements blockchainAccountInspect operation. // // Blockchain account inspect. diff --git a/tonapi/oas_client_gen.go b/tonapi/oas_client_gen.go index f378d1ce..5b7e91af 100644 --- a/tonapi/oas_client_gen.go +++ b/tonapi/oas_client_gen.go @@ -29,6 +29,12 @@ type Invoker interface { // // GET /v2/accounts/{account_id}/dns/backresolve AccountDnsBackResolve(ctx context.Context, params AccountDnsBackResolveParams) (*DomainNames, error) + // AddressParse invokes addressParse operation. + // + // Parse address and display in all formats. + // + // GET /v2/address/{account_id}/parse + AddressParse(ctx context.Context, params AddressParseParams) (*AddressParseOK, error) // BlockchainAccountInspect invokes blockchainAccountInspect operation. // // Blockchain account inspect. @@ -655,6 +661,97 @@ func (c *Client) sendAccountDnsBackResolve(ctx context.Context, params AccountDn return result, nil } +// AddressParse invokes addressParse operation. +// +// Parse address and display in all formats. +// +// GET /v2/address/{account_id}/parse +func (c *Client) AddressParse(ctx context.Context, params AddressParseParams) (*AddressParseOK, error) { + res, err := c.sendAddressParse(ctx, params) + return res, err +} + +func (c *Client) sendAddressParse(ctx context.Context, params AddressParseParams) (res *AddressParseOK, err error) { + otelAttrs := []attribute.KeyValue{ + otelogen.OperationID("addressParse"), + semconv.HTTPMethodKey.String("GET"), + semconv.HTTPRouteKey.String("/v2/address/{account_id}/parse"), + } + + // Run stopwatch. + startTime := time.Now() + defer func() { + // Use floating point division here for higher precision (instead of Millisecond method). + elapsedDuration := time.Since(startTime) + c.duration.Record(ctx, float64(float64(elapsedDuration)/float64(time.Millisecond)), metric.WithAttributes(otelAttrs...)) + }() + + // Increment request counter. + c.requests.Add(ctx, 1, metric.WithAttributes(otelAttrs...)) + + // Start a span for this request. + ctx, span := c.cfg.Tracer.Start(ctx, "AddressParse", + trace.WithAttributes(otelAttrs...), + clientSpanKind, + ) + // Track stage for error reporting. + var stage string + defer func() { + if err != nil { + span.RecordError(err) + span.SetStatus(codes.Error, stage) + c.errors.Add(ctx, 1, metric.WithAttributes(otelAttrs...)) + } + span.End() + }() + + stage = "BuildURL" + u := uri.Clone(c.requestURL(ctx)) + var pathParts [3]string + pathParts[0] = "/v2/address/" + { + // Encode "account_id" parameter. + e := uri.NewPathEncoder(uri.PathEncoderConfig{ + Param: "account_id", + Style: uri.PathStyleSimple, + Explode: false, + }) + if err := func() error { + return e.EncodeValue(conv.StringToString(params.AccountID)) + }(); err != nil { + return res, errors.Wrap(err, "encode path") + } + encoded, err := e.Result() + if err != nil { + return res, errors.Wrap(err, "encode path") + } + pathParts[1] = encoded + } + pathParts[2] = "/parse" + uri.AddPathParts(u, pathParts[:]...) + + stage = "EncodeRequest" + r, err := ht.NewRequest(ctx, "GET", u) + if err != nil { + return res, errors.Wrap(err, "create request") + } + + stage = "SendRequest" + resp, err := c.cfg.Client.Do(r) + if err != nil { + return res, errors.Wrap(err, "do request") + } + defer resp.Body.Close() + + stage = "DecodeResponse" + result, err := decodeAddressParseResponse(resp) + if err != nil { + return res, errors.Wrap(err, "decode response") + } + + return result, nil +} + // BlockchainAccountInspect invokes blockchainAccountInspect operation. // // Blockchain account inspect. diff --git a/tonapi/oas_json_gen.go b/tonapi/oas_json_gen.go index 07900b02..36c4a96f 100644 --- a/tonapi/oas_json_gen.go +++ b/tonapi/oas_json_gen.go @@ -2452,6 +2452,392 @@ func (s *ActionType) UnmarshalJSON(data []byte) error { return s.Decode(d) } +// Encode implements json.Marshaler. +func (s *AddressParseOK) Encode(e *jx.Encoder) { + e.ObjStart() + s.encodeFields(e) + e.ObjEnd() +} + +// encodeFields encodes fields. +func (s *AddressParseOK) encodeFields(e *jx.Encoder) { + { + e.FieldStart("raw_form") + e.Str(s.RawForm) + } + { + e.FieldStart("bounceable") + s.Bounceable.Encode(e) + } + { + e.FieldStart("non_bounceable") + s.NonBounceable.Encode(e) + } + { + e.FieldStart("given_type") + e.Str(s.GivenType) + } + { + e.FieldStart("test_only") + e.Bool(s.TestOnly) + } +} + +var jsonFieldsNameOfAddressParseOK = [5]string{ + 0: "raw_form", + 1: "bounceable", + 2: "non_bounceable", + 3: "given_type", + 4: "test_only", +} + +// Decode decodes AddressParseOK from json. +func (s *AddressParseOK) Decode(d *jx.Decoder) error { + if s == nil { + return errors.New("invalid: unable to decode AddressParseOK to nil") + } + var requiredBitSet [1]uint8 + + if err := d.ObjBytes(func(d *jx.Decoder, k []byte) error { + switch string(k) { + case "raw_form": + requiredBitSet[0] |= 1 << 0 + if err := func() error { + v, err := d.Str() + s.RawForm = string(v) + if err != nil { + return err + } + return nil + }(); err != nil { + return errors.Wrap(err, "decode field \"raw_form\"") + } + case "bounceable": + requiredBitSet[0] |= 1 << 1 + if err := func() error { + if err := s.Bounceable.Decode(d); err != nil { + return err + } + return nil + }(); err != nil { + return errors.Wrap(err, "decode field \"bounceable\"") + } + case "non_bounceable": + requiredBitSet[0] |= 1 << 2 + if err := func() error { + if err := s.NonBounceable.Decode(d); err != nil { + return err + } + return nil + }(); err != nil { + return errors.Wrap(err, "decode field \"non_bounceable\"") + } + case "given_type": + requiredBitSet[0] |= 1 << 3 + if err := func() error { + v, err := d.Str() + s.GivenType = string(v) + if err != nil { + return err + } + return nil + }(); err != nil { + return errors.Wrap(err, "decode field \"given_type\"") + } + case "test_only": + requiredBitSet[0] |= 1 << 4 + if err := func() error { + v, err := d.Bool() + s.TestOnly = bool(v) + if err != nil { + return err + } + return nil + }(); err != nil { + return errors.Wrap(err, "decode field \"test_only\"") + } + default: + return d.Skip() + } + return nil + }); err != nil { + return errors.Wrap(err, "decode AddressParseOK") + } + // Validate required fields. + var failures []validate.FieldError + for i, mask := range [1]uint8{ + 0b00011111, + } { + if result := (requiredBitSet[i] & mask) ^ mask; result != 0 { + // Mask only required fields and check equality to mask using XOR. + // + // If XOR result is not zero, result is not equal to expected, so some fields are missed. + // Bits of fields which would be set are actually bits of missed fields. + missed := bits.OnesCount8(result) + for bitN := 0; bitN < missed; bitN++ { + bitIdx := bits.TrailingZeros8(result) + fieldIdx := i*8 + bitIdx + var name string + if fieldIdx < len(jsonFieldsNameOfAddressParseOK) { + name = jsonFieldsNameOfAddressParseOK[fieldIdx] + } else { + name = strconv.Itoa(fieldIdx) + } + failures = append(failures, validate.FieldError{ + Name: name, + Error: validate.ErrFieldRequired, + }) + // Reset bit. + result &^= 1 << bitIdx + } + } + } + if len(failures) > 0 { + return &validate.Error{Fields: failures} + } + + return nil +} + +// MarshalJSON implements stdjson.Marshaler. +func (s *AddressParseOK) MarshalJSON() ([]byte, error) { + e := jx.Encoder{} + s.Encode(&e) + return e.Bytes(), nil +} + +// UnmarshalJSON implements stdjson.Unmarshaler. +func (s *AddressParseOK) UnmarshalJSON(data []byte) error { + d := jx.DecodeBytes(data) + return s.Decode(d) +} + +// Encode implements json.Marshaler. +func (s *AddressParseOKBounceable) Encode(e *jx.Encoder) { + e.ObjStart() + s.encodeFields(e) + e.ObjEnd() +} + +// encodeFields encodes fields. +func (s *AddressParseOKBounceable) encodeFields(e *jx.Encoder) { + { + e.FieldStart("b64") + e.Str(s.B64) + } + { + e.FieldStart("b64url") + e.Str(s.B64url) + } +} + +var jsonFieldsNameOfAddressParseOKBounceable = [2]string{ + 0: "b64", + 1: "b64url", +} + +// Decode decodes AddressParseOKBounceable from json. +func (s *AddressParseOKBounceable) Decode(d *jx.Decoder) error { + if s == nil { + return errors.New("invalid: unable to decode AddressParseOKBounceable to nil") + } + var requiredBitSet [1]uint8 + + if err := d.ObjBytes(func(d *jx.Decoder, k []byte) error { + switch string(k) { + case "b64": + requiredBitSet[0] |= 1 << 0 + if err := func() error { + v, err := d.Str() + s.B64 = string(v) + if err != nil { + return err + } + return nil + }(); err != nil { + return errors.Wrap(err, "decode field \"b64\"") + } + case "b64url": + requiredBitSet[0] |= 1 << 1 + if err := func() error { + v, err := d.Str() + s.B64url = string(v) + if err != nil { + return err + } + return nil + }(); err != nil { + return errors.Wrap(err, "decode field \"b64url\"") + } + default: + return d.Skip() + } + return nil + }); err != nil { + return errors.Wrap(err, "decode AddressParseOKBounceable") + } + // Validate required fields. + var failures []validate.FieldError + for i, mask := range [1]uint8{ + 0b00000011, + } { + if result := (requiredBitSet[i] & mask) ^ mask; result != 0 { + // Mask only required fields and check equality to mask using XOR. + // + // If XOR result is not zero, result is not equal to expected, so some fields are missed. + // Bits of fields which would be set are actually bits of missed fields. + missed := bits.OnesCount8(result) + for bitN := 0; bitN < missed; bitN++ { + bitIdx := bits.TrailingZeros8(result) + fieldIdx := i*8 + bitIdx + var name string + if fieldIdx < len(jsonFieldsNameOfAddressParseOKBounceable) { + name = jsonFieldsNameOfAddressParseOKBounceable[fieldIdx] + } else { + name = strconv.Itoa(fieldIdx) + } + failures = append(failures, validate.FieldError{ + Name: name, + Error: validate.ErrFieldRequired, + }) + // Reset bit. + result &^= 1 << bitIdx + } + } + } + if len(failures) > 0 { + return &validate.Error{Fields: failures} + } + + return nil +} + +// MarshalJSON implements stdjson.Marshaler. +func (s *AddressParseOKBounceable) MarshalJSON() ([]byte, error) { + e := jx.Encoder{} + s.Encode(&e) + return e.Bytes(), nil +} + +// UnmarshalJSON implements stdjson.Unmarshaler. +func (s *AddressParseOKBounceable) UnmarshalJSON(data []byte) error { + d := jx.DecodeBytes(data) + return s.Decode(d) +} + +// Encode implements json.Marshaler. +func (s *AddressParseOKNonBounceable) Encode(e *jx.Encoder) { + e.ObjStart() + s.encodeFields(e) + e.ObjEnd() +} + +// encodeFields encodes fields. +func (s *AddressParseOKNonBounceable) encodeFields(e *jx.Encoder) { + { + e.FieldStart("b64") + e.Str(s.B64) + } + { + e.FieldStart("b64url") + e.Str(s.B64url) + } +} + +var jsonFieldsNameOfAddressParseOKNonBounceable = [2]string{ + 0: "b64", + 1: "b64url", +} + +// Decode decodes AddressParseOKNonBounceable from json. +func (s *AddressParseOKNonBounceable) Decode(d *jx.Decoder) error { + if s == nil { + return errors.New("invalid: unable to decode AddressParseOKNonBounceable to nil") + } + var requiredBitSet [1]uint8 + + if err := d.ObjBytes(func(d *jx.Decoder, k []byte) error { + switch string(k) { + case "b64": + requiredBitSet[0] |= 1 << 0 + if err := func() error { + v, err := d.Str() + s.B64 = string(v) + if err != nil { + return err + } + return nil + }(); err != nil { + return errors.Wrap(err, "decode field \"b64\"") + } + case "b64url": + requiredBitSet[0] |= 1 << 1 + if err := func() error { + v, err := d.Str() + s.B64url = string(v) + if err != nil { + return err + } + return nil + }(); err != nil { + return errors.Wrap(err, "decode field \"b64url\"") + } + default: + return d.Skip() + } + return nil + }); err != nil { + return errors.Wrap(err, "decode AddressParseOKNonBounceable") + } + // Validate required fields. + var failures []validate.FieldError + for i, mask := range [1]uint8{ + 0b00000011, + } { + if result := (requiredBitSet[i] & mask) ^ mask; result != 0 { + // Mask only required fields and check equality to mask using XOR. + // + // If XOR result is not zero, result is not equal to expected, so some fields are missed. + // Bits of fields which would be set are actually bits of missed fields. + missed := bits.OnesCount8(result) + for bitN := 0; bitN < missed; bitN++ { + bitIdx := bits.TrailingZeros8(result) + fieldIdx := i*8 + bitIdx + var name string + if fieldIdx < len(jsonFieldsNameOfAddressParseOKNonBounceable) { + name = jsonFieldsNameOfAddressParseOKNonBounceable[fieldIdx] + } else { + name = strconv.Itoa(fieldIdx) + } + failures = append(failures, validate.FieldError{ + Name: name, + Error: validate.ErrFieldRequired, + }) + // Reset bit. + result &^= 1 << bitIdx + } + } + } + if len(failures) > 0 { + return &validate.Error{Fields: failures} + } + + return nil +} + +// MarshalJSON implements stdjson.Marshaler. +func (s *AddressParseOKNonBounceable) MarshalJSON() ([]byte, error) { + e := jx.Encoder{} + s.Encode(&e) + return e.Bytes(), nil +} + +// UnmarshalJSON implements stdjson.Unmarshaler. +func (s *AddressParseOKNonBounceable) UnmarshalJSON(data []byte) error { + d := jx.DecodeBytes(data) + return s.Decode(d) +} + // Encode implements json.Marshaler. func (s *ApyHistory) Encode(e *jx.Encoder) { e.ObjStart() diff --git a/tonapi/oas_parameters_gen.go b/tonapi/oas_parameters_gen.go index d0f71871..e9f5c0d9 100644 --- a/tonapi/oas_parameters_gen.go +++ b/tonapi/oas_parameters_gen.go @@ -8,6 +8,12 @@ type AccountDnsBackResolveParams struct { AccountID string } +// AddressParseParams is parameters of addressParse operation. +type AddressParseParams struct { + // Account ID. + AccountID string +} + // BlockchainAccountInspectParams is parameters of blockchainAccountInspect operation. type BlockchainAccountInspectParams struct { // Account ID. diff --git a/tonapi/oas_response_decoders_gen.go b/tonapi/oas_response_decoders_gen.go index 1beaaf6f..2e36a9ef 100644 --- a/tonapi/oas_response_decoders_gen.go +++ b/tonapi/oas_response_decoders_gen.go @@ -97,6 +97,89 @@ func decodeAccountDnsBackResolveResponse(resp *http.Response) (res *DomainNames, return res, errors.Wrap(defRes, "error") } +func decodeAddressParseResponse(resp *http.Response) (res *AddressParseOK, _ error) { + switch resp.StatusCode { + case 200: + // Code 200. + ct, _, err := mime.ParseMediaType(resp.Header.Get("Content-Type")) + if err != nil { + return res, errors.Wrap(err, "parse media type") + } + switch { + case ct == "application/json": + buf, err := io.ReadAll(resp.Body) + if err != nil { + return res, err + } + d := jx.DecodeBytes(buf) + + var response AddressParseOK + if err := func() error { + if err := response.Decode(d); err != nil { + return err + } + if err := d.Skip(); err != io.EOF { + return errors.New("unexpected trailing data") + } + return nil + }(); err != nil { + err = &ogenerrors.DecodeBodyError{ + ContentType: ct, + Body: buf, + Err: err, + } + return res, err + } + return &response, nil + default: + return res, validate.InvalidContentType(ct) + } + } + // Convenient error response. + defRes, err := func() (res *ErrorStatusCode, err error) { + ct, _, err := mime.ParseMediaType(resp.Header.Get("Content-Type")) + if err != nil { + return res, errors.Wrap(err, "parse media type") + } + switch { + case ct == "application/json": + buf, err := io.ReadAll(resp.Body) + if err != nil { + return res, err + } + d := jx.DecodeBytes(buf) + + var response Error + if err := func() error { + if err := response.Decode(d); err != nil { + return err + } + if err := d.Skip(); err != io.EOF { + return errors.New("unexpected trailing data") + } + return nil + }(); err != nil { + err = &ogenerrors.DecodeBodyError{ + ContentType: ct, + Body: buf, + Err: err, + } + return res, err + } + return &ErrorStatusCode{ + StatusCode: resp.StatusCode, + Response: response, + }, nil + default: + return res, validate.InvalidContentType(ct) + } + }() + if err != nil { + return res, errors.Wrapf(err, "default (code %d)", resp.StatusCode) + } + return res, errors.Wrap(defRes, "error") +} + func decodeBlockchainAccountInspectResponse(resp *http.Response) (res *BlockchainAccountInspect, _ error) { switch resp.StatusCode { case 200: diff --git a/tonapi/oas_schemas_gen.go b/tonapi/oas_schemas_gen.go index b53fd530..87610578 100644 --- a/tonapi/oas_schemas_gen.go +++ b/tonapi/oas_schemas_gen.go @@ -1168,6 +1168,114 @@ func (s *ActionType) UnmarshalText(data []byte) error { } } +type AddressParseOK struct { + RawForm string `json:"raw_form"` + Bounceable AddressParseOKBounceable `json:"bounceable"` + NonBounceable AddressParseOKNonBounceable `json:"non_bounceable"` + GivenType string `json:"given_type"` + TestOnly bool `json:"test_only"` +} + +// GetRawForm returns the value of RawForm. +func (s *AddressParseOK) GetRawForm() string { + return s.RawForm +} + +// GetBounceable returns the value of Bounceable. +func (s *AddressParseOK) GetBounceable() AddressParseOKBounceable { + return s.Bounceable +} + +// GetNonBounceable returns the value of NonBounceable. +func (s *AddressParseOK) GetNonBounceable() AddressParseOKNonBounceable { + return s.NonBounceable +} + +// GetGivenType returns the value of GivenType. +func (s *AddressParseOK) GetGivenType() string { + return s.GivenType +} + +// GetTestOnly returns the value of TestOnly. +func (s *AddressParseOK) GetTestOnly() bool { + return s.TestOnly +} + +// SetRawForm sets the value of RawForm. +func (s *AddressParseOK) SetRawForm(val string) { + s.RawForm = val +} + +// SetBounceable sets the value of Bounceable. +func (s *AddressParseOK) SetBounceable(val AddressParseOKBounceable) { + s.Bounceable = val +} + +// SetNonBounceable sets the value of NonBounceable. +func (s *AddressParseOK) SetNonBounceable(val AddressParseOKNonBounceable) { + s.NonBounceable = val +} + +// SetGivenType sets the value of GivenType. +func (s *AddressParseOK) SetGivenType(val string) { + s.GivenType = val +} + +// SetTestOnly sets the value of TestOnly. +func (s *AddressParseOK) SetTestOnly(val bool) { + s.TestOnly = val +} + +type AddressParseOKBounceable struct { + B64 string `json:"b64"` + B64url string `json:"b64url"` +} + +// GetB64 returns the value of B64. +func (s *AddressParseOKBounceable) GetB64() string { + return s.B64 +} + +// GetB64url returns the value of B64url. +func (s *AddressParseOKBounceable) GetB64url() string { + return s.B64url +} + +// SetB64 sets the value of B64. +func (s *AddressParseOKBounceable) SetB64(val string) { + s.B64 = val +} + +// SetB64url sets the value of B64url. +func (s *AddressParseOKBounceable) SetB64url(val string) { + s.B64url = val +} + +type AddressParseOKNonBounceable struct { + B64 string `json:"b64"` + B64url string `json:"b64url"` +} + +// GetB64 returns the value of B64. +func (s *AddressParseOKNonBounceable) GetB64() string { + return s.B64 +} + +// GetB64url returns the value of B64url. +func (s *AddressParseOKNonBounceable) GetB64url() string { + return s.B64url +} + +// SetB64 sets the value of B64. +func (s *AddressParseOKNonBounceable) SetB64(val string) { + s.B64 = val +} + +// SetB64url sets the value of B64url. +func (s *AddressParseOKNonBounceable) SetB64url(val string) { + s.B64url = val +} + // Ref: #/components/schemas/ApyHistory type ApyHistory struct { Apy float64 `json:"apy"`