@@ -821,6 +821,126 @@ export class SorobanEventWorker {
821821 timestamp,
822822 } ) ;
823823 }
824+
825+ private async handleStreamPaused (
826+ event : rpc . Api . EventResponse ,
827+ streamIdTopic : xdr . ScVal ,
828+ ) : Promise < void > {
829+ const streamId = Number ( decodeU64 ( streamIdTopic ) ) ;
830+ const body = decodeMap ( event . value ) ;
831+
832+ if ( ! body [ 'sender' ] || ! body [ 'paused_at' ] ) {
833+ throw new Error ( `StreamPaused #${ streamId } : missing body fields` ) ;
834+ }
835+
836+ const sender = decodeAddress ( body [ 'sender' ] ) ;
837+ const pausedAt = Number ( decodeU64 ( body [ 'paused_at' ] ) ) ;
838+ const timestamp = Math . floor ( Date . now ( ) / 1000 ) ;
839+
840+ await prisma . $transaction ( async ( tx : any ) => {
841+ // Get current stream to preserve totalPausedDuration
842+ const currentStream = await tx . stream . findUniqueOrThrow ( {
843+ where : { streamId } ,
844+ select : { totalPausedDuration : true } ,
845+ } ) ;
846+
847+ await tx . stream . update ( {
848+ where : { streamId } ,
849+ data : {
850+ isPaused : true ,
851+ pausedAt,
852+ lastUpdateTime : timestamp ,
853+ } ,
854+ } ) ;
855+
856+ await tx . streamEvent . create ( {
857+ data : {
858+ streamId,
859+ eventType : 'PAUSED' ,
860+ transactionHash : event . txHash ,
861+ ledgerSequence : event . ledger ,
862+ timestamp,
863+ metadata : JSON . stringify ( { sender, pausedAt } ) ,
864+ } ,
865+ } ) ;
866+ } ) ;
867+
868+ sseService . broadcastToStream ( String ( streamId ) , 'stream.paused' , {
869+ streamId,
870+ sender,
871+ pausedAt,
872+ transactionHash : event . txHash ,
873+ ledger : event . ledger ,
874+ timestamp,
875+ } ) ;
876+ }
877+
878+ private async handleStreamResumed (
879+ event : rpc . Api . EventResponse ,
880+ streamIdTopic : xdr . ScVal ,
881+ ) : Promise < void > {
882+ const streamId = Number ( decodeU64 ( streamIdTopic ) ) ;
883+ const body = decodeMap ( event . value ) ;
884+
885+ if ( ! body [ 'sender' ] || ! body [ 'new_end_time' ] ) {
886+ throw new Error ( `StreamResumed #${ streamId } : missing body fields` ) ;
887+ }
888+
889+ const sender = decodeAddress ( body [ 'sender' ] ) ;
890+ const newEndTime = Number ( decodeU64 ( body [ 'new_end_time' ] ) ) ;
891+ const timestamp = Math . floor ( Date . now ( ) / 1000 ) ;
892+
893+ await prisma . $transaction ( async ( tx : any ) => {
894+ // Get current stream to calculate paused duration
895+ const currentStream = await tx . stream . findUniqueOrThrow ( {
896+ where : { streamId } ,
897+ select : { pausedAt : true , totalPausedDuration : true } ,
898+ } ) ;
899+
900+ // Calculate the duration of this pause interval
901+ let additionalPausedDuration = 0 ;
902+ if ( currentStream . pausedAt ) {
903+ additionalPausedDuration = timestamp - currentStream . pausedAt ;
904+ }
905+
906+ const newTotalPausedDuration = currentStream . totalPausedDuration + additionalPausedDuration ;
907+
908+ await tx . stream . update ( {
909+ where : { streamId } ,
910+ data : {
911+ isPaused : false ,
912+ pausedAt : null ,
913+ totalPausedDuration : newTotalPausedDuration ,
914+ lastUpdateTime : timestamp ,
915+ } ,
916+ } ) ;
917+
918+ await tx . streamEvent . create ( {
919+ data : {
920+ streamId,
921+ eventType : 'RESUMED' ,
922+ transactionHash : event . txHash ,
923+ ledgerSequence : event . ledger ,
924+ timestamp,
925+ metadata : JSON . stringify ( {
926+ sender,
927+ newEndTime,
928+ pausedDuration : additionalPausedDuration ,
929+ totalPausedDuration : newTotalPausedDuration
930+ } ) ,
931+ } ,
932+ } ) ;
933+ } ) ;
934+
935+ sseService . broadcastToStream ( String ( streamId ) , 'stream.resumed' , {
936+ streamId,
937+ sender,
938+ newEndTime,
939+ transactionHash : event . txHash ,
940+ ledger : event . ledger ,
941+ timestamp,
942+ } ) ;
943+ }
824944}
825945
826946export const sorobanEventWorker = new SorobanEventWorker ( ) ;
0 commit comments