1use crate::error::{AptosError, AptosResult};
33use crate::transaction::{EntryFunction, TransactionPayload};
34use crate::types::{AccountAddress, EntryFunctionId, MoveModuleId, TypeTag};
35use serde::Serialize;
36
37#[allow(dead_code)] #[derive(Debug, Clone)]
55pub struct InputEntryFunctionData {
56 module: MoveModuleId,
57 function: String,
58 type_args: Vec<TypeTag>,
59 args: Vec<Vec<u8>>,
60}
61
62impl InputEntryFunctionData {
63 #[allow(clippy::new_ret_no_self)] pub fn new(function_id: &str) -> InputEntryFunctionDataBuilder {
76 InputEntryFunctionDataBuilder::new(function_id)
77 }
78
79 pub fn from_parts(
86 module: MoveModuleId,
87 function: impl Into<String>,
88 ) -> InputEntryFunctionDataBuilder {
89 InputEntryFunctionDataBuilder {
90 module: Ok(module),
91 function: function.into(),
92 type_args: Vec::new(),
93 args: Vec::new(),
94 errors: Vec::new(),
95 }
96 }
97
98 pub fn transfer_apt(recipient: AccountAddress, amount: u64) -> AptosResult<TransactionPayload> {
115 InputEntryFunctionData::new("0x1::aptos_account::transfer")
116 .arg(recipient)
117 .arg(amount)
118 .build()
119 }
120
121 pub fn transfer_coin(
133 coin_type: &str,
134 recipient: AccountAddress,
135 amount: u64,
136 ) -> AptosResult<TransactionPayload> {
137 InputEntryFunctionData::new("0x1::coin::transfer")
138 .type_arg(coin_type)
139 .arg(recipient)
140 .arg(amount)
141 .build()
142 }
143
144 pub fn create_account(auth_key: AccountAddress) -> AptosResult<TransactionPayload> {
154 InputEntryFunctionData::new("0x1::aptos_account::create_account")
155 .arg(auth_key)
156 .build()
157 }
158
159 pub fn rotate_authentication_key(
169 from_scheme: u8,
170 from_public_key_bytes: Vec<u8>,
171 to_scheme: u8,
172 to_public_key_bytes: Vec<u8>,
173 cap_rotate_key: Vec<u8>,
174 cap_update_table: Vec<u8>,
175 ) -> AptosResult<TransactionPayload> {
176 InputEntryFunctionData::new("0x1::account::rotate_authentication_key")
177 .arg(from_scheme)
178 .arg(from_public_key_bytes)
179 .arg(to_scheme)
180 .arg(to_public_key_bytes)
181 .arg(cap_rotate_key)
182 .arg(cap_update_table)
183 .build()
184 }
185
186 pub fn register_coin(coin_type: &str) -> AptosResult<TransactionPayload> {
196 InputEntryFunctionData::new("0x1::managed_coin::register")
197 .type_arg(coin_type)
198 .build()
199 }
200
201 pub fn publish_package(
212 metadata_serialized: Vec<u8>,
213 code: Vec<Vec<u8>>,
214 ) -> AptosResult<TransactionPayload> {
215 InputEntryFunctionData::new("0x1::code::publish_package_txn")
216 .arg(metadata_serialized)
217 .arg(code)
218 .build()
219 }
220}
221
222#[derive(Debug, Clone)]
224pub struct InputEntryFunctionDataBuilder {
225 module: Result<MoveModuleId, String>,
226 function: String,
227 type_args: Vec<TypeTag>,
228 args: Vec<Vec<u8>>,
229 errors: Vec<String>,
230}
231
232impl InputEntryFunctionDataBuilder {
233 #[must_use]
235 fn new(function_id: &str) -> Self {
236 match EntryFunctionId::from_str_strict(function_id) {
237 Ok(func_id) => Self {
238 module: Ok(func_id.module),
239 function: func_id.name.as_str().to_string(),
240 type_args: Vec::new(),
241 args: Vec::new(),
242 errors: Vec::new(),
243 },
244 Err(e) => Self {
245 module: Err(format!("Invalid function ID '{function_id}': {e}")),
246 function: String::new(),
247 type_args: Vec::new(),
248 args: Vec::new(),
249 errors: Vec::new(),
250 },
251 }
252 }
253
254 #[must_use]
267 pub fn type_arg(mut self, type_arg: &str) -> Self {
268 match TypeTag::from_str_strict(type_arg) {
269 Ok(tag) => self.type_args.push(tag),
270 Err(e) => self
271 .errors
272 .push(format!("Invalid type argument '{type_arg}': {e}")),
273 }
274 self
275 }
276
277 #[must_use]
279 pub fn type_arg_typed(mut self, type_arg: TypeTag) -> Self {
280 self.type_args.push(type_arg);
281 self
282 }
283
284 #[must_use]
286 pub fn type_args(mut self, type_args: impl IntoIterator<Item = &'static str>) -> Self {
287 for type_arg in type_args {
288 self = self.type_arg(type_arg);
289 }
290 self
291 }
292
293 #[must_use]
295 pub fn type_args_typed(mut self, type_args: impl IntoIterator<Item = TypeTag>) -> Self {
296 self.type_args.extend(type_args);
297 self
298 }
299
300 #[must_use]
323 pub fn arg<T: Serialize>(mut self, value: T) -> Self {
324 match aptos_bcs::to_bytes(&value) {
325 Ok(bytes) => self.args.push(bytes),
326 Err(e) => self
327 .errors
328 .push(format!("Failed to serialize argument: {e}")),
329 }
330 self
331 }
332
333 #[must_use]
337 pub fn arg_raw(mut self, bytes: Vec<u8>) -> Self {
338 self.args.push(bytes);
339 self
340 }
341
342 #[must_use]
344 pub fn args<T: Serialize>(mut self, values: impl IntoIterator<Item = T>) -> Self {
345 for value in values {
346 self = self.arg(value);
347 }
348 self
349 }
350
351 pub fn build(self) -> AptosResult<TransactionPayload> {
362 let module = self.module.map_err(AptosError::Transaction)?;
364
365 if !self.errors.is_empty() {
367 return Err(AptosError::Transaction(self.errors.join("; ")));
368 }
369
370 Ok(TransactionPayload::EntryFunction(EntryFunction {
371 module,
372 function: self.function,
373 type_args: self.type_args,
374 args: self.args,
375 }))
376 }
377
378 pub fn build_entry_function(self) -> AptosResult<EntryFunction> {
384 let module = self.module.map_err(AptosError::Transaction)?;
385
386 if !self.errors.is_empty() {
387 return Err(AptosError::Transaction(self.errors.join("; ")));
388 }
389
390 Ok(EntryFunction {
391 module,
392 function: self.function,
393 type_args: self.type_args,
394 args: self.args,
395 })
396 }
397}
398
399pub trait IntoMoveArg {
403 fn into_move_arg(self) -> AptosResult<Vec<u8>>;
409}
410
411impl<T: Serialize> IntoMoveArg for T {
412 fn into_move_arg(self) -> AptosResult<Vec<u8>> {
413 aptos_bcs::to_bytes(&self).map_err(AptosError::bcs)
414 }
415}
416
417pub fn move_vec<T: Serialize>(items: &[T]) -> Vec<u8> {
428 aptos_bcs::to_bytes(items).unwrap_or_default()
429}
430
431pub fn move_string(s: &str) -> String {
441 s.to_string()
442}
443
444pub fn move_some<T: Serialize>(value: T) -> Vec<u8> {
452 let mut bytes = vec![0x01];
454 if let Ok(value_bytes) = aptos_bcs::to_bytes(&value) {
455 bytes.extend(value_bytes);
456 }
457 bytes
458}
459
460pub fn move_none() -> Vec<u8> {
468 vec![0x00]
470}
471
472#[derive(Debug, Clone, Copy, PartialEq, Eq)]
476pub struct MoveU256(pub [u8; 32]);
477
478impl MoveU256 {
479 pub fn parse(s: &str) -> AptosResult<Self> {
485 let mut bytes = [0u8; 32];
487
488 if let Ok(val) = s.parse::<u128>() {
490 bytes[..16].copy_from_slice(&val.to_le_bytes());
491 return Ok(Self(bytes));
492 }
493
494 Err(AptosError::Transaction(format!("Invalid u256: {s}")))
495 }
496
497 pub fn from_u128(val: u128) -> Self {
499 let mut bytes = [0u8; 32];
500 bytes[..16].copy_from_slice(&val.to_le_bytes());
501 Self(bytes)
502 }
503
504 pub fn from_le_bytes(bytes: [u8; 32]) -> Self {
506 Self(bytes)
507 }
508}
509
510impl Serialize for MoveU256 {
511 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
512 where
513 S: serde::Serializer,
514 {
515 use serde::ser::SerializeTuple;
517 let mut tuple = serializer.serialize_tuple(32)?;
518 for byte in &self.0 {
519 tuple.serialize_element(byte)?;
520 }
521 tuple.end()
522 }
523}
524
525#[derive(Debug, Clone, Copy, PartialEq, Eq)]
530pub struct MoveI128(pub i128);
531
532impl MoveI128 {
533 pub fn new(val: i128) -> Self {
535 Self(val)
536 }
537}
538
539impl Serialize for MoveI128 {
540 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
541 where
542 S: serde::Serializer,
543 {
544 use serde::ser::SerializeTuple;
546 let bytes = self.0.to_le_bytes();
547 let mut tuple = serializer.serialize_tuple(16)?;
548 for byte in &bytes {
549 tuple.serialize_element(byte)?;
550 }
551 tuple.end()
552 }
553}
554
555impl From<i128> for MoveI128 {
556 fn from(val: i128) -> Self {
557 Self(val)
558 }
559}
560
561#[derive(Debug, Clone, Copy, PartialEq, Eq)]
566pub struct MoveI256(pub [u8; 32]);
567
568impl MoveI256 {
569 pub fn from_i128(val: i128) -> Self {
571 let mut bytes = [0u8; 32];
572 let val_bytes = val.to_le_bytes();
573 bytes[..16].copy_from_slice(&val_bytes);
574 if val < 0 {
576 bytes[16..].fill(0xFF);
577 }
578 Self(bytes)
579 }
580
581 pub fn from_le_bytes(bytes: [u8; 32]) -> Self {
583 Self(bytes)
584 }
585}
586
587impl Serialize for MoveI256 {
588 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
589 where
590 S: serde::Serializer,
591 {
592 use serde::ser::SerializeTuple;
594 let mut tuple = serializer.serialize_tuple(32)?;
595 for byte in &self.0 {
596 tuple.serialize_element(byte)?;
597 }
598 tuple.end()
599 }
600}
601
602impl From<i128> for MoveI256 {
603 fn from(val: i128) -> Self {
604 Self::from_i128(val)
605 }
606}
607
608pub mod functions {
610 pub const APT_TRANSFER: &str = "0x1::aptos_account::transfer";
612 pub const COIN_TRANSFER: &str = "0x1::coin::transfer";
614 pub const CREATE_ACCOUNT: &str = "0x1::aptos_account::create_account";
616 pub const REGISTER_COIN: &str = "0x1::managed_coin::register";
618 pub const PUBLISH_PACKAGE: &str = "0x1::code::publish_package_txn";
620 pub const ROTATE_AUTH_KEY: &str = "0x1::account::rotate_authentication_key";
622}
623
624pub mod types {
626 pub const APT_COIN: &str = "0x1::aptos_coin::AptosCoin";
628}
629
630#[cfg(test)]
631mod tests {
632 use super::*;
633
634 #[test]
635 fn test_simple_transfer() {
636 let recipient = AccountAddress::from_hex("0x123").unwrap();
637 let payload = InputEntryFunctionData::new("0x1::aptos_account::transfer")
638 .arg(recipient)
639 .arg(1_000_000u64)
640 .build()
641 .unwrap();
642
643 match payload {
644 TransactionPayload::EntryFunction(ef) => {
645 assert_eq!(ef.function, "transfer");
646 assert_eq!(ef.module.name.as_str(), "aptos_account");
647 assert!(ef.type_args.is_empty());
648 assert_eq!(ef.args.len(), 2);
649 }
650 _ => panic!("Expected EntryFunction"),
651 }
652 }
653
654 #[test]
655 fn test_with_type_args() {
656 let payload = InputEntryFunctionData::new("0x1::coin::transfer")
657 .type_arg("0x1::aptos_coin::AptosCoin")
658 .arg(AccountAddress::ONE)
659 .arg(1000u64)
660 .build()
661 .unwrap();
662
663 match payload {
664 TransactionPayload::EntryFunction(ef) => {
665 assert_eq!(ef.function, "transfer");
666 assert_eq!(ef.type_args.len(), 1);
667 }
668 _ => panic!("Expected EntryFunction"),
669 }
670 }
671
672 #[test]
673 fn test_invalid_function_id() {
674 let result = InputEntryFunctionData::new("invalid").arg(42u64).build();
675
676 assert!(result.is_err());
677 }
678
679 #[test]
680 fn test_invalid_type_arg() {
681 let result = InputEntryFunctionData::new("0x1::coin::transfer")
682 .type_arg("not a type")
683 .arg(AccountAddress::ONE)
684 .arg(1000u64)
685 .build();
686
687 assert!(result.is_err());
688 }
689
690 #[test]
691 fn test_transfer_apt_helper() {
692 let recipient = AccountAddress::from_hex("0x456").unwrap();
693 let payload = InputEntryFunctionData::transfer_apt(recipient, 5_000_000).unwrap();
694
695 match payload {
696 TransactionPayload::EntryFunction(ef) => {
697 assert_eq!(ef.function, "transfer");
698 assert_eq!(ef.module.name.as_str(), "aptos_account");
699 }
700 _ => panic!("Expected EntryFunction"),
701 }
702 }
703
704 #[test]
705 fn test_transfer_coin_helper() {
706 let recipient = AccountAddress::from_hex("0x789").unwrap();
707 let payload =
708 InputEntryFunctionData::transfer_coin("0x1::aptos_coin::AptosCoin", recipient, 1000)
709 .unwrap();
710
711 match payload {
712 TransactionPayload::EntryFunction(ef) => {
713 assert_eq!(ef.function, "transfer");
714 assert_eq!(ef.module.name.as_str(), "coin");
715 assert_eq!(ef.type_args.len(), 1);
716 }
717 _ => panic!("Expected EntryFunction"),
718 }
719 }
720
721 #[test]
722 fn test_various_arg_types() {
723 let payload = InputEntryFunctionData::new("0x1::test::test_function")
724 .arg(42u8)
725 .arg(1000u64)
726 .arg(true)
727 .arg("hello".to_string())
728 .arg(vec![1u8, 2u8, 3u8])
729 .arg(AccountAddress::ONE)
730 .build()
731 .unwrap();
732
733 match payload {
734 TransactionPayload::EntryFunction(ef) => {
735 assert_eq!(ef.args.len(), 6);
736 }
737 _ => panic!("Expected EntryFunction"),
738 }
739 }
740
741 #[test]
742 fn test_move_u256() {
743 let val = MoveU256::from_u128(12345);
744 let bytes = aptos_bcs::to_bytes(&val).unwrap();
745 assert_eq!(bytes.len(), 32);
746 }
747
748 #[test]
749 fn test_move_some_none() {
750 let some_bytes = move_some(42u64);
751 assert_eq!(some_bytes[0], 0x01);
752
753 let none_bytes = move_none();
754 assert_eq!(none_bytes, vec![0x00]);
755 }
756
757 #[test]
758 fn test_from_parts() {
759 let module = MoveModuleId::from_str_strict("0x1::coin").unwrap();
760 let payload = InputEntryFunctionData::from_parts(module, "transfer")
761 .type_arg("0x1::aptos_coin::AptosCoin")
762 .arg(AccountAddress::ONE)
763 .arg(1000u64)
764 .build()
765 .unwrap();
766
767 match payload {
768 TransactionPayload::EntryFunction(ef) => {
769 assert_eq!(ef.function, "transfer");
770 assert_eq!(ef.module.name.as_str(), "coin");
771 }
772 _ => panic!("Expected EntryFunction"),
773 }
774 }
775
776 #[test]
777 fn test_build_entry_function() {
778 let ef = InputEntryFunctionData::new("0x1::aptos_account::transfer")
779 .arg(AccountAddress::ONE)
780 .arg(1000u64)
781 .build_entry_function()
782 .unwrap();
783
784 assert_eq!(ef.function, "transfer");
785 assert_eq!(ef.args.len(), 2);
786 }
787
788 #[test]
789 fn test_function_constants() {
790 assert_eq!(functions::APT_TRANSFER, "0x1::aptos_account::transfer");
791 assert_eq!(functions::COIN_TRANSFER, "0x1::coin::transfer");
792 }
793
794 #[test]
795 fn test_move_u256_from_u128() {
796 let val = MoveU256::from_u128(123_456_789);
797 let expected = 123_456_789_u128.to_le_bytes();
799 assert_eq!(&val.0[..16], &expected);
800 assert_eq!(&val.0[16..], &[0u8; 16]);
802 }
803
804 #[test]
805 fn test_move_u256_from_le_bytes() {
806 let bytes = [0xab; 32];
807 let val = MoveU256::from_le_bytes(bytes);
808 assert_eq!(val.0, bytes);
809 }
810
811 #[test]
812 fn test_move_u256_parse() {
813 let val = MoveU256::parse("12345678901234567890").unwrap();
814 let expected = 12_345_678_901_234_567_890_u128;
815 let mut expected_bytes = [0u8; 32];
816 expected_bytes[..16].copy_from_slice(&expected.to_le_bytes());
817 assert_eq!(val.0, expected_bytes);
818 }
819
820 #[test]
821 fn test_move_u256_parse_invalid() {
822 let result = MoveU256::parse("999999999999999999999999999999999999999999999");
824 assert!(result.is_err());
825 }
826
827 #[test]
828 fn test_move_u256_serialization() {
829 let val = MoveU256::from_u128(0x0102_0304_0506_0708);
830 let bcs = aptos_bcs::to_bytes(&val).unwrap();
831 assert_eq!(bcs.len(), 32);
833 assert_eq!(&bcs[..8], &[0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01]);
835 }
836
837 #[test]
838 fn test_move_i128_new() {
839 let val = MoveI128::new(42);
840 assert_eq!(val.0, 42);
841 }
842
843 #[test]
844 fn test_move_i128_from_i128() {
845 let val: MoveI128 = (-100i128).into();
846 assert_eq!(val.0, -100);
847 }
848
849 #[test]
850 fn test_move_i128_serialization_positive() {
851 let val = MoveI128::new(0x0102_0304_0506_0708);
852 let bcs = aptos_bcs::to_bytes(&val).unwrap();
853 assert_eq!(bcs.len(), 16);
855 assert_eq!(&bcs[..8], &[0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01]);
857 assert_eq!(&bcs[8..], &[0, 0, 0, 0, 0, 0, 0, 0]);
859 }
860
861 #[test]
862 fn test_move_i128_serialization_negative() {
863 let val = MoveI128::new(-1);
864 let bcs = aptos_bcs::to_bytes(&val).unwrap();
865 assert_eq!(bcs.len(), 16);
866 assert_eq!(bcs, vec![0xFF; 16]);
868 }
869
870 #[test]
871 fn test_move_i256_from_i128_positive() {
872 let val = MoveI256::from_i128(42);
873 let expected = 42i128.to_le_bytes();
875 assert_eq!(&val.0[..16], &expected);
876 assert_eq!(&val.0[16..], &[0u8; 16]);
878 }
879
880 #[test]
881 fn test_move_i256_from_i128_negative() {
882 let val = MoveI256::from_i128(-1);
883 assert_eq!(val.0, [0xFF; 32]);
885 }
886
887 #[test]
888 fn test_move_i256_from_le_bytes() {
889 let bytes = [0xcd; 32];
890 let val = MoveI256::from_le_bytes(bytes);
891 assert_eq!(val.0, bytes);
892 }
893
894 #[test]
895 fn test_move_i256_from_trait() {
896 let val: MoveI256 = (-100i128).into();
897 let expected = MoveI256::from_i128(-100);
898 assert_eq!(val, expected);
899 }
900
901 #[test]
902 fn test_move_i256_serialization() {
903 let val = MoveI256::from_i128(0x0102_0304_0506_0708);
904 let bcs = aptos_bcs::to_bytes(&val).unwrap();
905 assert_eq!(bcs.len(), 32);
907 assert_eq!(&bcs[..8], &[0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01]);
909 }
910
911 #[test]
912 fn test_move_i256_serialization_negative() {
913 let val = MoveI256::from_i128(-1);
914 let bcs = aptos_bcs::to_bytes(&val).unwrap();
915 assert_eq!(bcs.len(), 32);
916 assert_eq!(bcs, vec![0xFF; 32]);
918 }
919
920 fn payload_as_entry_function(
923 p: crate::transaction::TransactionPayload,
924 ) -> crate::transaction::EntryFunction {
925 match p {
926 crate::transaction::TransactionPayload::EntryFunction(ef) => ef,
927 other => panic!(
928 "expected TransactionPayload::EntryFunction, got: {:?}",
929 std::mem::discriminant(&other)
930 ),
931 }
932 }
933
934 #[test]
935 fn test_input_entry_function_data_new() {
936 let builder = InputEntryFunctionData::new("0x1::coin::transfer");
937 let entry_fn = payload_as_entry_function(builder.build().expect("build should succeed"));
938 assert_eq!(entry_fn.module.name.as_str(), "coin");
939 assert_eq!(entry_fn.function, "transfer");
940 assert!(entry_fn.type_args.is_empty());
941 assert!(entry_fn.args.is_empty());
942 }
943
944 #[test]
945 fn test_input_entry_function_data_invalid_function_id() {
946 let builder = InputEntryFunctionData::new("invalid");
947 let result = builder.build();
948 assert!(result.is_err());
949 assert!(
950 result
951 .unwrap_err()
952 .to_string()
953 .contains("Invalid function ID")
954 );
955 }
956
957 #[test]
958 fn test_input_entry_function_data_type_arg() {
959 let entry_fn = payload_as_entry_function(
960 InputEntryFunctionData::new("0x1::coin::transfer")
961 .type_arg("0x1::aptos_coin::AptosCoin")
962 .build()
963 .expect("build should succeed"),
964 );
965 assert_eq!(entry_fn.type_args.len(), 1);
966 assert_eq!(
967 entry_fn.type_args[0].to_string(),
968 "0x1::aptos_coin::AptosCoin"
969 );
970 }
971
972 #[test]
973 fn test_input_entry_function_data_invalid_type_arg() {
974 let builder =
975 InputEntryFunctionData::new("0x1::coin::transfer").type_arg("not a valid type");
976 let result = builder.build();
977 assert!(result.is_err());
978 assert!(result.unwrap_err().to_string().contains("type argument"));
979 }
980
981 #[test]
982 fn test_input_entry_function_data_type_arg_typed() {
983 use crate::types::TypeTag;
984
985 let entry_fn = payload_as_entry_function(
986 InputEntryFunctionData::new("0x1::coin::transfer")
987 .type_arg_typed(TypeTag::U64)
988 .build()
989 .expect("build should succeed"),
990 );
991 assert_eq!(entry_fn.type_args, vec![TypeTag::U64]);
992 }
993
994 #[test]
995 fn test_input_entry_function_data_type_args() {
996 let entry_fn = payload_as_entry_function(
997 InputEntryFunctionData::new("0x1::coin::transfer")
998 .type_args(["u64", "u128"])
999 .build()
1000 .expect("build should succeed"),
1001 );
1002 assert_eq!(entry_fn.type_args.len(), 2);
1003 assert_eq!(entry_fn.type_args[0].to_string(), "u64");
1004 assert_eq!(entry_fn.type_args[1].to_string(), "u128");
1005 }
1006
1007 #[test]
1008 fn test_input_entry_function_data_type_args_typed() {
1009 use crate::types::TypeTag;
1010
1011 let entry_fn = payload_as_entry_function(
1012 InputEntryFunctionData::new("0x1::coin::transfer")
1013 .type_args_typed([TypeTag::U64, TypeTag::Bool])
1014 .build()
1015 .expect("build should succeed"),
1016 );
1017 assert_eq!(entry_fn.type_args, vec![TypeTag::U64, TypeTag::Bool]);
1018 }
1019
1020 #[test]
1021 fn test_input_entry_function_data_arg() {
1022 let entry_fn = payload_as_entry_function(
1023 InputEntryFunctionData::new("0x1::coin::transfer")
1024 .arg(42u64)
1025 .arg(true)
1026 .arg("hello".to_string())
1027 .build()
1028 .expect("build should succeed"),
1029 );
1030 assert_eq!(entry_fn.args.len(), 3, "all three args must be present");
1031 assert_eq!(entry_fn.args[0][0], 42);
1033 assert_eq!(entry_fn.args[1], vec![0x01]);
1035 }
1036
1037 #[test]
1038 fn test_input_entry_function_data_arg_raw() {
1039 let raw_bytes = vec![0x01, 0x02, 0x03];
1040 let entry_fn = payload_as_entry_function(
1041 InputEntryFunctionData::new("0x1::coin::transfer")
1042 .arg_raw(raw_bytes.clone())
1043 .build()
1044 .expect("build should succeed"),
1045 );
1046 assert_eq!(entry_fn.args.len(), 1);
1047 assert_eq!(entry_fn.args[0], raw_bytes);
1048 }
1049
1050 #[test]
1051 fn test_input_entry_function_data_args() {
1052 let entry_fn = payload_as_entry_function(
1053 InputEntryFunctionData::new("0x1::coin::transfer")
1054 .args([1u64, 2u64, 3u64])
1055 .build()
1056 .expect("build should succeed"),
1057 );
1058 assert_eq!(entry_fn.args.len(), 3);
1059 assert_eq!(entry_fn.args[0][0], 1);
1060 assert_eq!(entry_fn.args[1][0], 2);
1061 assert_eq!(entry_fn.args[2][0], 3);
1062 }
1063
1064 #[test]
1065 fn test_input_entry_function_data_transfer_apt() {
1066 use crate::types::AccountAddress;
1067
1068 let recipient = AccountAddress::from_hex("0x123").unwrap();
1069 let entry_fn = payload_as_entry_function(
1070 InputEntryFunctionData::transfer_apt(recipient, 1000)
1071 .expect("transfer_apt should succeed"),
1072 );
1073 assert_eq!(entry_fn.module.address, AccountAddress::ONE);
1074 assert_eq!(entry_fn.module.name.as_str(), "aptos_account");
1075 assert_eq!(entry_fn.function, "transfer");
1076 assert_eq!(entry_fn.args.len(), 2);
1077 }
1078
1079 #[test]
1080 fn test_input_entry_function_data_builder_debug() {
1081 let builder = InputEntryFunctionData::new("0x1::coin::transfer");
1082 let debug = format!("{builder:?}");
1083 assert!(debug.contains("InputEntryFunctionDataBuilder"));
1084 }
1085
1086 #[test]
1087 fn test_input_entry_function_data_builder_clone() {
1088 let builder = InputEntryFunctionData::new("0x1::coin::transfer").arg(42u64);
1089 let cloned = builder.clone();
1090 let original_built = payload_as_entry_function(builder.build().expect("original builds"));
1091 let cloned_built = payload_as_entry_function(cloned.build().expect("clone builds"));
1092 assert_eq!(original_built.module.name, cloned_built.module.name);
1094 assert_eq!(original_built.function, cloned_built.function);
1095 assert_eq!(original_built.args, cloned_built.args);
1096 }
1097
1098 #[test]
1099 fn test_move_u256_debug() {
1100 let val = MoveU256::from_u128(123_456_789);
1101 let debug = format!("{val:?}");
1102 assert!(debug.contains("MoveU256"));
1103 }
1104
1105 #[test]
1106 fn test_move_i128_debug() {
1107 let val = MoveI128::new(-42);
1108 let debug = format!("{val:?}");
1109 assert!(debug.contains("MoveI128"));
1110 }
1111
1112 #[test]
1113 fn test_move_i256_debug() {
1114 let val = MoveI256::from_i128(-42);
1115 let debug = format!("{val:?}");
1116 assert!(debug.contains("MoveI256"));
1117 }
1118
1119 #[test]
1120 fn test_move_u256_equality() {
1121 let val1 = MoveU256::from_u128(100);
1122 let val2 = MoveU256::from_u128(100);
1123 let val3 = MoveU256::from_u128(200);
1124 assert_eq!(val1, val2);
1125 assert_ne!(val1, val3);
1126 }
1127
1128 #[test]
1129 fn test_move_i256_equality() {
1130 let val1 = MoveI256::from_i128(-50);
1131 let val2 = MoveI256::from_i128(-50);
1132 let val3 = MoveI256::from_i128(50);
1133 assert_eq!(val1, val2);
1134 assert_ne!(val1, val3);
1135 }
1136
1137 #[test]
1138 fn test_move_u256_clone() {
1139 let val1 = MoveU256::from_u128(999);
1140 let val2 = val1;
1141 assert_eq!(val1, val2);
1142 }
1143
1144 #[test]
1145 fn test_move_i256_clone() {
1146 let val1 = MoveI256::from_i128(-999);
1147 let val2 = val1;
1148 assert_eq!(val1, val2);
1149 }
1150}