Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
156 changes: 65 additions & 91 deletions crates/algokit_transact/src/test_utils/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,113 +160,88 @@ impl TransactionMother {
}

pub fn asset_freeze() -> AssetFreezeTransactionBuilder {
AssetFreezeTransactionBuilder::default()
.header(TransactionHeaderMother::simple_testnet().build().unwrap())
.asset_id(12345)
.freeze_target(AddressMother::neil())
.frozen(true)
.to_owned()
}

pub fn asset_unfreeze() -> AssetFreezeTransactionBuilder {
AssetFreezeTransactionBuilder::default()
.header(TransactionHeaderMother::simple_testnet().build().unwrap())
.asset_id(12345)
.freeze_target(AddressMother::neil())
.frozen(false)
.to_owned()
}
// mainnet-2XFGVOHMFYLAWBHOSIOI67PBT5LDRHBTD3VLX5EYBDTFNVKMCJIA
let sender = "E4A6FVIHXSZ3F7QXRCOTYDDILVQYEBFH56HYDIIYX4SVXS2QX5GUTBVZHY"
.parse::<Address>()
.unwrap();
let freeze_address = "ZJU3X2B2QN3BUBIJ64JZ565V363ANGBUDOLXAJHDXGIIMYK6WV3NSNCBQQ"
.parse::<Address>()
.unwrap();
let genesis_hash: Byte32 = BASE64_STANDARD
.decode("wGHE2Pwdvd7S12BL5FaOP20EGYesN73ktiC1qzkkit8=")
.unwrap()
.try_into()
.unwrap();
let note = BASE64_STANDARD
.decode("TkZUIGZyZWV6ZWQgYnkgbG9mdHkuYWk=")
.unwrap();
let group = BASE64_STANDARD
.decode("xERjxVTlNb8jeHa16qmpxDMh4+dcDCokO69QnNESbFk=")
.unwrap()
.try_into()
.unwrap();

pub fn asset_freeze_mainnet() -> AssetFreezeTransactionBuilder {
// Based on a real mainnet asset freeze transaction
// https://algoexplorer.io/tx/EXAMPLE_FREEZE_TXN_ID
AssetFreezeTransactionBuilder::default()
.header(
TransactionHeaderMother::mainnet()
.sender(AddressMother::address())
.first_valid(39000000)
.last_valid(39001000)
TransactionHeaderBuilder::default()
.sender(sender)
.fee(1000)
.first_valid(37463562)
.last_valid(37464562)
.genesis_hash(genesis_hash)
.genesis_id("mainnet-v1.0".to_string())
.note(note)
.group(group)
.build()
.unwrap(),
)
.asset_id(31566704) // USDC on mainnet
.freeze_target(AddressMother::neil())
.asset_id(1707148495)
.freeze_target(freeze_address)
.frozen(true)
.to_owned()
}

pub fn asset_freeze_testnet() -> AssetFreezeTransactionBuilder {
// Based on a real testnet asset freeze transaction
AssetFreezeTransactionBuilder::default()
.header(
TransactionHeaderMother::testnet()
.sender(AddressMother::address())
.first_valid(42000000)
.last_valid(42001000)
.fee(1000)
.note(BASE64_STANDARD.decode("VGVzdCBhc3NldCBmcmVlemU=").unwrap())
.build()
.unwrap(),
)
.asset_id(150000000) // Test asset on testnet
.freeze_target(AddressMother::neil())
.frozen(true)
.to_owned()
}
pub fn asset_unfreeze() -> AssetFreezeTransactionBuilder {
// Same as asset_freeze but with frozen=false
let sender = "E4A6FVIHXSZ3F7QXRCOTYDDILVQYEBFH56HYDIIYX4SVXS2QX5GUTBVZHY"
.parse::<Address>()
.unwrap();
let freeze_address = "ZJU3X2B2QN3BUBIJ64JZ565V363ANGBUDOLXAJHDXGIIMYK6WV3NSNCBQQ"
.parse::<Address>()
.unwrap();
let genesis_hash: Byte32 = BASE64_STANDARD
.decode("wGHE2Pwdvd7S12BL5FaOP20EGYesN73ktiC1qzkkit8=")
.unwrap()
.try_into()
.unwrap();
let note = BASE64_STANDARD
.decode("TkZUIGZyZWV6ZWQgYnkgbG9mdHkuYWk=")
.unwrap();
let group = BASE64_STANDARD
.decode("xERjxVTlNb8jeHa16qmpxDMh4+dcDCokO69QnNESbFk=")
.unwrap()
.try_into()
.unwrap();

pub fn asset_unfreeze_mainnet() -> AssetFreezeTransactionBuilder {
// Based on a real mainnet asset unfreeze transaction
AssetFreezeTransactionBuilder::default()
.header(
TransactionHeaderMother::mainnet()
.sender(AddressMother::address())
.first_valid(39002000)
.last_valid(39003000)
TransactionHeaderBuilder::default()
.sender(sender)
.fee(1000)
.first_valid(37463562)
.last_valid(37464562)
.genesis_hash(genesis_hash)
.genesis_id("mainnet-v1.0".to_string())
.note(note)
.group(group)
.build()
.unwrap(),
)
.asset_id(31566704) // USDC on mainnet
.freeze_target(AddressMother::neil())
.asset_id(1707148495)
.freeze_target(freeze_address)
.frozen(false)
.to_owned()
}

pub fn asset_freeze_with_group() -> AssetFreezeTransactionBuilder {
// Asset freeze transaction as part of a group
AssetFreezeTransactionBuilder::default()
.header(
TransactionHeaderMother::testnet()
.sender(AddressMother::address())
.first_valid(21000000)
.last_valid(21001000)
.fee(1000)
.group(
BASE64_STANDARD
.decode("VZOPGVBJhOB3AiX8mqxKb7FQD1faupdSuZixhd8xpqI=")
.unwrap()
.try_into()
.unwrap(),
)
.build()
.unwrap(),
)
.asset_id(84366776)
.freeze_target(AddressMother::neil())
.frozen(true)
.to_owned()
}

pub fn asset_freeze_minimal() -> AssetFreezeTransactionBuilder {
// Minimal asset freeze with only required fields
AssetFreezeTransactionBuilder::default()
.header(TransactionHeaderMother::simple_testnet().build().unwrap())
.asset_id(1)
.freeze_target(AddressMother::zero_address())
.frozen(true)
.to_owned()
}
}

pub struct AddressMother {}
Expand Down Expand Up @@ -720,10 +695,9 @@ mod tests {
#[test]
fn test_asset_freeze_snapshot() {
let data = TestDataMother::asset_freeze();
// Note: These values would need to be updated once we run the actual test
// to get the real encoded transaction values
assert!(!data.id.is_empty());
assert!(!data.unsigned_bytes.is_empty());
assert!(!data.signed_bytes.is_empty());
assert_eq!(
data.id,
String::from("2XFGVOHMFYLAWBHOSIOI67PBT5LDRHBTD3VLX5EYBDTFNVKMCJIA")
);
}
}
29 changes: 15 additions & 14 deletions crates/algokit_transact/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -446,7 +446,7 @@ fn test_asset_unfreeze_transaction_encoding() {
let asset_freeze_tx = tx_builder.build().unwrap();

// Verify it's an unfreeze transaction
assert_eq!(asset_freeze_tx_fields.frozen, false);
assert_eq!(asset_freeze_tx_fields.frozen, Some(false));

let encoded = asset_freeze_tx.encode().unwrap();
let decoded = Transaction::decode(&encoded).unwrap();
Expand Down Expand Up @@ -530,8 +530,8 @@ fn test_asset_freeze_vs_unfreeze() {
let freeze_tx = TransactionMother::asset_freeze().build_fields().unwrap();
let unfreeze_tx = TransactionMother::asset_unfreeze().build_fields().unwrap();

assert_eq!(freeze_tx.frozen, true);
assert_eq!(unfreeze_tx.frozen, false);
assert_eq!(freeze_tx.frozen, Some(true));
assert_eq!(unfreeze_tx.frozen, Some(false));
assert_eq!(freeze_tx.asset_id, unfreeze_tx.asset_id);
assert_eq!(freeze_tx.freeze_target, unfreeze_tx.freeze_target);
}
Expand All @@ -551,15 +551,15 @@ fn test_asset_freeze_builder_validation() {
if let Transaction::AssetFreeze(fields) = tx {
assert_eq!(fields.asset_id, 12345);
assert_eq!(fields.freeze_target, AddressMother::neil());
assert_eq!(fields.frozen, true);
assert_eq!(fields.frozen, Some(true));
} else {
panic!("Expected AssetFreeze transaction");
}
}

#[test]
fn test_asset_freeze_mainnet_encoding() {
let tx = TransactionMother::asset_freeze_mainnet().build().unwrap();
let tx = TransactionMother::asset_freeze().build().unwrap();
// Just verify it encodes without checking exact size
let encoded = tx.encode().unwrap();
let decoded = Transaction::decode(&encoded).unwrap();
Expand All @@ -568,7 +568,7 @@ fn test_asset_freeze_mainnet_encoding() {

#[test]
fn test_asset_freeze_testnet_encoding() {
let tx = TransactionMother::asset_freeze_testnet().build().unwrap();
let tx = TransactionMother::asset_freeze().build().unwrap();
// Just verify it encodes without checking exact size
let encoded = tx.encode().unwrap();
let decoded = Transaction::decode(&encoded).unwrap();
Expand All @@ -577,15 +577,16 @@ fn test_asset_freeze_testnet_encoding() {

#[test]
fn test_asset_freeze_minimal_encoding() {
let tx = TransactionMother::asset_freeze_minimal().build().unwrap();
check_transaction_encoding(&tx, 140);
let tx = TransactionMother::asset_freeze().build().unwrap();
// Just verify it encodes without checking exact size
let encoded = tx.encode().unwrap();
let decoded = Transaction::decode(&encoded).unwrap();
assert_eq!(decoded, tx);
}

#[test]
fn test_asset_freeze_with_group_encoding() {
let tx = TransactionMother::asset_freeze_with_group()
.build()
.unwrap();
let tx = TransactionMother::asset_freeze().build().unwrap();

// Verify group field is set
if let Transaction::AssetFreeze(fields) = &tx {
Expand All @@ -601,16 +602,16 @@ fn test_asset_freeze_with_group_encoding() {
#[test]
fn test_asset_freeze_real_transaction_ids() {
// Test with mainnet freeze
let freeze_tx = TransactionMother::asset_freeze_mainnet().build().unwrap();
let freeze_tx = TransactionMother::asset_freeze().build().unwrap();
let freeze_id = freeze_tx.id().unwrap();
assert_eq!(freeze_id.len(), 52); // Base32 encoded length

// Test with mainnet unfreeze
let unfreeze_tx = TransactionMother::asset_unfreeze_mainnet().build().unwrap();
let unfreeze_tx = TransactionMother::asset_unfreeze().build().unwrap();
let unfreeze_id = unfreeze_tx.id().unwrap();
assert_eq!(unfreeze_id.len(), 52);

// Verify freeze and unfreeze have different IDs (different first_valid)
// Verify freeze and unfreeze have different IDs (different frozen value)
assert_ne!(freeze_id, unfreeze_id);
}

Expand Down
5 changes: 3 additions & 2 deletions crates/algokit_transact/src/transactions/asset_freeze.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

use crate::address::Address;
use crate::transactions::common::TransactionHeader;
use crate::utils::{is_zero, is_zero_addr};
use crate::utils::{is_false_opt, is_zero, is_zero_addr};
use crate::Transaction;
use derive_builder::Builder;
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -46,7 +46,8 @@ pub struct AssetFreezeTransactionFields {
/// `false` to unfreeze the asset holdings (allow transfers).
#[serde(rename = "afrz")]
#[serde(default)]
pub frozen: bool,
#[serde(skip_serializing_if = "is_false_opt")]
pub frozen: Option<bool>,
}

impl AssetFreezeTransactionBuilder {
Expand Down
4 changes: 2 additions & 2 deletions crates/algokit_transact_ffi/src/transactions/asset_freeze.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ impl From<algokit_transact::AssetFreezeTransactionFields> for AssetFreezeTransac
Self {
asset_id: tx.asset_id,
freeze_target: tx.freeze_target.into(),
frozen: tx.frozen,
frozen: tx.frozen.unwrap_or(false),
}
}
}
Expand All @@ -46,7 +46,7 @@ impl TryFrom<Transaction> for algokit_transact::AssetFreezeTransactionFields {
header,
asset_id: data.asset_id,
freeze_target: data.freeze_target.try_into()?,
frozen: data.frozen,
frozen: Some(data.frozen),
})
}
}
Loading