55 "encoding/json"
66 "fmt"
77 "time"
8+ "path/filepath"
89
910 actiontypes "github.com/LumeraProtocol/lumera/x/action/v1/types"
1011 "github.com/LumeraProtocol/sdk-go/blockchain"
@@ -15,8 +16,8 @@ import (
1516
1617// UploadOptions configures cascade upload
1718type UploadOptions struct {
18- Public bool
19- FileName string
19+ ID string // optional custom ID for the upload
20+ Public bool // whether the uploaded file will be accessible publicly
2021}
2122
2223// UploadOption is a functional option for Upload
@@ -29,32 +30,29 @@ func WithPublic(public bool) UploadOption {
2930 }
3031}
3132
32- // WithFileName sets a custom filename
33- func WithFileName ( name string ) UploadOption {
33+ // WithID sets a custom ID
34+ func WithID ( id string ) UploadOption {
3435 return func (o * UploadOptions ) {
35- o .FileName = name
36+ o .ID = id
3637 }
3738}
38-
3939// CreateRequestActionMessage builds Cascade metadata and constructs a MsgRequestAction without broadcasting it.
4040// Returns the built Cosmos message and the serialized metadata bytes used in the message.
41- func (c * Client ) CreateRequestActionMessage (ctx context.Context , creator string , filePath string , opts ... UploadOption ) (* actiontypes.MsgRequestAction , []byte , error ) {
42- // Apply options
43- options := & UploadOptions {Public : false }
44- for _ , opt := range opts {
45- opt (options )
41+ func (c * Client ) CreateRequestActionMessage (ctx context.Context , creator string , filePath string , options * UploadOptions ) (* actiontypes.MsgRequestAction , []byte , error ) {
42+ var isPublic bool
43+ if options != nil {
44+ isPublic = options .Public
4645 }
47-
4846 // Build metadata with SuperNode SDK
49- meta , price , expiration , err := c .snClient .BuildCascadeMetadataFromFile (ctx , filePath , options . Public )
47+ meta , price , expiration , err := c .snClient .BuildCascadeMetadataFromFile (ctx , filePath , isPublic )
5048 if err != nil {
5149 return nil , nil , fmt .Errorf ("failed to build metadata: %w" , err )
5250 }
5351 metaBytes , err := json .Marshal (& meta )
5452 if err != nil {
5553 return nil , nil , fmt .Errorf ("failed to marshal metadata: %w" , err )
5654 }
57- c .logf ("cascade: built metadata for %s (public=%t price=%s expires=%s)" , filePath , options . Public , price , expiration )
55+ c .logf ("cascade: built metadata for %s (public=%t price=%s expires=%s)" , filePath , isPublic , price , expiration )
5856
5957 // Construct the action message
6058 msg := blockchain .NewMsgRequestAction (creator , actiontypes .ActionTypeCascade , string (metaBytes ), price , expiration )
@@ -63,7 +61,8 @@ func (c *Client) CreateRequestActionMessage(ctx context.Context, creator string,
6361
6462// SendRequestActionMessage signs, simulates and broadcasts the provided request message.
6563// "memo" can be used to pass an optional filename or idempotency key.
66- func (c * Client ) SendRequestActionMessage (ctx context.Context , bc * blockchain.Client , msg * actiontypes.MsgRequestAction , memo string ) (* types.ActionResult , error ) {
64+ func (c * Client ) SendRequestActionMessage (ctx context.Context , bc * blockchain.Client , msg * actiontypes.MsgRequestAction ,
65+ memo string , options * UploadOptions ) (* types.ActionResult , error ) {
6766 if bc == nil || msg == nil {
6867 return nil , fmt .Errorf ("blockchain client and msg are required" )
6968 }
@@ -73,16 +72,22 @@ func (c *Client) SendRequestActionMessage(ctx context.Context, bc *blockchain.Cl
7372 at = actiontypes .ActionType (v )
7473 }
7574
75+ var id string
76+ if options != nil {
77+ id = options .ID
78+ }
79+
7680 // Request Action transaction
7781 taskType := normalizeTaskType (msg .GetActionType ())
7882 c .emitClientEvent (ctx , sdkEvent.Event {
79- Type : sdkEvent .SDKActionRegistrationRequested ,
83+ Type : sdkEvent .SDKGoActionRegistrationRequested ,
8084 TaskType : taskType ,
85+ TaskID : id ,
8186 Timestamp : time .Now (),
8287 Data : sdkEvent.EventData {
83- sdkEvent .KeyEventType : taskType ,
8488 sdkEvent .KeyPrice : msg .Price ,
8589 sdkEvent .KeyExpiration : msg .ExpirationTime ,
90+ sdkEvent .KeyMessage : "Action registration requested" ,
8691 },
8792 })
8893
@@ -94,14 +99,15 @@ func (c *Client) SendRequestActionMessage(ctx context.Context, bc *blockchain.Cl
9499
95100 actionID := ar .ActionID
96101 c .emitClientEvent (ctx , sdkEvent.Event {
97- Type : sdkEvent .SDKActionRegistrationConfirmed ,
102+ Type : sdkEvent .SDKGoActionRegistrationConfirmed ,
98103 ActionID : actionID ,
104+ TaskID : id ,
99105 TaskType : taskType ,
100106 Timestamp : time .Now (),
101107 Data : sdkEvent.EventData {
102- sdkEvent .KeyActionID : actionID ,
103108 sdkEvent .KeyTxHash : ar .TxHash ,
104109 sdkEvent .KeyBlockHeight : ar .Height ,
110+ sdkEvent .KeyMessage : "Action registration confirmed" ,
105111 },
106112 })
107113 c .logf ("cascade: request action confirmed action_id=%s height=%d tx=%s" , actionID , ar .Height , ar .TxHash )
@@ -144,6 +150,16 @@ func (c *Client) UploadToSupernode(ctx context.Context, actionID string, filePat
144150 if err != nil {
145151 return "" , fmt .Errorf ("failed to start cascade: %w" , err )
146152 }
153+ // emit upload started event
154+ c .emitClientEvent (ctx , sdkEvent.Event {
155+ Type : sdkEvent .SDKGoUploadStarted ,
156+ ActionID : actionID ,
157+ TaskID : taskID ,
158+ Data : sdkEvent.EventData {
159+ sdkEvent .KeyMessage : "Cascade upload task started" ,
160+ },
161+ Timestamp : time .Now (),
162+ })
147163
148164 // Wait for task completion
149165 if task , err := c .tasks .Wait (ctx , taskID ); err != nil {
@@ -155,20 +171,28 @@ func (c *Client) UploadToSupernode(ctx context.Context, actionID string, filePat
155171}
156172
157173// Upload provides a one-shot convenience helper that performs:
158- // 1) CreateRequestActionMessage 2) SendRequestActionMessage 3) UploadToSupernode
174+ // 1) CreateRequestActionMessage
175+ // 2) SendRequestActionMessage
176+ // 3) UploadToSupernode
159177func (c * Client ) Upload (ctx context.Context , creator string , bc * blockchain.Client , filePath string , opts ... UploadOption ) (* types.CascadeResult , error ) {
178+
179+ // Apply upload options
180+ options := & UploadOptions {Public : false }
181+ for _ , opt := range opts {
182+ opt (options )
183+ }
184+
160185 // Build message
161- msg , _ , err := c .CreateRequestActionMessage (ctx , creator , filePath , opts ... )
186+ msg , _ , err := c .CreateRequestActionMessage (ctx , creator , filePath , options )
162187 if err != nil {
163188 return nil , err
164189 }
165190
191+ // extract filename from path
192+ fileName := filepath .Base (filePath )
193+
166194 // Broadcast
167- options := & UploadOptions {Public : false }
168- for _ , opt := range opts {
169- opt (options )
170- }
171- ar , err := c .SendRequestActionMessage (ctx , bc , msg , options .FileName )
195+ ar , err := c .SendRequestActionMessage (ctx , bc , msg , fileName , options )
172196 if err != nil {
173197 return nil , fmt .Errorf ("request action tx: %w" , err )
174198 }
@@ -205,14 +229,36 @@ func (c *Client) Download(ctx context.Context, actionID string, outputDir string
205229 opt (options )
206230 }
207231
232+ taskType := string (types .ActionTypeCascade )
233+ c .logf ("cascade: starting download, action=%s dest=%s" , actionID , outputDir )
234+ c .emitClientEvent (ctx , sdkEvent.Event {
235+ Type : sdkEvent .SDKGoDownloadStarted ,
236+ ActionID : actionID ,
237+ TaskType : taskType ,
238+ Data : sdkEvent.EventData {
239+ sdkEvent .KeyMessage : "Cascade download task started" ,
240+ },
241+ Timestamp : time .Now (),
242+ })
243+
208244 // Create download signature
209245 signature , err := c .snClient .GenerateDownloadSignature (ctx , actionID , c .config .Address )
210246 if err != nil {
211247 return nil , fmt .Errorf ("failed to create signature: %w" , err )
212248 }
213249
250+ c .logf ("cascade: download signature generated, action=%s" , actionID )
251+ c .emitClientEvent (ctx , sdkEvent.Event {
252+ Type : sdkEvent .SDKGoDownloadSignatureGenerated ,
253+ ActionID : actionID ,
254+ TaskType : taskType ,
255+ Data : sdkEvent.EventData {
256+ sdkEvent .KeyMessage : "Cascade download signature generated" ,
257+ },
258+ Timestamp : time .Now (),
259+ })
260+
214261 // Start download via SuperNode SDK
215- c .logf ("cascade: starting download action_id=%s dest=%s" , actionID , outputDir )
216262 taskID , err := c .snClient .DownloadCascade (ctx , actionID , outputDir , signature )
217263 if err != nil {
218264 return nil , fmt .Errorf ("failed to start download: %w" , err )
@@ -223,13 +269,26 @@ func (c *Client) Download(ctx context.Context, actionID string, outputDir string
223269 if err != nil {
224270 return nil , fmt .Errorf ("download failed: %w" , err )
225271 }
226- c .logf ("cascade: download completed action_id=%s task_id=%s" , actionID , task .TaskID )
227272
228- return & types.DownloadResult {
273+ result := & types.DownloadResult {
229274 ActionID : actionID ,
230275 TaskID : task .TaskID ,
231276 OutputPath : outputDir + "/" + actionID ,
232- }, nil
277+ }
278+
279+ c .logf ("cascade: download completed action_id=%s task_id=%s" , actionID , taskID )
280+ c .emitClientEvent (ctx , sdkEvent.Event {
281+ Type : sdkEvent .SDKGoDownloadCompleted ,
282+ ActionID : actionID ,
283+ TaskType : taskType ,
284+ TaskID : taskID ,
285+ Data : sdkEvent.EventData {
286+ sdkEvent .KeyMessage : "Cascade download task completed" ,
287+ },
288+ Timestamp : time .Now (),
289+ })
290+
291+ return result , nil
233292}
234293
235294func (c * Client ) emitClientEvent (ctx context.Context , evt sdkEvent.Event ) {
0 commit comments