@@ -404,3 +404,145 @@ def test_chunk_transaction_id_nanosecond_overflow(file_id):
404404 # Second chunk seconds=base_seconds + 1, nanos=0
405405 assert tx ._transaction_ids [1 ].valid_start .seconds == base_seconds + 1
406406 assert tx ._transaction_ids [1 ].valid_start .nanos == 0
407+
408+
409+ def test_serialization_non_chunk_transaction_non_freeze (file_id ):
410+ """Test that FileAppendTransaction can serialize non frozen and non chunk transaction"""
411+ content = "Hello! Hiero"
412+
413+ tx1 = FileAppendTransaction ().set_file_id (file_id ).set_contents (content ).set_chunk_size (100 ).set_max_chunks (10 )
414+
415+ assert tx1 .file_id == file_id
416+ assert tx1 .contents == content .encode ("utf-8" )
417+ assert tx1 .chunk_size == 100
418+ assert tx1 .max_chunks == 10
419+
420+ tx_bytes = tx1 .to_bytes ()
421+
422+ assert tx_bytes is not None
423+
424+ tx2 = Transaction .from_bytes (tx_bytes )
425+
426+ assert isinstance (tx2 , FileAppendTransaction )
427+ assert not tx2 ._transaction_body_bytes
428+ assert tx2 .file_id == tx1 .file_id
429+ assert tx2 .contents == tx1 .contents
430+
431+ # These values are not serialized because they are not part of FileAppendTransactionBody they should fallback to default values.
432+ assert tx2 .chunk_size != tx1 .chunk_size
433+ assert tx2 .chunk_size == 4096
434+ assert tx2 .max_chunks != tx1 .max_chunks
435+ assert tx2 .max_chunks == 20
436+
437+
438+ def test_serialization_chunk_transaction_non_freeze (file_id ):
439+ """Test that FileAppendTransaction can serialize non frozen and chunk transaction"""
440+ content = "A" * 8192 # create 2 chucks
441+
442+ tx1 = FileAppendTransaction ().set_file_id (file_id ).set_contents (content )
443+
444+ assert tx1 .file_id == file_id
445+ assert tx1 .contents == content .encode ("utf-8" )
446+
447+ tx_bytes = tx1 .to_bytes ()
448+
449+ assert tx_bytes is not None
450+
451+ tx2 = Transaction .from_bytes (tx_bytes )
452+
453+ assert isinstance (tx2 , FileAppendTransaction )
454+ assert not tx2 ._transaction_body_bytes
455+ assert tx2 .file_id == tx1 .file_id
456+ assert tx2 .contents == tx1 .contents
457+
458+
459+ def test_serialization_non_chunk_transaction_freeze (file_id ):
460+ """Test that FileAppendTransaction can serialize frozen and non chunk transaction"""
461+ transaction_id = TransactionId .generate (AccountId (0 , 0 , 3 ))
462+ content = "Hello! Hiero"
463+
464+ tx1 = (
465+ FileAppendTransaction ()
466+ .set_file_id (file_id )
467+ .set_contents (content )
468+ .set_chunk_size (100 )
469+ .set_max_chunks (10 )
470+ .set_transaction_id (transaction_id )
471+ .set_node_account_ids ([AccountId (0 , 0 , 4 ), AccountId (0 , 0 , 5 )])
472+ .freeze ()
473+ )
474+
475+ assert tx1 .file_id == file_id
476+ assert tx1 .contents == content .encode ("utf-8" )
477+ assert tx1 .chunk_size == 100
478+ assert tx1 .max_chunks == 10
479+
480+ assert tx1 ._transaction_body_bytes
481+
482+ assert tx1 .transaction_id == transaction_id
483+ assert len (tx1 ._transaction_ids ) == 1 # single chunk
484+
485+ tx_bytes = tx1 .to_bytes ()
486+
487+ assert tx_bytes is not None
488+
489+ tx2 = Transaction .from_bytes (tx_bytes )
490+
491+ assert isinstance (tx2 , FileAppendTransaction )
492+ assert tx2 .file_id == tx1 .file_id
493+ assert tx2 .contents == tx1 .contents
494+
495+ assert tx2 .chunk_size != tx1 .chunk_size
496+ assert tx2 .chunk_size == 4096
497+ assert tx2 .max_chunks != tx1 .max_chunks
498+ assert tx2 .max_chunks == 20
499+
500+ assert tx2 ._transaction_body_bytes
501+
502+ assert tx2 .transaction_id == transaction_id
503+ assert len (tx2 ._transaction_ids ) == 1 # single chunk
504+ assert tx2 ._transaction_ids == tx1 ._transaction_ids
505+ assert tx2 .node_account_ids == tx1 .node_account_ids
506+
507+
508+ def test_serialization_chunk_transaction_freeze (file_id ):
509+ """Test that FileAppendTransaction can serialize frozen and chunk transaction"""
510+ transaction_id = TransactionId .generate (AccountId (0 , 0 , 3 ))
511+ content = "A" * 8192 # create 2 chucks
512+
513+ tx1 = (
514+ FileAppendTransaction ()
515+ .set_file_id (file_id )
516+ .set_contents (content )
517+ .set_transaction_id (transaction_id )
518+ .set_node_account_ids ([AccountId (0 , 0 , 4 ), AccountId (0 , 0 , 5 )])
519+ .freeze ()
520+ )
521+
522+ assert tx1 .file_id == file_id
523+ assert tx1 .contents == content .encode ("utf-8" )
524+
525+ assert tx1 ._transaction_body_bytes
526+
527+ assert tx1 .transaction_id == transaction_id
528+ assert len (tx1 ._transaction_ids ) == 2 # 2 chunks
529+
530+ tx_bytes = tx1 .to_bytes ()
531+
532+ assert tx_bytes is not None
533+
534+ tx2 = Transaction .from_bytes (tx_bytes )
535+
536+ assert isinstance (tx2 , FileAppendTransaction )
537+ assert tx2 .file_id == tx1 .file_id
538+
539+ # On freeze, the chunked tx content will be only the first chunk content. the chunk execution is handle by the _transaction_bytes and _transaction_ids
540+ assert tx2 .contents != tx1 .contents
541+ assert tx2 .contents == tx1 .contents [0 :4096 ]
542+
543+ assert tx2 ._transaction_body_bytes
544+
545+ assert tx2 .transaction_id == transaction_id
546+ assert len (tx2 ._transaction_ids ) == 2 # 2 chunk
547+ assert tx2 ._transaction_ids == tx1 ._transaction_ids
548+ assert tx2 .node_account_ids == tx1 .node_account_ids
0 commit comments