From 324ba39a61c210ce43fb825ab1e64e850713822c Mon Sep 17 00:00:00 2001 From: Alexey Kostenko Date: Thu, 5 Dec 2024 13:19:01 +0300 Subject: [PATCH 1/3] get jetton history --- pkg/api/interfaces.go | 4 +- pkg/api/jetton_converters.go | 104 +++++++++++++++++++++-------------- pkg/api/jetton_handlers.go | 8 +-- pkg/core/jetton.go | 24 ++++++++ 4 files changed, 94 insertions(+), 46 deletions(-) diff --git a/pkg/api/interfaces.go b/pkg/api/interfaces.go index e045da95..19416c49 100644 --- a/pkg/api/interfaces.go +++ b/pkg/api/interfaces.go @@ -75,8 +75,8 @@ type storage interface { GetJettonHolders(ctx context.Context, jettonMaster tongo.AccountID, limit, offset int) ([]core.JettonHolder, error) GetJettonMasterMetadata(ctx context.Context, master tongo.AccountID) (tongo.JettonMetadata, error) GetJettonMasterData(ctx context.Context, master tongo.AccountID) (core.JettonMaster, error) - GetAccountJettonsHistory(ctx context.Context, address tongo.AccountID, limit int, beforeLT, startTime, endTime *int64) ([]tongo.Bits256, error) - GetAccountJettonHistoryByID(ctx context.Context, address, jettonMaster tongo.AccountID, limit int, beforeLT, startTime, endTime *int64) ([]tongo.Bits256, error) + GetAccountJettonsHistory(ctx context.Context, address tongo.AccountID, limit int, beforeLT, startTime, endTime *int64) ([]core.JettonOperation, error) + GetAccountJettonHistoryByID(ctx context.Context, address, jettonMaster tongo.AccountID, limit int, beforeLT, startTime, endTime *int64) ([]core.JettonOperation, error) GetJettonTransferPayload(ctx context.Context, accountID, jettonMaster ton.AccountID) (*core.JettonTransferPayload, error) GetAllAuctions(ctx context.Context) ([]core.Auction, error) diff --git a/pkg/api/jetton_converters.go b/pkg/api/jetton_converters.go index 61ba34d6..327419bb 100644 --- a/pkg/api/jetton_converters.go +++ b/pkg/api/jetton_converters.go @@ -4,6 +4,7 @@ import ( "context" "errors" "fmt" + "github.com/tonkeeper/tongo/tlb" "net/http" "strings" @@ -51,57 +52,80 @@ func jettonMetadata(account ton.AccountID, meta NormalizedMetadata) oas.JettonMe return metadata } -func (h *Handler) convertJettonHistory(ctx context.Context, account ton.AccountID, master *ton.AccountID, traceIDs []ton.Bits256, acceptLanguage oas.OptString) ([]oas.AccountEvent, int64, error) { +func (h *Handler) convertJettonHistory(ctx context.Context, account ton.AccountID, master *ton.AccountID, history []core.JettonOperation, acceptLanguage oas.OptString) ([]oas.AccountEvent, int64, error) { var lastLT uint64 - events := make([]oas.AccountEvent, 0, len(traceIDs)) - for _, traceID := range traceIDs { - trace, err := h.storage.GetTrace(ctx, traceID) - if err != nil { - if errors.Is(err, core.ErrTraceIsTooLong) { - // we ignore this for now, because we believe that this case is extremely rare. - continue + var events []oas.AccountEvent + res := make(map[core.TraceID]oas.AccountEvent) + + for _, op := range history { + event, ok := res[op.TraceID] + if !ok { + event = oas.AccountEvent{ + EventID: op.TraceID.Hash.Hex(), + Account: convertAccountAddress(account, h.addressBook), + Timestamp: op.TraceID.UTime, + IsScam: false, + Lt: int64(op.TraceID.Lt), + //InProgress: trace.InProgress(), // TODO: always false? + //Extra: result.Extra(account), // TODO: extra? } - return nil, 0, err - } - result, err := bath.FindActions(ctx, trace, - bath.WithStraws(bath.JettonTransfersBurnsMints), - bath.WithInformationSource(h.storage)) - if err != nil { - return nil, 0, err } - event := oas.AccountEvent{ - EventID: trace.Hash.Hex(), - Account: convertAccountAddress(account, h.addressBook), - Timestamp: trace.Utime, - IsScam: false, - Lt: int64(trace.Lt), - InProgress: trace.InProgress(), - Extra: result.Extra(account), - } - for _, action := range result.Actions { - if action.Type != bath.JettonTransfer && action.Type != bath.JettonBurn && action.Type != bath.JettonMint { - continue - } - if master != nil && ((action.JettonTransfer != nil && action.JettonTransfer.Jetton != *master) || - (action.JettonMint != nil && action.JettonMint.Jetton != *master) || - (action.JettonBurn != nil && action.JettonBurn.Jetton != *master)) { - continue + + var action bath.Action + switch op.Operation { + case core.TransferJettonOperation: + transferAction := bath.JettonTransferAction{ + //Comment: *string, + //EncryptedComment: *EncryptedComment, + Jetton: op.JettonMaster, + Recipient: op.Destination, + Sender: op.Source, + //RecipientsWallet: tongo.AccountID, + //SendersWallet: tongo.AccountID, + Amount: tlb.VarUInteger16(*op.Amount.BigInt()), + //Refund: *Refund, + //isWrappedTon: bool, } - if !action.IsSubject(account) { - continue + action.Type = "JettonTransfer" + action.JettonTransfer = &transferAction + case core.MintJettonOperation: + mintAction := bath.JettonMintAction{ + Jetton: op.JettonMaster, + Recipient: *op.Destination, + //RecipientsWallet: tongo.AccountID, + Amount: tlb.VarUInteger16(*op.Amount.BigInt()), } - convertedAction, err := h.convertAction(ctx, &account, action, acceptLanguage) - if err != nil { - return nil, 0, err + action.Type = "JettonMint" + action.JettonMint = &mintAction + case core.BurnJettonOperation: + burnAction := bath.JettonBurnAction{ + Jetton: op.JettonMaster, + Sender: *op.Source, + //SendersWallet: tongo.AccountID, + Amount: tlb.VarUInteger16(*op.Amount.BigInt()), } - event.Actions = append(event.Actions, convertedAction) + action.Type = "JettonTransfer" + action.JettonBurn = &burnAction + default: + continue + } + convertedAction, err := h.convertAction(ctx, &account, action, acceptLanguage) + if err != nil { + return nil, 0, err } - event.IsScam = h.spamFilter.CheckActions(event.Actions, &account, trace.Account) + event.Actions = append(event.Actions, convertedAction) + res[op.TraceID] = event + } + + for id, event := range res { + // event.IsScam = h.spamFilter.CheckActions(event.Actions, &account, trace.Account) TODO: trace.Account? we do not know initiator if len(event.Actions) == 0 { continue } events = append(events, event) - lastLT = trace.Lt + if id.Lt > lastLT { + lastLT = id.Lt + } } return events, int64(lastLT), nil diff --git a/pkg/api/jetton_handlers.go b/pkg/api/jetton_handlers.go index 20756222..5c217434 100644 --- a/pkg/api/jetton_handlers.go +++ b/pkg/api/jetton_handlers.go @@ -100,11 +100,11 @@ func (h *Handler) GetAccountJettonsHistory(ctx context.Context, params oas.GetAc if err != nil { return nil, toError(http.StatusBadRequest, err) } - traceIDs, err := h.storage.GetAccountJettonsHistory(ctx, account.ID, params.Limit, optIntToPointer(params.BeforeLt), optIntToPointer(params.StartDate), optIntToPointer(params.EndDate)) + history, err := h.storage.GetAccountJettonsHistory(ctx, account.ID, params.Limit, optIntToPointer(params.BeforeLt), optIntToPointer(params.StartDate), optIntToPointer(params.EndDate)) if err != nil { return nil, toError(http.StatusInternalServerError, err) } - events, lastLT, err := h.convertJettonHistory(ctx, account.ID, nil, traceIDs, params.AcceptLanguage) + events, lastLT, err := h.convertJettonHistory(ctx, account.ID, nil, history, params.AcceptLanguage) if err != nil { return nil, toError(http.StatusInternalServerError, err) } @@ -120,14 +120,14 @@ func (h *Handler) GetAccountJettonHistoryByID(ctx context.Context, params oas.Ge if err != nil { return nil, toError(http.StatusBadRequest, err) } - traceIDs, err := h.storage.GetAccountJettonHistoryByID(ctx, account.ID, jettonMasterAccount.ID, params.Limit, optIntToPointer(params.BeforeLt), optIntToPointer(params.StartDate), optIntToPointer(params.EndDate)) + history, err := h.storage.GetAccountJettonHistoryByID(ctx, account.ID, jettonMasterAccount.ID, params.Limit, optIntToPointer(params.BeforeLt), optIntToPointer(params.StartDate), optIntToPointer(params.EndDate)) if errors.Is(err, core.ErrEntityNotFound) { return &oas.AccountEvents{}, nil } if err != nil { return nil, toError(http.StatusInternalServerError, err) } - events, lastLT, err := h.convertJettonHistory(ctx, account.ID, &jettonMasterAccount.ID, traceIDs, params.AcceptLanguage) + events, lastLT, err := h.convertJettonHistory(ctx, account.ID, &jettonMasterAccount.ID, history, params.AcceptLanguage) if err != nil { return nil, toError(http.StatusInternalServerError, err) } diff --git a/pkg/core/jetton.go b/pkg/core/jetton.go index 56c370ef..0c513d5c 100644 --- a/pkg/core/jetton.go +++ b/pkg/core/jetton.go @@ -37,3 +37,27 @@ type JettonWalletLockData struct { FullBalance decimal.Decimal UnlockTime int64 } + +type JettonOperationType = string + +const ( + TransferJettonOperation JettonOperationType = "transfer" + MintJettonOperation JettonOperationType = "mint" + BurnJettonOperation JettonOperationType = "burn" + UnknownJettonOperation JettonOperationType = "unknown" +) + +type JettonOperation struct { + Operation JettonOperationType + Source *tongo.AccountID + Destination *tongo.AccountID + JettonMaster tongo.AccountID + TraceID TraceID + //TxID TxID + DestEndBalance decimal.Decimal + Amount decimal.Decimal + QueryID uint64 + ForwardPayload string + Lt uint64 + Utime int64 +} From aa92a88d4895807f327641e12f1d138ddc4b6bf5 Mon Sep 17 00:00:00 2001 From: Alexey Kostenko Date: Thu, 5 Dec 2024 17:26:57 +0300 Subject: [PATCH 2/3] jetton history updates --- pkg/api/event_converters.go | 4 ++-- pkg/api/interfaces.go | 2 +- pkg/api/jetton_converters.go | 39 ++++++++++++++++++++---------------- pkg/api/nft_converters.go | 2 +- pkg/core/jetton.go | 11 +++++----- pkg/litestorage/jetton.go | 4 ++-- pkg/spam/spam.go | 2 +- 7 files changed, 34 insertions(+), 30 deletions(-) diff --git a/pkg/api/event_converters.go b/pkg/api/event_converters.go index e265a5c8..112407b7 100644 --- a/pkg/api/event_converters.go +++ b/pkg/api/event_converters.go @@ -769,7 +769,7 @@ func (h *Handler) toEvent(ctx context.Context, trace *core.Trace, result *bath.A } event.Actions[i] = convertedAction } - event.IsScam = h.spamFilter.CheckActions(event.Actions, nil, trace.Account) + event.IsScam = h.spamFilter.CheckActions(event.Actions, nil, &trace.Account) previews := make(map[tongo.AccountID]oas.JettonPreview) for _, flow := range result.ValueFlow.Accounts { for jettonMaster := range flow.Jettons { @@ -849,7 +849,7 @@ func (h *Handler) toAccountEvent(ctx context.Context, account tongo.AccountID, t e.Actions = append(e.Actions, convertedAction) } if h.spamFilter != nil { - e.IsScam = h.spamFilter.CheckActions(e.Actions, &account, trace.Account) + e.IsScam = h.spamFilter.CheckActions(e.Actions, &account, &trace.Account) } if len(e.Actions) == 0 { e.Actions = []oas.Action{ diff --git a/pkg/api/interfaces.go b/pkg/api/interfaces.go index 19416c49..879b1e5d 100644 --- a/pkg/api/interfaces.go +++ b/pkg/api/interfaces.go @@ -179,7 +179,7 @@ type ratesSource interface { } type SpamFilter interface { - CheckActions(actions []oas.Action, viewer *ton.AccountID, initiator ton.AccountID) bool + CheckActions(actions []oas.Action, viewer *ton.AccountID, initiator *ton.AccountID) bool JettonTrust(address tongo.AccountID, symbol, name, image string) core.TrustType NftTrust(address tongo.AccountID, collection *ton.AccountID, description, image string) core.TrustType } diff --git a/pkg/api/jetton_converters.go b/pkg/api/jetton_converters.go index 327419bb..ea975446 100644 --- a/pkg/api/jetton_converters.go +++ b/pkg/api/jetton_converters.go @@ -2,8 +2,10 @@ package api import ( "context" + "encoding/json" "errors" "fmt" + "github.com/tonkeeper/tongo/abi" "github.com/tonkeeper/tongo/tlb" "net/http" "strings" @@ -66,8 +68,7 @@ func (h *Handler) convertJettonHistory(ctx context.Context, account ton.AccountI Timestamp: op.TraceID.UTime, IsScam: false, Lt: int64(op.TraceID.Lt), - //InProgress: trace.InProgress(), // TODO: always false? - //Extra: result.Extra(account), // TODO: extra? + Extra: 0, } } @@ -75,25 +76,30 @@ func (h *Handler) convertJettonHistory(ctx context.Context, account ton.AccountI switch op.Operation { case core.TransferJettonOperation: transferAction := bath.JettonTransferAction{ - //Comment: *string, - //EncryptedComment: *EncryptedComment, Jetton: op.JettonMaster, Recipient: op.Destination, Sender: op.Source, - //RecipientsWallet: tongo.AccountID, - //SendersWallet: tongo.AccountID, - Amount: tlb.VarUInteger16(*op.Amount.BigInt()), - //Refund: *Refund, - //isWrappedTon: bool, + Amount: tlb.VarUInteger16(*op.Amount.BigInt()), } action.Type = "JettonTransfer" action.JettonTransfer = &transferAction + var payload abi.JettonPayload + err := json.Unmarshal([]byte(op.ForwardPayload), &payload) + if err != nil { + break + } + switch p := payload.Value.(type) { + case abi.TextCommentJettonPayload: + comment := string(p.Text) + action.JettonTransfer.Comment = &comment + case abi.EncryptedTextCommentJettonPayload: + action.JettonTransfer.EncryptedComment = &bath.EncryptedComment{EncryptionType: "simple", CipherText: p.CipherText} + } case core.MintJettonOperation: mintAction := bath.JettonMintAction{ Jetton: op.JettonMaster, Recipient: *op.Destination, - //RecipientsWallet: tongo.AccountID, - Amount: tlb.VarUInteger16(*op.Amount.BigInt()), + Amount: tlb.VarUInteger16(*op.Amount.BigInt()), } action.Type = "JettonMint" action.JettonMint = &mintAction @@ -101,7 +107,6 @@ func (h *Handler) convertJettonHistory(ctx context.Context, account ton.AccountI burnAction := bath.JettonBurnAction{ Jetton: op.JettonMaster, Sender: *op.Source, - //SendersWallet: tongo.AccountID, Amount: tlb.VarUInteger16(*op.Amount.BigInt()), } action.Type = "JettonTransfer" @@ -114,18 +119,18 @@ func (h *Handler) convertJettonHistory(ctx context.Context, account ton.AccountI return nil, 0, err } event.Actions = append(event.Actions, convertedAction) + if op.Lt > lastLT { + lastLT = op.Lt + } res[op.TraceID] = event } - for id, event := range res { - // event.IsScam = h.spamFilter.CheckActions(event.Actions, &account, trace.Account) TODO: trace.Account? we do not know initiator + for _, event := range res { + event.IsScam = h.spamFilter.CheckActions(event.Actions, &account, nil) if len(event.Actions) == 0 { continue } events = append(events, event) - if id.Lt > lastLT { - lastLT = id.Lt - } } return events, int64(lastLT), nil diff --git a/pkg/api/nft_converters.go b/pkg/api/nft_converters.go index 7861fd81..ffa410db 100644 --- a/pkg/api/nft_converters.go +++ b/pkg/api/nft_converters.go @@ -163,7 +163,7 @@ func (h *Handler) convertNftHistory(ctx context.Context, account tongo.AccountID } event.Actions = append(event.Actions, convertedAction) } - event.IsScam = h.spamFilter.CheckActions(event.Actions, &account, trace.Account) + event.IsScam = h.spamFilter.CheckActions(event.Actions, &account, &trace.Account) if len(event.Actions) > 0 { events = append(events, event) lastLT = trace.Lt diff --git a/pkg/core/jetton.go b/pkg/core/jetton.go index 0c513d5c..d3d243fd 100644 --- a/pkg/core/jetton.go +++ b/pkg/core/jetton.go @@ -48,12 +48,11 @@ const ( ) type JettonOperation struct { - Operation JettonOperationType - Source *tongo.AccountID - Destination *tongo.AccountID - JettonMaster tongo.AccountID - TraceID TraceID - //TxID TxID + Operation JettonOperationType + Source *tongo.AccountID + Destination *tongo.AccountID + JettonMaster tongo.AccountID + TraceID TraceID DestEndBalance decimal.Decimal Amount decimal.Decimal QueryID uint64 diff --git a/pkg/litestorage/jetton.go b/pkg/litestorage/jetton.go index edcb950d..8226db2a 100644 --- a/pkg/litestorage/jetton.go +++ b/pkg/litestorage/jetton.go @@ -117,11 +117,11 @@ func (s *LiteStorage) GetJettonMasterData(ctx context.Context, master tongo.Acco return jettonMaster, nil } -func (s *LiteStorage) GetAccountJettonsHistory(ctx context.Context, address tongo.AccountID, limit int, beforeLT, startTime, endTime *int64) ([]tongo.Bits256, error) { +func (s *LiteStorage) GetAccountJettonsHistory(ctx context.Context, address tongo.AccountID, limit int, beforeLT, startTime, endTime *int64) ([]core.JettonOperation, error) { return nil, nil } -func (s *LiteStorage) GetAccountJettonHistoryByID(ctx context.Context, address, jettonMaster tongo.AccountID, limit int, beforeLT, startTime, endTime *int64) ([]tongo.Bits256, error) { +func (s *LiteStorage) GetAccountJettonHistoryByID(ctx context.Context, address, jettonMaster tongo.AccountID, limit int, beforeLT, startTime, endTime *int64) ([]core.JettonOperation, error) { return nil, nil } diff --git a/pkg/spam/spam.go b/pkg/spam/spam.go index 188cc833..945f5cc9 100644 --- a/pkg/spam/spam.go +++ b/pkg/spam/spam.go @@ -18,7 +18,7 @@ func NewSpamFilter() *Filter { } } -func (f Filter) CheckActions(actions []oas.Action, viewer *ton.AccountID, initiator ton.AccountID) bool { +func (f Filter) CheckActions(actions []oas.Action, viewer *ton.AccountID, initiator *ton.AccountID) bool { var comment string for _, action := range actions { switch { From 270ddbbfcbf636f5735f7f86c8c1d92e790188e8 Mon Sep 17 00:00:00 2001 From: Alexey Kostenko Date: Fri, 6 Dec 2024 00:47:21 +0300 Subject: [PATCH 3/3] ordering fix --- pkg/api/interfaces.go | 4 +- pkg/api/jetton_converters.go | 127 +++++++++++++++++------------------ pkg/litestorage/jetton.go | 4 +- 3 files changed, 67 insertions(+), 68 deletions(-) diff --git a/pkg/api/interfaces.go b/pkg/api/interfaces.go index 879b1e5d..28be8463 100644 --- a/pkg/api/interfaces.go +++ b/pkg/api/interfaces.go @@ -75,8 +75,8 @@ type storage interface { GetJettonHolders(ctx context.Context, jettonMaster tongo.AccountID, limit, offset int) ([]core.JettonHolder, error) GetJettonMasterMetadata(ctx context.Context, master tongo.AccountID) (tongo.JettonMetadata, error) GetJettonMasterData(ctx context.Context, master tongo.AccountID) (core.JettonMaster, error) - GetAccountJettonsHistory(ctx context.Context, address tongo.AccountID, limit int, beforeLT, startTime, endTime *int64) ([]core.JettonOperation, error) - GetAccountJettonHistoryByID(ctx context.Context, address, jettonMaster tongo.AccountID, limit int, beforeLT, startTime, endTime *int64) ([]core.JettonOperation, error) + GetAccountJettonsHistory(ctx context.Context, address tongo.AccountID, limit int, beforeLT, startTime, endTime *int64) (map[core.TraceID][]core.JettonOperation, error) + GetAccountJettonHistoryByID(ctx context.Context, address, jettonMaster tongo.AccountID, limit int, beforeLT, startTime, endTime *int64) (map[core.TraceID][]core.JettonOperation, error) GetJettonTransferPayload(ctx context.Context, accountID, jettonMaster ton.AccountID) (*core.JettonTransferPayload, error) GetAllAuctions(ctx context.Context) ([]core.Auction, error) diff --git a/pkg/api/jetton_converters.go b/pkg/api/jetton_converters.go index ea975446..916cff62 100644 --- a/pkg/api/jetton_converters.go +++ b/pkg/api/jetton_converters.go @@ -8,6 +8,7 @@ import ( "github.com/tonkeeper/tongo/abi" "github.com/tonkeeper/tongo/tlb" "net/http" + "sort" "strings" "github.com/tonkeeper/opentonapi/pkg/bath" @@ -54,85 +55,83 @@ func jettonMetadata(account ton.AccountID, meta NormalizedMetadata) oas.JettonMe return metadata } -func (h *Handler) convertJettonHistory(ctx context.Context, account ton.AccountID, master *ton.AccountID, history []core.JettonOperation, acceptLanguage oas.OptString) ([]oas.AccountEvent, int64, error) { +func (h *Handler) convertJettonHistory(ctx context.Context, account ton.AccountID, master *ton.AccountID, history map[core.TraceID][]core.JettonOperation, acceptLanguage oas.OptString) ([]oas.AccountEvent, int64, error) { var lastLT uint64 var events []oas.AccountEvent - res := make(map[core.TraceID]oas.AccountEvent) - for _, op := range history { - event, ok := res[op.TraceID] - if !ok { - event = oas.AccountEvent{ - EventID: op.TraceID.Hash.Hex(), - Account: convertAccountAddress(account, h.addressBook), - Timestamp: op.TraceID.UTime, - IsScam: false, - Lt: int64(op.TraceID.Lt), - Extra: 0, - } + for id, ops := range history { + event := oas.AccountEvent{ + EventID: id.Hash.Hex(), + Account: convertAccountAddress(account, h.addressBook), + Timestamp: id.UTime, // TODO: or first/last op Utime + IsScam: false, + Lt: int64(id.Lt), // TODO: or first/last op Lt + Extra: 0, } - - var action bath.Action - switch op.Operation { - case core.TransferJettonOperation: - transferAction := bath.JettonTransferAction{ - Jetton: op.JettonMaster, - Recipient: op.Destination, - Sender: op.Source, - Amount: tlb.VarUInteger16(*op.Amount.BigInt()), + for _, op := range ops { + var action bath.Action + switch op.Operation { + case core.TransferJettonOperation: + transferAction := bath.JettonTransferAction{ + Jetton: op.JettonMaster, + Recipient: op.Destination, + Sender: op.Source, + Amount: tlb.VarUInteger16(*op.Amount.BigInt()), + } + action.Type = "JettonTransfer" + action.JettonTransfer = &transferAction + var payload abi.JettonPayload + err := json.Unmarshal([]byte(op.ForwardPayload), &payload) + if err != nil { + break + } + switch p := payload.Value.(type) { + case abi.TextCommentJettonPayload: + comment := string(p.Text) + action.JettonTransfer.Comment = &comment + case abi.EncryptedTextCommentJettonPayload: + action.JettonTransfer.EncryptedComment = &bath.EncryptedComment{EncryptionType: "simple", CipherText: p.CipherText} + } + case core.MintJettonOperation: + mintAction := bath.JettonMintAction{ + Jetton: op.JettonMaster, + Recipient: *op.Destination, + Amount: tlb.VarUInteger16(*op.Amount.BigInt()), + } + action.Type = "JettonMint" + action.JettonMint = &mintAction + case core.BurnJettonOperation: + burnAction := bath.JettonBurnAction{ + Jetton: op.JettonMaster, + Sender: *op.Source, + Amount: tlb.VarUInteger16(*op.Amount.BigInt()), + } + action.Type = "JettonTransfer" + action.JettonBurn = &burnAction + default: + continue } - action.Type = "JettonTransfer" - action.JettonTransfer = &transferAction - var payload abi.JettonPayload - err := json.Unmarshal([]byte(op.ForwardPayload), &payload) + convertedAction, err := h.convertAction(ctx, &account, action, acceptLanguage) if err != nil { - break - } - switch p := payload.Value.(type) { - case abi.TextCommentJettonPayload: - comment := string(p.Text) - action.JettonTransfer.Comment = &comment - case abi.EncryptedTextCommentJettonPayload: - action.JettonTransfer.EncryptedComment = &bath.EncryptedComment{EncryptionType: "simple", CipherText: p.CipherText} + return nil, 0, err } - case core.MintJettonOperation: - mintAction := bath.JettonMintAction{ - Jetton: op.JettonMaster, - Recipient: *op.Destination, - Amount: tlb.VarUInteger16(*op.Amount.BigInt()), + event.Actions = append(event.Actions, convertedAction) + if lastLT == 0 { + lastLT = op.Lt } - action.Type = "JettonMint" - action.JettonMint = &mintAction - case core.BurnJettonOperation: - burnAction := bath.JettonBurnAction{ - Jetton: op.JettonMaster, - Sender: *op.Source, - Amount: tlb.VarUInteger16(*op.Amount.BigInt()), + if op.Lt < lastLT { + lastLT = op.Lt } - action.Type = "JettonTransfer" - action.JettonBurn = &burnAction - default: - continue - } - convertedAction, err := h.convertAction(ctx, &account, action, acceptLanguage) - if err != nil { - return nil, 0, err } - event.Actions = append(event.Actions, convertedAction) - if op.Lt > lastLT { - lastLT = op.Lt - } - res[op.TraceID] = event - } - - for _, event := range res { - event.IsScam = h.spamFilter.CheckActions(event.Actions, &account, nil) if len(event.Actions) == 0 { continue } + event.IsScam = h.spamFilter.CheckActions(event.Actions, &account, nil) events = append(events, event) } - + sort.Slice(events, func(i, j int) bool { + return events[i].Lt > events[j].Lt + }) return events, int64(lastLT), nil } diff --git a/pkg/litestorage/jetton.go b/pkg/litestorage/jetton.go index 8226db2a..91f7537a 100644 --- a/pkg/litestorage/jetton.go +++ b/pkg/litestorage/jetton.go @@ -117,11 +117,11 @@ func (s *LiteStorage) GetJettonMasterData(ctx context.Context, master tongo.Acco return jettonMaster, nil } -func (s *LiteStorage) GetAccountJettonsHistory(ctx context.Context, address tongo.AccountID, limit int, beforeLT, startTime, endTime *int64) ([]core.JettonOperation, error) { +func (s *LiteStorage) GetAccountJettonsHistory(ctx context.Context, address tongo.AccountID, limit int, beforeLT, startTime, endTime *int64) (map[core.TraceID][]core.JettonOperation, error) { return nil, nil } -func (s *LiteStorage) GetAccountJettonHistoryByID(ctx context.Context, address, jettonMaster tongo.AccountID, limit int, beforeLT, startTime, endTime *int64) ([]core.JettonOperation, error) { +func (s *LiteStorage) GetAccountJettonHistoryByID(ctx context.Context, address, jettonMaster tongo.AccountID, limit int, beforeLT, startTime, endTime *int64) (map[core.TraceID][]core.JettonOperation, error) { return nil, nil }