Skip to content

Commit f5e9cf0

Browse files
committed
Add logic for get command
1 parent 02a84b3 commit f5e9cf0

File tree

1 file changed

+226
-30
lines changed

1 file changed

+226
-30
lines changed

internal/schedule/get.go

Lines changed: 226 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,20 @@
1919
package schedule
2020

2121
import (
22+
"context"
2223
"fmt"
24+
"strconv"
2325

26+
"github.com/onflow/cadence"
27+
flowsdk "github.com/onflow/flow-go-sdk"
2428
"github.com/spf13/cobra"
2529

2630
"github.com/onflow/flowkit/v2"
2731
"github.com/onflow/flowkit/v2/output"
2832

33+
"github.com/onflow/flow-cli/common/branding"
2934
"github.com/onflow/flow-cli/internal/command"
35+
"github.com/onflow/flow-cli/internal/util"
3036
)
3137

3238
type flagsGet struct{}
@@ -65,51 +71,241 @@ func getRun(
6571
return nil, fmt.Errorf("transaction ID is required as an argument")
6672
}
6773

68-
transactionID := args[0]
74+
transactionIDStr := args[0]
6975

70-
logger.Info(fmt.Sprintf("Network: %s", globalFlags.Network))
71-
logger.Info(fmt.Sprintf("Transaction ID: %s", transactionID))
72-
logger.Info("Retrieving scheduled transaction details...")
76+
// Parse transaction ID as UInt64
77+
transactionID, err := strconv.ParseUint(transactionIDStr, 10, 64)
78+
if err != nil {
79+
return nil, fmt.Errorf("invalid transaction ID: %w", err)
80+
}
81+
82+
chainID, err := util.NetworkToChainID(globalFlags.Network)
83+
if err != nil {
84+
return nil, err
85+
}
86+
87+
// Check if network is supported
88+
if chainID == flowsdk.Mainnet {
89+
return nil, fmt.Errorf("transaction scheduling is not yet supported on mainnet")
90+
}
91+
92+
contractAddress, err := getContractAddress(FlowTransactionScheduler, chainID)
93+
if err != nil {
94+
return nil, err
95+
}
96+
97+
networkStr := branding.GrayStyle.Render(globalFlags.Network)
98+
txIDStr := branding.PurpleStyle.Render(transactionIDStr)
99+
100+
logger.Info(fmt.Sprintf("🌐 Network: %s", networkStr))
101+
logger.Info(fmt.Sprintf("🔍 Transaction ID: %s", txIDStr))
102+
logger.Info("")
103+
logger.Info("⏳ Retrieving scheduled transaction details...")
104+
105+
script := fmt.Sprintf(`import FlowTransactionScheduler from %s
106+
107+
access(all) fun main(transactionID: UInt64): FlowTransactionScheduler.TransactionData? {
108+
// Get the transaction data directly from the FlowTransactionScheduler contract
109+
return FlowTransactionScheduler.getTransactionData(id: transactionID)
110+
}`, contractAddress)
111+
112+
value, err := flow.ExecuteScript(
113+
context.Background(),
114+
flowkit.Script{
115+
Code: []byte(script),
116+
Args: []cadence.Value{cadence.NewUInt64(transactionID)},
117+
},
118+
flowkit.LatestScriptQuery,
119+
)
120+
if err != nil {
121+
return nil, fmt.Errorf("failed to execute script: %w", err)
122+
}
123+
124+
txData, err := parseTransactionData(value)
125+
if err != nil {
126+
return nil, fmt.Errorf("failed to parse transaction data: %w", err)
127+
}
128+
129+
if txData == nil {
130+
return nil, fmt.Errorf("scheduled transaction not found")
131+
}
132+
133+
// Log success
134+
logger.Info("")
135+
successIcon := branding.GreenStyle.Render("✅")
136+
successMsg := branding.GreenStyle.Render("Transaction data retrieved successfully")
137+
logger.Info(fmt.Sprintf("%s %s", successIcon, successMsg))
138+
139+
return txData, nil
140+
}
141+
142+
// parseTransactionData parses the cadence.Value returned from the script
143+
func parseTransactionData(value cadence.Value) (*getResult, error) {
144+
// Check if result is nil (optional return)
145+
optional, ok := value.(cadence.Optional)
146+
if !ok {
147+
return nil, fmt.Errorf("expected optional value, got %T", value)
148+
}
149+
150+
if optional.Value == nil {
151+
return nil, nil // Transaction not found
152+
}
153+
154+
structValue, ok := optional.Value.(cadence.Struct)
155+
if !ok {
156+
return nil, fmt.Errorf("expected struct value, got %T", optional.Value)
157+
}
158+
159+
fields := cadence.FieldsMappedByName(structValue)
160+
161+
result := &getResult{}
162+
163+
if id, ok := fields["id"].(cadence.UInt64); ok {
164+
result.id = uint64(id)
165+
}
166+
167+
if priority, ok := fields["priority"].(cadence.Enum); ok {
168+
priorityFields := cadence.FieldsMappedByName(priority)
169+
if rawValue, ok := priorityFields["rawValue"].(cadence.UInt8); ok {
170+
result.priority = uint8(rawValue)
171+
}
172+
}
173+
174+
if effort, ok := fields["executionEffort"].(cadence.UInt64); ok {
175+
result.executionEffort = uint64(effort)
176+
}
177+
178+
if status, ok := fields["status"].(cadence.Enum); ok {
179+
statusFields := cadence.FieldsMappedByName(status)
180+
if rawValue, ok := statusFields["rawValue"].(cadence.UInt8); ok {
181+
result.status = uint8(rawValue)
182+
}
183+
}
73184

74-
// TODO: Implement get logic for scheduled transaction
185+
if fees, ok := fields["fees"].(cadence.UFix64); ok {
186+
result.fees = fees.String()
187+
}
75188

76-
return &getResult{
77-
success: true,
78-
message: "Scheduled transaction details retrieved successfully",
79-
transactionID: transactionID,
80-
status: "Scheduled",
81-
scheduledAt: "2024-01-01T00:00:00Z",
82-
executeAt: "2024-01-01T12:00:00Z",
83-
}, nil
189+
if timestamp, ok := fields["scheduledTimestamp"].(cadence.UFix64); ok {
190+
result.scheduledTimestamp = timestamp.String()
191+
}
192+
193+
if handlerType, ok := fields["handlerTypeIdentifier"].(cadence.String); ok {
194+
result.handlerTypeIdentifier = string(handlerType)
195+
}
196+
197+
if handlerAddr, ok := fields["handlerAddress"].(cadence.Address); ok {
198+
result.handlerAddress = handlerAddr.String()
199+
}
200+
201+
return result, nil
84202
}
85203

86204
type getResult struct {
87-
success bool
88-
message string
89-
transactionID string
90-
status string
91-
scheduledAt string
92-
executeAt string
205+
id uint64
206+
priority uint8
207+
executionEffort uint64
208+
status uint8
209+
fees string
210+
scheduledTimestamp string
211+
handlerTypeIdentifier string
212+
handlerAddress string
93213
}
94214

95215
func (r *getResult) JSON() any {
96216
return map[string]any{
97-
"success": r.success,
98-
"message": r.message,
99-
"transaction_id": r.transactionID,
100-
"status": r.status,
101-
"scheduled_at": r.scheduledAt,
102-
"execute_at": r.executeAt,
217+
"id": r.id,
218+
"priority": r.priority,
219+
"execution_effort": r.executionEffort,
220+
"status": r.status,
221+
"fees": r.fees,
222+
"scheduled_timestamp": r.scheduledTimestamp,
223+
"handler_type_identifier": r.handlerTypeIdentifier,
224+
"handler_address": r.handlerAddress,
103225
}
104226
}
105227

106228
func (r *getResult) String() string {
107-
return fmt.Sprintf(`Transaction ID: %s
108-
Status: %s
109-
Scheduled At: %s
110-
Execute At: %s`, r.transactionID, r.status, r.scheduledAt, r.executeAt)
229+
var output string
230+
231+
// ID
232+
idLabel := branding.GrayStyle.Render(" ID:")
233+
idValue := branding.PurpleStyle.Render(fmt.Sprintf("%d", r.id))
234+
output += fmt.Sprintf("%s %s\n", idLabel, idValue)
235+
236+
// Status
237+
statusLabel := branding.GrayStyle.Render(" Status:")
238+
statusValue := branding.GreenStyle.Render(getStatusString(r.status))
239+
output += fmt.Sprintf("%s %s\n", statusLabel, statusValue)
240+
241+
// Priority
242+
priorityLabel := branding.GrayStyle.Render(" Priority:")
243+
priorityValue := branding.PurpleStyle.Render(getPriorityString(r.priority))
244+
output += fmt.Sprintf("%s %s\n", priorityLabel, priorityValue)
245+
246+
// Execution Effort
247+
effortLabel := branding.GrayStyle.Render(" Execution Effort:")
248+
effortValue := branding.PurpleStyle.Render(fmt.Sprintf("%d", r.executionEffort))
249+
output += fmt.Sprintf("%s %s\n", effortLabel, effortValue)
250+
251+
// Fees
252+
feesLabel := branding.GrayStyle.Render(" Fees:")
253+
feesValue := branding.PurpleStyle.Render(fmt.Sprintf("%s FLOW", r.fees))
254+
output += fmt.Sprintf("%s %s\n", feesLabel, feesValue)
255+
256+
// Scheduled Timestamp
257+
timestampLabel := branding.GrayStyle.Render(" Scheduled Timestamp:")
258+
timestampValue := branding.PurpleStyle.Render(r.scheduledTimestamp)
259+
output += fmt.Sprintf("%s %s\n", timestampLabel, timestampValue)
260+
261+
// Handler Type
262+
handlerTypeLabel := branding.GrayStyle.Render(" Handler Type:")
263+
handlerTypeValue := branding.PurpleStyle.Render(r.handlerTypeIdentifier)
264+
output += fmt.Sprintf("%s %s\n", handlerTypeLabel, handlerTypeValue)
265+
266+
// Handler Address
267+
handlerAddrLabel := branding.GrayStyle.Render(" Handler Address:")
268+
handlerAddrValue := branding.PurpleStyle.Render(r.handlerAddress)
269+
output += fmt.Sprintf("%s %s\n", handlerAddrLabel, handlerAddrValue)
270+
271+
return output
111272
}
112273

113274
func (r *getResult) Oneliner() string {
114-
return fmt.Sprintf("Transaction %s - Status: %s", r.transactionID, r.status)
275+
statusStr := getStatusString(r.status)
276+
return fmt.Sprintf("Transaction %d - Status: %s", r.id, statusStr)
277+
}
278+
279+
// getStatusString converts status code to readable string
280+
func getStatusString(status uint8) string {
281+
switch status {
282+
case 0:
283+
return "Pending"
284+
case 1:
285+
return "Scheduled"
286+
case 2:
287+
return "Executing"
288+
case 3:
289+
return "Executed"
290+
case 4:
291+
return "Failed"
292+
case 5:
293+
return "Cancelled"
294+
default:
295+
return fmt.Sprintf("Unknown(%d)", status)
296+
}
297+
}
298+
299+
// getPriorityString converts priority code to readable string
300+
func getPriorityString(priority uint8) string {
301+
switch priority {
302+
case 0:
303+
return "Low"
304+
case 1:
305+
return "Medium"
306+
case 2:
307+
return "High"
308+
default:
309+
return fmt.Sprintf("Unknown(%d)", priority)
310+
}
115311
}

0 commit comments

Comments
 (0)