From 7d440b8696d412e291d1508bf0c011081607d79e Mon Sep 17 00:00:00 2001 From: "aleksej.paschenko" Date: Mon, 11 Sep 2023 11:51:59 +0300 Subject: [PATCH] Add jetton preview to ValueFlow --- api/openapi.json | 9 ++++- api/openapi.yml | 3 ++ client/oas_json_gen.go | 23 ++++++++++-- client/oas_schemas_gen.go | 11 ++++++ client/oas_validators_gen.go | 69 +++++++++++++++++++++++++++++++++++ pkg/api/event_converters.go | 23 +++++++++--- pkg/bath/value_flow.go | 6 +-- pkg/oas/oas_json_gen.go | 23 ++++++++++-- pkg/oas/oas_schemas_gen.go | 11 ++++++ pkg/oas/oas_validators_gen.go | 69 +++++++++++++++++++++++++++++++++++ 10 files changed, 229 insertions(+), 18 deletions(-) diff --git a/api/openapi.json b/api/openapi.json index 2a607977..1c591094 100644 --- a/api/openapi.json +++ b/api/openapi.json @@ -3436,7 +3436,11 @@ "items": { "properties": { "account": { - "$ref": "#/components/schemas/AccountAddress" + "$ref": "#/components/schemas/AccountAddress", + "deprecated": true + }, + "jetton": { + "$ref": "#/components/schemas/JettonPreview" }, "quantity": { "example": 10, @@ -3446,7 +3450,8 @@ }, "required": [ "account", - "quantity" + "quantity", + "jetton" ], "type": "object" }, diff --git a/api/openapi.yml b/api/openapi.yml index 7f7be079..2c1c0b00 100644 --- a/api/openapi.yml +++ b/api/openapi.yml @@ -3401,9 +3401,12 @@ components: required: - account - quantity + - jetton properties: account: $ref: '#/components/schemas/AccountAddress' + jetton: + $ref: '#/components/schemas/JettonPreview' quantity: type: integer format: int64 diff --git a/client/oas_json_gen.go b/client/oas_json_gen.go index 0eccec42..479f185f 100644 --- a/client/oas_json_gen.go +++ b/client/oas_json_gen.go @@ -23013,15 +23013,20 @@ func (s *ValueFlowJettonsItem) encodeFields(e *jx.Encoder) { e.FieldStart("account") s.Account.Encode(e) } + { + e.FieldStart("jetton") + s.Jetton.Encode(e) + } { e.FieldStart("quantity") e.Int64(s.Quantity) } } -var jsonFieldsNameOfValueFlowJettonsItem = [2]string{ +var jsonFieldsNameOfValueFlowJettonsItem = [3]string{ 0: "account", - 1: "quantity", + 1: "jetton", + 2: "quantity", } // Decode decodes ValueFlowJettonsItem from json. @@ -23043,8 +23048,18 @@ func (s *ValueFlowJettonsItem) Decode(d *jx.Decoder) error { }(); err != nil { return errors.Wrap(err, "decode field \"account\"") } - case "quantity": + case "jetton": requiredBitSet[0] |= 1 << 1 + if err := func() error { + if err := s.Jetton.Decode(d); err != nil { + return err + } + return nil + }(); err != nil { + return errors.Wrap(err, "decode field \"jetton\"") + } + case "quantity": + requiredBitSet[0] |= 1 << 2 if err := func() error { v, err := d.Int64() s.Quantity = int64(v) @@ -23065,7 +23080,7 @@ func (s *ValueFlowJettonsItem) Decode(d *jx.Decoder) error { // Validate required fields. var failures []validate.FieldError for i, mask := range [1]uint8{ - 0b00000011, + 0b00000111, } { if result := (requiredBitSet[i] & mask) ^ mask; result != 0 { // Mask only required fields and check equality to mask using XOR. diff --git a/client/oas_schemas_gen.go b/client/oas_schemas_gen.go index b4848194..8016fcde 100644 --- a/client/oas_schemas_gen.go +++ b/client/oas_schemas_gen.go @@ -9477,6 +9477,7 @@ func (s *ValueFlow) SetJettons(val []ValueFlowJettonsItem) { type ValueFlowJettonsItem struct { Account AccountAddress `json:"account"` + Jetton JettonPreview `json:"jetton"` Quantity int64 `json:"quantity"` } @@ -9485,6 +9486,11 @@ func (s *ValueFlowJettonsItem) GetAccount() AccountAddress { return s.Account } +// GetJetton returns the value of Jetton. +func (s *ValueFlowJettonsItem) GetJetton() JettonPreview { + return s.Jetton +} + // GetQuantity returns the value of Quantity. func (s *ValueFlowJettonsItem) GetQuantity() int64 { return s.Quantity @@ -9495,6 +9501,11 @@ func (s *ValueFlowJettonsItem) SetAccount(val AccountAddress) { s.Account = val } +// SetJetton sets the value of Jetton. +func (s *ValueFlowJettonsItem) SetJetton(val JettonPreview) { + s.Jetton = val +} + // SetQuantity sets the value of Quantity. func (s *ValueFlowJettonsItem) SetQuantity(val int64) { s.Quantity = val diff --git a/client/oas_validators_gen.go b/client/oas_validators_gen.go index 4b9d198c..b1ae074c 100644 --- a/client/oas_validators_gen.go +++ b/client/oas_validators_gen.go @@ -1047,6 +1047,23 @@ func (s *Event) Validate() error { if s.ValueFlow == nil { return errors.New("nil is invalid value") } + var failures []validate.FieldError + for i, elem := range s.ValueFlow { + if err := func() error { + if err := elem.Validate(); err != nil { + return err + } + return nil + }(); err != nil { + failures = append(failures, validate.FieldError{ + Name: fmt.Sprintf("[%d]", i), + Error: err, + }) + } + } + if len(failures) > 0 { + return &validate.Error{Fields: failures} + } return nil }(); err != nil { failures = append(failures, validate.FieldError{ @@ -2600,6 +2617,58 @@ func (s *ValidatorsSet) Validate() error { return nil } +func (s *ValueFlow) Validate() error { + var failures []validate.FieldError + if err := func() error { + var failures []validate.FieldError + for i, elem := range s.Jettons { + if err := func() error { + if err := elem.Validate(); err != nil { + return err + } + return nil + }(); err != nil { + failures = append(failures, validate.FieldError{ + Name: fmt.Sprintf("[%d]", i), + Error: err, + }) + } + } + if len(failures) > 0 { + return &validate.Error{Fields: failures} + } + return nil + }(); err != nil { + failures = append(failures, validate.FieldError{ + Name: "jettons", + Error: err, + }) + } + if len(failures) > 0 { + return &validate.Error{Fields: failures} + } + return nil +} + +func (s *ValueFlowJettonsItem) Validate() error { + var failures []validate.FieldError + if err := func() error { + if err := s.Jetton.Validate(); err != nil { + return err + } + return nil + }(); err != nil { + failures = append(failures, validate.FieldError{ + Name: "jetton", + Error: err, + }) + } + if len(failures) > 0 { + return &validate.Error{Fields: failures} + } + return nil +} + func (s *WalletDNS) Validate() error { var failures []validate.FieldError if err := func() error { diff --git a/pkg/api/event_converters.go b/pkg/api/event_converters.go index e1e0003e..a567ae32 100644 --- a/pkg/api/event_converters.go +++ b/pkg/api/event_converters.go @@ -4,10 +4,11 @@ import ( "context" "encoding/hex" "fmt" - "github.com/tonkeeper/tongo/ton" "math/big" "strings" + "github.com/tonkeeper/tongo/ton" + "github.com/tonkeeper/opentonapi/pkg/references" rules "github.com/tonkeeper/scam_backoffice_rules" @@ -641,15 +642,16 @@ func (h Handler) convertAction(ctx context.Context, viewer *tongo.AccountID, a b return action, spamDetected, nil } -func convertAccountValueFlow(accountID tongo.AccountID, flow *bath.AccountValueFlow, book addressBook) oas.ValueFlow { +func convertAccountValueFlow(accountID tongo.AccountID, flow *bath.AccountValueFlow, book addressBook, previews map[tongo.AccountID]oas.JettonPreview) oas.ValueFlow { valueFlow := oas.ValueFlow{ Account: convertAccountAddress(accountID, book), Ton: flow.Ton, Fees: flow.Fees, } - for jettonItem, quantity := range flow.Jettons { + for jettonMaster, quantity := range flow.Jettons { valueFlow.Jettons = append(valueFlow.Jettons, oas.ValueFlowJettonsItem{ - Account: convertAccountAddress(jettonItem, book), + Account: convertAccountAddress(jettonMaster, book), + Jetton: previews[jettonMaster], Quantity: quantity.Int64(), }) } @@ -674,8 +676,19 @@ func (h Handler) toEvent(ctx context.Context, trace *core.Trace, result *bath.Ac event.IsScam = event.IsScam || spamDetected event.Actions[i] = convertedAction } + + previews := make(map[tongo.AccountID]oas.JettonPreview) + for _, flow := range result.ValueFlow.Accounts { + for jettonMaster := range flow.Jettons { + if _, ok := previews[jettonMaster]; ok { + continue + } + meta := h.GetJettonNormalizedMetadata(ctx, jettonMaster) + previews[jettonMaster] = jettonPreview(jettonMaster, meta) + } + } for accountID, flow := range result.ValueFlow.Accounts { - event.ValueFlow = append(event.ValueFlow, convertAccountValueFlow(accountID, flow, h.addressBook)) + event.ValueFlow = append(event.ValueFlow, convertAccountValueFlow(accountID, flow, h.addressBook, previews)) } return event, nil } diff --git a/pkg/bath/value_flow.go b/pkg/bath/value_flow.go index 55b4d6e6..e624f433 100644 --- a/pkg/bath/value_flow.go +++ b/pkg/bath/value_flow.go @@ -40,7 +40,7 @@ func (flow *ValueFlow) AddFee(accountID tongo.AccountID, amount int64) { flow.Accounts[accountID] = &AccountValueFlow{Fees: amount} } -func (flow *ValueFlow) AddJettons(accountID tongo.AccountID, jetton tongo.AccountID, value big.Int) { +func (flow *ValueFlow) AddJettons(accountID tongo.AccountID, jettonMaster tongo.AccountID, value big.Int) { accountFlow, ok := flow.Accounts[accountID] if !ok { accountFlow = &AccountValueFlow{} @@ -49,10 +49,10 @@ func (flow *ValueFlow) AddJettons(accountID tongo.AccountID, jetton tongo.Accoun if accountFlow.Jettons == nil { accountFlow.Jettons = make(map[tongo.AccountID]big.Int, 1) } - current := accountFlow.Jettons[jetton] + current := accountFlow.Jettons[jettonMaster] newValue := big.Int{} newValue.Add(¤t, &value) - accountFlow.Jettons[jetton] = newValue + accountFlow.Jettons[jettonMaster] = newValue } func (flow *ValueFlow) Merge(other *ValueFlow) { diff --git a/pkg/oas/oas_json_gen.go b/pkg/oas/oas_json_gen.go index 008bda2b..46c26576 100644 --- a/pkg/oas/oas_json_gen.go +++ b/pkg/oas/oas_json_gen.go @@ -23013,15 +23013,20 @@ func (s *ValueFlowJettonsItem) encodeFields(e *jx.Encoder) { e.FieldStart("account") s.Account.Encode(e) } + { + e.FieldStart("jetton") + s.Jetton.Encode(e) + } { e.FieldStart("quantity") e.Int64(s.Quantity) } } -var jsonFieldsNameOfValueFlowJettonsItem = [2]string{ +var jsonFieldsNameOfValueFlowJettonsItem = [3]string{ 0: "account", - 1: "quantity", + 1: "jetton", + 2: "quantity", } // Decode decodes ValueFlowJettonsItem from json. @@ -23043,8 +23048,18 @@ func (s *ValueFlowJettonsItem) Decode(d *jx.Decoder) error { }(); err != nil { return errors.Wrap(err, "decode field \"account\"") } - case "quantity": + case "jetton": requiredBitSet[0] |= 1 << 1 + if err := func() error { + if err := s.Jetton.Decode(d); err != nil { + return err + } + return nil + }(); err != nil { + return errors.Wrap(err, "decode field \"jetton\"") + } + case "quantity": + requiredBitSet[0] |= 1 << 2 if err := func() error { v, err := d.Int64() s.Quantity = int64(v) @@ -23065,7 +23080,7 @@ func (s *ValueFlowJettonsItem) Decode(d *jx.Decoder) error { // Validate required fields. var failures []validate.FieldError for i, mask := range [1]uint8{ - 0b00000011, + 0b00000111, } { if result := (requiredBitSet[i] & mask) ^ mask; result != 0 { // Mask only required fields and check equality to mask using XOR. diff --git a/pkg/oas/oas_schemas_gen.go b/pkg/oas/oas_schemas_gen.go index 7e0b5fe6..dfcb5af4 100644 --- a/pkg/oas/oas_schemas_gen.go +++ b/pkg/oas/oas_schemas_gen.go @@ -9477,6 +9477,7 @@ func (s *ValueFlow) SetJettons(val []ValueFlowJettonsItem) { type ValueFlowJettonsItem struct { Account AccountAddress `json:"account"` + Jetton JettonPreview `json:"jetton"` Quantity int64 `json:"quantity"` } @@ -9485,6 +9486,11 @@ func (s *ValueFlowJettonsItem) GetAccount() AccountAddress { return s.Account } +// GetJetton returns the value of Jetton. +func (s *ValueFlowJettonsItem) GetJetton() JettonPreview { + return s.Jetton +} + // GetQuantity returns the value of Quantity. func (s *ValueFlowJettonsItem) GetQuantity() int64 { return s.Quantity @@ -9495,6 +9501,11 @@ func (s *ValueFlowJettonsItem) SetAccount(val AccountAddress) { s.Account = val } +// SetJetton sets the value of Jetton. +func (s *ValueFlowJettonsItem) SetJetton(val JettonPreview) { + s.Jetton = val +} + // SetQuantity sets the value of Quantity. func (s *ValueFlowJettonsItem) SetQuantity(val int64) { s.Quantity = val diff --git a/pkg/oas/oas_validators_gen.go b/pkg/oas/oas_validators_gen.go index 64a1323f..149aab9e 100644 --- a/pkg/oas/oas_validators_gen.go +++ b/pkg/oas/oas_validators_gen.go @@ -1047,6 +1047,23 @@ func (s *Event) Validate() error { if s.ValueFlow == nil { return errors.New("nil is invalid value") } + var failures []validate.FieldError + for i, elem := range s.ValueFlow { + if err := func() error { + if err := elem.Validate(); err != nil { + return err + } + return nil + }(); err != nil { + failures = append(failures, validate.FieldError{ + Name: fmt.Sprintf("[%d]", i), + Error: err, + }) + } + } + if len(failures) > 0 { + return &validate.Error{Fields: failures} + } return nil }(); err != nil { failures = append(failures, validate.FieldError{ @@ -2600,6 +2617,58 @@ func (s *ValidatorsSet) Validate() error { return nil } +func (s *ValueFlow) Validate() error { + var failures []validate.FieldError + if err := func() error { + var failures []validate.FieldError + for i, elem := range s.Jettons { + if err := func() error { + if err := elem.Validate(); err != nil { + return err + } + return nil + }(); err != nil { + failures = append(failures, validate.FieldError{ + Name: fmt.Sprintf("[%d]", i), + Error: err, + }) + } + } + if len(failures) > 0 { + return &validate.Error{Fields: failures} + } + return nil + }(); err != nil { + failures = append(failures, validate.FieldError{ + Name: "jettons", + Error: err, + }) + } + if len(failures) > 0 { + return &validate.Error{Fields: failures} + } + return nil +} + +func (s *ValueFlowJettonsItem) Validate() error { + var failures []validate.FieldError + if err := func() error { + if err := s.Jetton.Validate(); err != nil { + return err + } + return nil + }(); err != nil { + failures = append(failures, validate.FieldError{ + Name: "jetton", + Error: err, + }) + } + if len(failures) > 0 { + return &validate.Error{Fields: failures} + } + return nil +} + func (s *WalletDNS) Validate() error { var failures []validate.FieldError if err := func() error {