Skip to content

Commit 65243e0

Browse files
committed
Update Fee Event Filter Implementation to Remove 4 Fees and Add Defensive Checks
1 parent e1d5d78 commit 65243e0

9 files changed

Lines changed: 147 additions & 73 deletions

File tree

internal/transactions/build.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,9 +133,10 @@ func build(
133133
}
134134

135135
return &transactionResult{
136+
result: nil,
136137
tx: tx.FlowTransaction(),
138+
chainID: "",
137139
include: []string{"code", "payload", "signatures"},
138-
network: flow.Network().Name,
139140
}, nil
140141
}
141142

internal/transactions/decode.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,9 @@ func decode(
6767
}
6868

6969
return &transactionResult{
70+
result: nil,
7071
tx: tx.FlowTransaction(),
72+
chainID: "",
7173
include: decodeFlags.Include,
72-
network: "", // decode doesn't have network context
7374
}, nil
7475
}

internal/transactions/get-system.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import (
2929
"github.com/onflow/flowkit/v2/output"
3030

3131
"github.com/onflow/flow-cli/internal/command"
32+
"github.com/onflow/flow-cli/internal/util"
3233
)
3334

3435
type flagsGetSystem struct {
@@ -80,11 +81,16 @@ func getSystemTransaction(
8081
return nil, err
8182
}
8283

84+
chainID, err := util.GetChainIDFromHost(flow.Network().Host)
85+
if err != nil {
86+
return nil, err
87+
}
88+
8389
return &transactionResult{
8490
result: result,
8591
tx: tx,
92+
chainID: chainID,
8693
include: getSystemFlags.Include,
8794
exclude: getSystemFlags.Exclude,
88-
network: flow.Network().Name,
8995
}, nil
9096
}

internal/transactions/get.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import (
2929
"github.com/onflow/flowkit/v2/output"
3030

3131
"github.com/onflow/flow-cli/internal/command"
32+
"github.com/onflow/flow-cli/internal/util"
3233
)
3334

3435
type flagsGet struct {
@@ -65,11 +66,16 @@ func get(
6566
return nil, err
6667
}
6768

69+
chainID, err := util.GetChainIDFromHost(flow.Network().Host)
70+
if err != nil {
71+
return nil, err
72+
}
73+
6874
return &transactionResult{
6975
result: result,
7076
tx: tx,
77+
chainID: chainID,
7178
include: getFlags.Include,
7279
exclude: getFlags.Exclude,
73-
network: flow.Network().Name,
7480
}, nil
7581
}

internal/transactions/send-signed.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import (
3232
"github.com/onflow/flowkit/v2/output"
3333

3434
"github.com/onflow/flow-cli/internal/command"
35+
"github.com/onflow/flow-cli/internal/util"
3536
)
3637

3738
type flagsSendSigned struct {
@@ -83,11 +84,16 @@ func sendSigned(
8384
return nil, err
8485
}
8586

87+
chainID, err := util.GetChainIDFromHost(flow.Network().Host)
88+
if err != nil {
89+
return nil, err
90+
}
91+
8692
return &transactionResult{
8793
result: result,
8894
tx: sentTx,
95+
chainID: chainID,
8996
include: sendSignedFlags.Include,
9097
exclude: sendSignedFlags.Exclude,
91-
network: flow.Network().Name,
9298
}, nil
9399
}

internal/transactions/send.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import (
3232
"github.com/onflow/flowkit/v2/transactions"
3333

3434
"github.com/onflow/flow-cli/internal/command"
35+
"github.com/onflow/flow-cli/internal/util"
3536
)
3637

3738
type Flags struct {
@@ -160,11 +161,16 @@ func SendTransaction(code []byte, args []string, location string, flow flowkit.S
160161
return nil, err
161162
}
162163

164+
chainID, err := util.GetChainIDFromHost(flow.Network().Host)
165+
if err != nil {
166+
return nil, err
167+
}
168+
163169
return &transactionResult{
164170
result: txResult,
165171
tx: tx,
172+
chainID: chainID,
166173
include: sendFlags.Include,
167174
exclude: sendFlags.Exclude,
168-
network: flow.Network().Name,
169175
}, nil
170176
}

internal/transactions/sign.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import (
2828
"sort"
2929

3030
"github.com/onflow/flow-cli/internal/prompt"
31+
"github.com/onflow/flow-cli/internal/util"
3132

3233
"github.com/onflow/flowkit/v2/transactions"
3334

@@ -138,10 +139,16 @@ func sign(
138139
fmt.Printf("%s Signed RLP Posted successfully\n", output.SuccessEmoji())
139140
}
140141

142+
chainID, err := util.GetChainIDFromHost(flow.Network().Host)
143+
if err != nil {
144+
return nil, err
145+
}
146+
141147
return &transactionResult{
148+
result: nil,
142149
tx: signed.FlowTransaction(),
150+
chainID: chainID,
143151
include: signFlags.Include,
144-
network: flow.Network().Name,
145152
}, nil
146153
}
147154

internal/transactions/transactions.go

Lines changed: 57 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ import (
2525
"strings"
2626

2727
"github.com/onflow/flow-go-sdk"
28+
"github.com/onflow/flow-go/fvm/systemcontracts"
29+
flowGo "github.com/onflow/flow-go/model/flow"
2830
"github.com/spf13/cobra"
2931

3032
"github.com/onflow/flowkit/v2/output"
@@ -60,37 +62,26 @@ type transactionResult struct {
6062
tx *flow.Transaction
6163
include []string
6264
exclude []string
63-
network string
64-
}
65-
66-
func NewTransactionResult(tx *flow.Transaction, result *flow.TransactionResult) *transactionResult {
67-
return &transactionResult{
68-
result: result,
69-
tx: tx,
70-
network: "", // Default to empty, should be set by caller
71-
}
65+
chainID flowGo.ChainID
7266
}
7367

7468
// getBlockExplorerLink returns the block explorer link for the transaction if it's on mainnet or testnet
7569
func (r *transactionResult) getBlockExplorerLink() string {
76-
if r.network == "" {
77-
return ""
78-
}
79-
80-
// Only show block explorer links for mainnet and testnet
81-
if r.network != "mainnet" && r.network != "testnet" {
70+
if r.chainID == "" {
8271
return ""
8372
}
8473

8574
txID := r.tx.ID().String()
8675

87-
if r.network == "mainnet" {
76+
// Only show block explorer links for mainnet and testnet
77+
switch r.chainID {
78+
case flowGo.Mainnet:
8879
return fmt.Sprintf("https://www.flowscan.io/tx/%s", txID)
89-
} else if r.network == "testnet" {
80+
case flowGo.Testnet:
9081
return fmt.Sprintf("https://testnet.flowscan.io/tx/%s", txID)
82+
default:
83+
return ""
9184
}
92-
93-
return ""
9485
}
9586

9687
func (r *transactionResult) JSON() any {
@@ -109,8 +100,9 @@ func (r *transactionResult) JSON() any {
109100
result["block_height"] = r.result.BlockHeight
110101
result["status"] = r.result.Status.String()
111102

112-
txEvents := make([]any, 0, len(r.result.Events))
113-
for _, event := range r.result.Events {
103+
events := r.getDisplayEvents()
104+
txEvents := make([]any, 0, len(events))
105+
for _, event := range events {
114106
txEvents = append(txEvents, map[string]any{
115107
"index": event.EventIndex,
116108
"type": event.Type,
@@ -129,11 +121,48 @@ func (r *transactionResult) JSON() any {
129121
return result
130122
}
131123

124+
func (r *transactionResult) getDisplayEvents() []flow.Event {
125+
if r.result == nil || command.ContainsFlag(r.exclude, "events") {
126+
return nil
127+
}
128+
129+
events := r.result.Events
130+
if !command.ContainsFlag(r.include, "fee-events") {
131+
events = filterFeeEvents(events, r.chainID)
132+
}
133+
return events
134+
}
135+
136+
func filterFeeEvents(events []flow.Event, chainID flowGo.ChainID) []flow.Event {
137+
const feeEventsCountAppended = 4
138+
139+
if len(events) == 0 || chainID == "" {
140+
return events
141+
}
142+
143+
// Get the FlowFees system contract address for this chain
144+
systemContracts := systemcontracts.SystemContractsForChain(chainID)
145+
flowFeesAddress := systemContracts.FlowFees.Address
146+
147+
// Build the expected event type: A.<address>.FlowFees.FeesDeducted
148+
expectedEventType := fmt.Sprintf("A.%s.FlowFees.FeesDeducted", flowFeesAddress.Hex())
149+
150+
// Fee events are always at the end, so just check the last event
151+
lastEvent := events[len(events)-1]
152+
if strings.HasPrefix(lastEvent.Type, expectedEventType) {
153+
cutIndex := len(events) - feeEventsCountAppended
154+
if cutIndex < 0 {
155+
cutIndex = 0
156+
}
157+
return events[:cutIndex]
158+
}
159+
160+
return events
161+
}
162+
132163
func (r *transactionResult) String() string {
133164
var b bytes.Buffer
134165
writer := util.CreateTabWriter(&b)
135-
const feeEventsCountAppended = 5
136-
const feeDeductedEvent = "FeesDeducted"
137166

138167
if r.result != nil {
139168
_, _ = fmt.Fprintf(writer, "%s\t%s\n", branding.GrayStyle.Render("Block ID"), branding.PurpleStyle.Render(r.result.BlockID.String()))
@@ -199,19 +228,10 @@ func (r *transactionResult) String() string {
199228
_, _ = fmt.Fprintf(writer, "\n%s", branding.GrayStyle.Render("Signatures (minimized, use --include signatures)"))
200229
}
201230

202-
if r.result != nil && !command.ContainsFlag(r.exclude, "events") {
231+
displayEvents := r.getDisplayEvents()
232+
if displayEvents != nil {
203233
e := events.EventResult{
204-
Events: r.result.Events,
205-
}
206-
207-
if r.result != nil && e.Events != nil && !command.ContainsFlag(r.include, "fee-events") {
208-
for _, event := range e.Events {
209-
if strings.Contains(event.Type, feeDeductedEvent) {
210-
// if fee event are present remove them
211-
e.Events = e.Events[:len(e.Events)-feeEventsCountAppended]
212-
break
213-
}
214-
}
234+
Events: displayEvents,
215235
}
216236

217237
eventsOutput := e.String()
@@ -263,7 +283,8 @@ func (r *transactionResult) Oneliner() string {
263283
r.tx.ID(), r.tx.Payer, r.tx.Authorizers)
264284

265285
if r.result != nil {
266-
result += fmt.Sprintf(", Status: %s, Events: %s", r.result.Status, r.result.Events)
286+
displayEvents := r.getDisplayEvents()
287+
result += fmt.Sprintf(", Status: %s, Events: %s", r.result.Status, displayEvents)
267288
}
268289

269290
return result

0 commit comments

Comments
 (0)