Skip to content

Commit 00d7408

Browse files
committedMay 12, 2023
bath.FindActions to return action list along with value flow
1 parent bbf3215 commit 00d7408

24 files changed

+1527
-261
lines changed
 

‎.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
11
cover.out
2+
*.output.json
3+
scripts/

‎api/openapi.yml

+54
Original file line numberDiff line numberDiff line change
@@ -2176,6 +2176,51 @@ components:
21762176
origin:
21772177
type: string
21782178
example: "0:da6b1b6663a0e4d18cc8574ccd9db5296e367dd9324706f3bbd9eb1cd2caf0bf"
2179+
ValueFlow:
2180+
type: object
2181+
required:
2182+
- account
2183+
- ton
2184+
- fees
2185+
properties:
2186+
account:
2187+
$ref: '#/components/schemas/AccountAddress'
2188+
ton:
2189+
type: integer
2190+
format: int64
2191+
example: 80
2192+
fees:
2193+
type: integer
2194+
format: int64
2195+
example: 10
2196+
nfts:
2197+
type: array
2198+
items:
2199+
type: object
2200+
required:
2201+
- account
2202+
- quantity
2203+
properties:
2204+
account:
2205+
$ref: '#/components/schemas/AccountAddress'
2206+
quantity:
2207+
type: integer
2208+
format: int64
2209+
example: 10
2210+
jettons:
2211+
type: array
2212+
items:
2213+
type: object
2214+
required:
2215+
- account
2216+
- quantity
2217+
properties:
2218+
account:
2219+
$ref: '#/components/schemas/AccountAddress'
2220+
quantity:
2221+
type: integer
2222+
format: int64
2223+
example: 10
21792224

21802225
Action:
21812226
type: object
@@ -2456,6 +2501,7 @@ components:
24562501
- timestamp
24572502
- actions
24582503
- fee
2504+
- value_flow
24592505
- account
24602506
- is_scam
24612507
- lt
@@ -2476,6 +2522,9 @@ components:
24762522
$ref: '#/components/schemas/Action'
24772523
fee:
24782524
$ref: '#/components/schemas/Fee'
2525+
deprecated: true
2526+
value_flow:
2527+
$ref: '#/components/schemas/ValueFlow'
24792528
is_scam:
24802529
type: boolean
24812530
description: scam
@@ -2744,6 +2793,7 @@ components:
27442793
- timestamp
27452794
- actions
27462795
- fees
2796+
- value_flow
27472797
- is_scam
27482798
- lt
27492799
- in_progress
@@ -2763,6 +2813,10 @@ components:
27632813
type: array
27642814
items:
27652815
$ref: '#/components/schemas/Fee'
2816+
value_flow:
2817+
type: array
2818+
items:
2819+
$ref: '#/components/schemas/ValueFlow'
27662820
is_scam:
27672821
type: boolean
27682822
description: scam

‎go.sum

-4
Original file line numberDiff line numberDiff line change
@@ -263,10 +263,6 @@ github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKs
263263
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
264264
github.com/tonkeeper/scam_backoffice_rules v0.0.0-20230413094040-a66ab71fb269 h1:roJPVpmFnUZX6YCUqzoD5+0+Z2ruuuXmxWKS+IH3O2s=
265265
github.com/tonkeeper/scam_backoffice_rules v0.0.0-20230413094040-a66ab71fb269/go.mod h1:VGp8QednbWkKHcpQVlWyO0XSqAA0cR6d9wEdrDmHbbA=
266-
github.com/tonkeeper/tongo v1.0.14-0.20230425143018-42fbbbfed2a3 h1:7pbY+FHPuUXt+s/lqMiDFL6G7FrSEqZK+73gZvDfd4I=
267-
github.com/tonkeeper/tongo v1.0.14-0.20230425143018-42fbbbfed2a3/go.mod h1:Nn/5t5MGQHBUuEm56O135FIYwk9WpPgDITjWPk+fPGc=
268-
github.com/tonkeeper/tongo v1.0.15-0.20230501203905-82920df08b2f h1:0pqgkGrgosH8PX7+RTz2YfnEwAymUJ9VHlhb2VkIaQE=
269-
github.com/tonkeeper/tongo v1.0.15-0.20230501203905-82920df08b2f/go.mod h1:LdOBjpUz6vLp1EdX3E0XLNks9YI5XMSqaQahfOMrBEY=
270266
github.com/tonkeeper/tongo v1.0.15-0.20230508095306-c4c3b7a0ae50 h1:WG6lvONwtWRb4HlJqgjmf2eJXKRoi4bYJWQdgW53hoo=
271267
github.com/tonkeeper/tongo v1.0.15-0.20230508095306-c4c3b7a0ae50/go.mod h1:LdOBjpUz6vLp1EdX3E0XLNks9YI5XMSqaQahfOMrBEY=
272268
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=

‎pkg/api/event_converters.go

+19-15
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"github.com/tonkeeper/opentonapi/pkg/core"
1010
"github.com/tonkeeper/opentonapi/pkg/oas"
1111
rules "github.com/tonkeeper/scam_backoffice_rules"
12+
"github.com/tonkeeper/tongo"
1213
)
1314

1415
func convertTrace(t core.Trace, book addressBook) oas.Trace {
@@ -44,13 +45,6 @@ func (h Handler) convertAction(ctx context.Context, a bath.Action) (oas.Action,
4445
Recipient: convertAccountAddress(a.TonTransfer.Recipient, h.addressBook),
4546
Sender: convertAccountAddress(a.TonTransfer.Sender, h.addressBook),
4647
})
47-
if a.TonTransfer.Refund != nil {
48-
action.TonTransfer.Value.Refund.SetTo(oas.Refund{
49-
Type: oas.RefundType(a.TonTransfer.Refund.Type),
50-
Origin: a.TonTransfer.Refund.Origin,
51-
})
52-
53-
}
5448
case bath.NftItemTransfer:
5549
action.NftItemTransfer.SetTo(oas.NftItemTransferAction{
5650
Nft: a.NftItemTransfer.Nft.ToRaw(),
@@ -108,13 +102,23 @@ func (h Handler) convertAction(ctx context.Context, a bath.Action) (oas.Action,
108102
return action, spamDetected
109103
}
110104

111-
func convertFees(fee bath.Fee, book addressBook) oas.Fee {
112-
return oas.Fee{
113-
Account: convertAccountAddress(fee.WhoPay, book),
114-
Total: 0,
115-
Gas: fee.Compute,
116-
Rent: fee.Storage,
117-
Deposit: fee.Deposit,
118-
Refund: 0,
105+
func convertAccountValueFlow(accountID tongo.AccountID, flow *bath.AccountValueFlow, book addressBook) oas.ValueFlow {
106+
valueFlow := oas.ValueFlow{
107+
Account: convertAccountAddress(accountID, book),
108+
Ton: flow.Ton,
109+
Fees: flow.Fees,
110+
}
111+
for nftItem, quantity := range flow.Nfts {
112+
valueFlow.Nfts = append(valueFlow.Nfts, oas.ValueFlowNftsItem{
113+
Account: convertAccountAddress(nftItem, book),
114+
Quantity: quantity,
115+
})
116+
}
117+
for jettonItem, quantity := range flow.Jettons {
118+
valueFlow.Jettons = append(valueFlow.Jettons, oas.ValueFlowJettonsItem{
119+
Account: convertAccountAddress(jettonItem, book),
120+
Quantity: quantity.Int64(),
121+
})
119122
}
123+
return valueFlow
120124
}

‎pkg/api/event_handlers.go

+16-17
Original file line numberDiff line numberDiff line change
@@ -51,25 +51,26 @@ func (h Handler) GetEvent(ctx context.Context, params oas.GetEventParams) (oas.G
5151
if err != nil {
5252
return &oas.InternalError{Error: err.Error()}, nil
5353
}
54-
b := bath.FromTrace(trace)
55-
bath.MergeAllBubbles(b, bath.DefaultStraws)
56-
actions, fees := bath.CollectActions(b, nil)
54+
result, err := bath.FindActions(trace)
55+
if err != nil {
56+
return nil, err
57+
}
5758
event := oas.Event{
5859
EventID: trace.Hash.Hex(),
5960
Timestamp: trace.Utime,
60-
Actions: make([]oas.Action, len(actions)),
61-
Fees: make([]oas.Fee, len(fees)),
61+
Actions: make([]oas.Action, len(result.Actions)),
62+
ValueFlow: make([]oas.ValueFlow, 0, len(result.ValueFlow.Accounts)),
6263
IsScam: false,
6364
Lt: int64(trace.Lt),
6465
InProgress: trace.InProgress(),
6566
}
66-
for i, a := range actions {
67+
for i, a := range result.Actions {
6768
convertedAction, spamDetected := h.convertAction(ctx, a)
6869
event.IsScam = event.IsScam || spamDetected
6970
event.Actions[i] = convertedAction
7071
}
71-
for i, f := range fees {
72-
event.Fees[i] = convertFees(f, h.addressBook)
72+
for accountID, flow := range result.ValueFlow.Accounts {
73+
event.ValueFlow = append(event.ValueFlow, convertAccountValueFlow(accountID, flow, h.addressBook))
7374
}
7475
return &event, nil
7576
}
@@ -90,9 +91,10 @@ func (h Handler) GetEventsByAccount(ctx context.Context, params oas.GetEventsByA
9091
if err != nil {
9192
return &oas.InternalError{Error: err.Error()}, nil
9293
}
93-
b := bath.FromTrace(trace)
94-
bath.MergeAllBubbles(b, bath.DefaultStraws)
95-
actions, fees := bath.CollectActions(b, &account)
94+
result, err := bath.FindActions(trace)
95+
if err != nil {
96+
return &oas.InternalError{Error: err.Error()}, nil
97+
}
9698
e := oas.AccountEvent{
9799
EventID: trace.Hash.Hex(),
98100
Account: convertAccountAddress(account, h.addressBook),
@@ -102,13 +104,10 @@ func (h Handler) GetEventsByAccount(ctx context.Context, params oas.GetEventsByA
102104
Lt: int64(trace.Lt),
103105
InProgress: trace.InProgress(),
104106
}
105-
for _, f := range fees {
106-
if f.WhoPay == account {
107-
e.Fee = convertFees(f, h.addressBook)
108-
break
109-
}
107+
if flow, ok := result.ValueFlow.Accounts[account]; ok {
108+
e.ValueFlow = convertAccountValueFlow(account, flow, h.addressBook)
110109
}
111-
for _, a := range actions {
110+
for _, a := range result.Actions {
112111
convertedAction, spamDetected := h.convertAction(ctx, a)
113112
if !e.IsScam && spamDetected {
114113
e.IsScam = true

‎pkg/api/jetton_converters.go

+7-9
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,10 @@ func (h Handler) convertJettonHistory(ctx context.Context, account tongo.Account
6666
if err != nil {
6767
return nil, 0, err
6868
}
69-
bubble := bath.FromTrace(trace)
70-
bath.MergeAllBubbles(bubble, []bath.Straw{bath.FindJettonTransfer})
71-
actions, fees := bath.CollectActions(bubble, &account)
69+
result, err := bath.FindActions(trace, bath.WithStraws([]bath.Straw{bath.FindJettonTransfer}))
70+
if err != nil {
71+
return nil, 0, err
72+
}
7273
event := oas.AccountEvent{
7374
EventID: trace.Hash.Hex(),
7475
Account: convertAccountAddress(account, h.addressBook),
@@ -78,13 +79,10 @@ func (h Handler) convertJettonHistory(ctx context.Context, account tongo.Account
7879
Lt: int64(trace.Lt),
7980
InProgress: trace.InProgress(),
8081
}
81-
for _, fee := range fees {
82-
if fee.WhoPay == account {
83-
event.Fee = convertFees(fee, h.addressBook)
84-
break
85-
}
82+
if flow, ok := result.ValueFlow.Accounts[account]; ok {
83+
event.ValueFlow = convertAccountValueFlow(account, flow, h.addressBook)
8684
}
87-
for _, action := range actions {
85+
for _, action := range result.Actions {
8886
convertedAction, spamDetected := h.convertAction(ctx, action)
8987
if !event.IsScam && spamDetected {
9088
event.IsScam = true

‎pkg/bath/action.go ‎pkg/bath/actions.go

+9-33
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@ import (
55
"fmt"
66
"reflect"
77

8-
"github.com/tonkeeper/opentonapi/pkg/core"
98
"github.com/tonkeeper/tongo"
109
"github.com/tonkeeper/tongo/tlb"
11-
"golang.org/x/exp/maps"
1210
"golang.org/x/exp/slices"
11+
12+
"github.com/tonkeeper/opentonapi/pkg/core"
1313
)
1414

1515
const (
@@ -23,22 +23,11 @@ const (
2323
UnSubscription ActionType = "UnSubscribe"
2424
AuctionBid ActionType = "AuctionBid"
2525
AuctionTgInitBid ActionType = "AuctionTgInitBid"
26-
27-
RefundDnsTg RefundType = "DNS.tg"
28-
RefundDnsTon RefundType = "DNS.ton"
29-
RefundGetGems RefundType = "GetGems"
30-
RefundUnknown RefundType = "unknown"
3126
)
3227

3328
type ActionType string
34-
type RefundType string
3529

3630
type (
37-
Refund struct {
38-
Type RefundType
39-
Origin string
40-
}
41-
4231
Action struct {
4332
TonTransfer *TonTransferAction
4433
SmartContractExec *SmartContractAction
@@ -56,7 +45,6 @@ type (
5645
Comment *string
5746
Recipient tongo.AccountID
5847
Sender tongo.AccountID
59-
Refund *Refund
6048
}
6149
SmartContractAction struct {
6250
TonAttached int64
@@ -71,7 +59,6 @@ type (
7159
Recipient *tongo.AccountID
7260
Sender *tongo.AccountID
7361
Nft tongo.AccountID
74-
Refund *Refund
7562
}
7663

7764
JettonTransferAction struct {
@@ -82,7 +69,6 @@ type (
8269
RecipientsWallet tongo.AccountID
8370
SendersWallet tongo.AccountID
8471
Amount tlb.VarUInteger16
85-
Refund *Refund
8672
}
8773

8874
ContractDeployAction struct {
@@ -121,30 +107,20 @@ func (a Action) String() string {
121107
return fmt.Sprintf("%v: %+v", a.Type, string(b))
122108
}
123109

124-
func (f Fee) String() string {
125-
return fmt.Sprintf("%v: %v/%v/%v/%v/%v", f.WhoPay, f.Total(), f.Storage, f.Compute, f.Deposit, f.Refund)
126-
}
127-
128-
func CollectActions(bubble *Bubble, forAccount *tongo.AccountID) ([]Action, []Fee) {
129-
fees := make(map[tongo.AccountID]Fee)
130-
actions := collectActions(bubble, fees, forAccount)
131-
return actions, maps.Values(fees)
132-
}
133-
134-
func collectActions(bubble *Bubble, fees map[tongo.AccountID]Fee, forAccount *tongo.AccountID) []Action {
110+
func collectActionsAndValueFlow(bubble *Bubble, forAccount *tongo.AccountID) ([]Action, *ValueFlow) {
135111
var actions []Action
112+
valueFlow := newValueFlow()
136113
if forAccount == nil || slices.Contains(bubble.Accounts, *forAccount) {
137114
a := bubble.Info.ToAction()
138115
if a != nil {
139116
actions = append(actions, *a)
140117
}
141118
}
142119
for _, c := range bubble.Children {
143-
a := collectActions(c, fees, forAccount)
144-
actions = append(actions, a...)
120+
childActions, childValueFlow := collectActionsAndValueFlow(c, forAccount)
121+
actions = append(actions, childActions...)
122+
valueFlow.Merge(childValueFlow)
145123
}
146-
f := fees[bubble.Fee.WhoPay]
147-
bubble.Fee.Add(f)
148-
fees[bubble.Fee.WhoPay] = bubble.Fee
149-
return actions
124+
valueFlow.Merge(bubble.ValueFlow)
125+
return actions, valueFlow
150126
}

0 commit comments

Comments
 (0)