diff --git a/.github/workflows/android_ci.yml b/.github/workflows/android_ci.yml new file mode 100644 index 000000000..3172189c2 --- /dev/null +++ b/.github/workflows/android_ci.yml @@ -0,0 +1,76 @@ +name: Android CI + +on: + workflow_dispatch: + push: + branches: + - main + pull_request: + branches: + - main + +jobs: + android: + runs-on: ubuntu-latest + steps: + - name: Checkout Code + uses: actions/checkout@v5 + + - name: Set up JDK 21 + uses: actions/setup-java@v4 + with: + distribution: 'temurin' + java-version: '21' + + - uses: dtolnay/rust-toolchain@master + with: + toolchain: 1.85.0 + targets: aarch64-linux-android, arm-linux-androideabi, armv7-linux-androideabi, i686-linux-android, thumbv7neon-linux-androideabi, x86_64-linux-android + + - name: Install Cargo-NDK + run: cargo install cargo-ndk@^3.5 + + - name: Install Android ndk + uses: nttld/setup-ndk@v1 + with: + ndk-version: r27d + + - name: Build AAR + run: cargo pkg transact aar + + - name: Host Test + working-directory: packages/android/algokit_transact + run: ./gradlew test + + - name: Enable KVM + run: | + echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules + sudo udevadm control --reload-rules + sudo udevadm trigger --name-match=kvm + + - name: Install emulator dependencies + run: sudo apt-get update && sudo apt-get install -y libx11-xcb1 libglu1-mesa + + - name: Free Disk Space (Ubuntu) + uses: AdityaGarg8/remove-unwanted-software@v5 + with: + remove-dotnet: true + remove-haskell: true + remove-codeql: true + remove-docker-images: true + remove-large-packages: true + + - name: Android Test + uses: reactivecircus/android-emulator-runner@v2 + with: + api-level: 34 + arch: x86_64 + script: ./gradlew connectedAndroidTest + working-directory: packages/android/algokit_transact + + - name: Archive Build Output + uses: actions/upload-artifact@v4 + if: github.event_name == 'push' || github.event_name == 'workflow_dispatch' + with: + name: algokit_transact.aar + path: packages/android/algokit_transact/build/outputs/aar/algokit_transact-release.aar diff --git a/.gitignore b/.gitignore index 3fc493b60..453f9f9e3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,7 @@ /target +*.dylib +*.a +*.so .zed/ .venv/ crates/**/dist/ @@ -7,9 +10,18 @@ node_modules/ .dmypy.json .build .bin/ +.vscode/ .DS_Store +*.idea wheelhouse/ +# Android/Kotlin +.gradle/ +build/ +*.iml +local.properties +gradle-wrapper.jar + # Insta snapshot testing *.snap.new *.pending-snap @@ -22,6 +34,7 @@ AGENTS.md .opencode/ .references/ .kiro/ +.kotlin/ packages/python/**/*algokit_*.py packages/python**/*.dll diff --git a/README.md b/README.md index fc8f34091..0fdb528d8 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,12 @@ The exported interfaces should be purely functional without any state owned by R ## Contributing +## Build Scripts + +`cargo pkg` will run the build script. For example: `cargo pkg transact kt` builds `algokit_transact` for `kotlin`. + +The scripts are defined in [tools/build_pkgs] for each language. + ### Learning Resources If you are new to Rust or UniFFI, check out the [learning resources document](./docs/contributing/learning_resources.md) diff --git a/crates/algokit_transact/src/address.rs b/crates/algokit_transact/src/address.rs index a5fff1809..ad7655bef 100644 --- a/crates/algokit_transact/src/address.rs +++ b/crates/algokit_transact/src/address.rs @@ -65,12 +65,12 @@ impl FromStr for Address { fn from_str(s: &str) -> Result { if s.len() != ALGORAND_ADDRESS_LENGTH { return Err(AlgoKitTransactError::InvalidAddress { - message: "Algorand address must be exactly 58 characters".into(), + err_msg: "Algorand address must be exactly 58 characters".into(), }); } let decoded_address = base32::decode(base32::Alphabet::Rfc4648 { padding: false }, s) .ok_or_else(|| AlgoKitTransactError::InvalidAddress { - message: "Invalid base32 encoding for Algorand address".into(), + err_msg: "Invalid base32 encoding for Algorand address".into(), })?; // Although this is called public key (and it actually is when the account is a `KeyPairAccount`), @@ -80,18 +80,18 @@ impl FromStr for Address { [..ALGORAND_PUBLIC_KEY_BYTE_LENGTH] .try_into() .map_err(|_| AlgoKitTransactError::InvalidAddress { - message: "Could not decode address into 32-byte public key".to_string(), + err_msg: "Could not decode address into 32-byte public key".to_string(), })?; let checksum: [u8; ALGORAND_CHECKSUM_BYTE_LENGTH] = decoded_address [ALGORAND_PUBLIC_KEY_BYTE_LENGTH..] .try_into() .map_err(|_| AlgoKitTransactError::InvalidAddress { - message: "Could not get 4-byte checksum from decoded address".to_string(), + err_msg: "Could not get 4-byte checksum from decoded address".to_string(), })?; if pub_key_to_checksum(&pub_key) != checksum { return Err(AlgoKitTransactError::InvalidAddress { - message: "Checksum is invalid".to_string(), + err_msg: "Checksum is invalid".to_string(), }); } Ok(Address(pub_key)) diff --git a/crates/algokit_transact/src/error.rs b/crates/algokit_transact/src/error.rs index f69db83b7..b838d695f 100644 --- a/crates/algokit_transact/src/error.rs +++ b/crates/algokit_transact/src/error.rs @@ -24,17 +24,17 @@ pub enum AlgoKitTransactError { #[snafu(display("Error ocurred during msgpack decoding: {source}"))] MsgpackDecodingError { source: rmpv::decode::Error }, - #[snafu(display("Unknown transaction type: {message}"))] - UnknownTransactionType { message: String }, + #[snafu(display("Unknown transaction type: {err_msg}"))] + UnknownTransactionType { err_msg: String }, - #[snafu(display("{message}"))] - InputError { message: String }, + #[snafu(display("{err_msg}"))] + InputError { err_msg: String }, - #[snafu(display("{message}"))] - InvalidAddress { message: String }, + #[snafu(display("{err_msg}"))] + InvalidAddress { err_msg: String }, - #[snafu(display("Invalid multisig signature: {message}"))] - InvalidMultisigSignature { message: String }, + #[snafu(display("Invalid multisig signature: {err_msg}"))] + InvalidMultisigSignature { err_msg: String }, } impl From for AlgoKitTransactError { diff --git a/crates/algokit_transact/src/multisig.rs b/crates/algokit_transact/src/multisig.rs index 04ece0fba..b02f6fdc7 100644 --- a/crates/algokit_transact/src/multisig.rs +++ b/crates/algokit_transact/src/multisig.rs @@ -78,16 +78,16 @@ impl MultisigSignature { ) -> Result { if version == 0 { return Err(AlgoKitTransactError::InvalidMultisigSignature { - message: "Version cannot be zero".to_string(), + err_msg: "Version cannot be zero".to_string(), }); } if subsignatures.is_empty() { return Err(AlgoKitTransactError::InvalidMultisigSignature { - message: "Subsignatures cannot be empty".to_string(), + err_msg: "Subsignatures cannot be empty".to_string(), }); } if threshold == 0 || threshold as usize > subsignatures.len() { - return Err(AlgoKitTransactError::InvalidMultisigSignature { message: "Threshold must be greater than zero and less than or equal to the number of sub-signers".to_string() }); + return Err(AlgoKitTransactError::InvalidMultisigSignature { err_msg:"Threshold must be greater than zero and less than or equal to the number of sub-signers".to_string() }); } Ok(Self { version, @@ -138,7 +138,7 @@ impl MultisigSignature { } if !found { return Err(AlgoKitTransactError::InvalidMultisigSignature { - message: "Address not found in multisig signature".to_string(), + err_msg: "Address not found in multisig signature".to_string(), }); } @@ -161,17 +161,17 @@ impl MultisigSignature { pub fn merge(&self, other: &Self) -> Result { if self.version != other.version { return Err(AlgoKitTransactError::InvalidMultisigSignature { - message: "Cannot merge multisig signatures with different versions".to_string(), + err_msg: "Cannot merge multisig signatures with different versions".to_string(), }); } if self.threshold != other.threshold { return Err(AlgoKitTransactError::InvalidMultisigSignature { - message: "Cannot merge multisig signatures with different thresholds".to_string(), + err_msg: "Cannot merge multisig signatures with different thresholds".to_string(), }); } if self.participants() != other.participants() { return Err(AlgoKitTransactError::InvalidMultisigSignature { - message: "Cannot merge multisig signatures with different participants".to_string(), + err_msg: "Cannot merge multisig signatures with different participants".to_string(), }); } diff --git a/crates/algokit_transact/src/traits.rs b/crates/algokit_transact/src/traits.rs index 9d278cfc4..08e9dd637 100644 --- a/crates/algokit_transact/src/traits.rs +++ b/crates/algokit_transact/src/traits.rs @@ -63,7 +63,7 @@ pub trait AlgorandMsgpack: Serialize + for<'de> Deserialize<'de> { fn decode(bytes: &[u8]) -> Result { if bytes.is_empty() { return Err(AlgoKitTransactError::InputError { - message: "attempted to decode 0 bytes".to_string(), + err_msg: "attempted to decode 0 bytes".to_string(), }); } diff --git a/crates/algokit_transact/src/transactions/mod.rs b/crates/algokit_transact/src/transactions/mod.rs index cd3370f17..1969f3fd5 100644 --- a/crates/algokit_transact/src/transactions/mod.rs +++ b/crates/algokit_transact/src/transactions/mod.rs @@ -138,7 +138,7 @@ impl Transaction { if let Some(max_fee) = request.max_fee { if calculated_fee > max_fee { return Err(AlgoKitTransactError::InputError { - message: format!( + err_msg: format!( "Transaction fee {} µALGO is greater than max fee {} µALGO", calculated_fee, max_fee ), @@ -230,7 +230,7 @@ impl AlgorandMsgpack for SignedTransaction { Ok(stxn) } _ => Err(AlgoKitTransactError::InputError { - message: format!( + err_msg: format!( "expected signed transaction to be a map, but got a: {:#?}", value.type_id() ), diff --git a/crates/algokit_transact/src/transactions/payment.rs b/crates/algokit_transact/src/transactions/payment.rs index ae38a5b4b..7572e7221 100644 --- a/crates/algokit_transact/src/transactions/payment.rs +++ b/crates/algokit_transact/src/transactions/payment.rs @@ -150,7 +150,7 @@ mod tests { let msg = format!("{}", err); assert!( msg == "Transaction fee 2470 µALGO is greater than max fee 1000 µALGO", - "Unexpected error message: {}", + "Unexpected error err_msg:{}", msg ); } diff --git a/crates/algokit_transact/src/utils.rs b/crates/algokit_transact/src/utils.rs index 7d2aa0fb9..e1bce3357 100644 --- a/crates/algokit_transact/src/utils.rs +++ b/crates/algokit_transact/src/utils.rs @@ -32,7 +32,7 @@ pub fn sort_msgpack_value(value: rmpv::Value) -> Result binary_entries.push((bytes, sorted_v)), _ => { return Err(AlgoKitTransactError::InputError { - message: "Unsupported MessagePack map key type; only integer, string, and binary keys are supported".to_string(), + err_msg: "Unsupported MessagePack map key type; only integer, string, and binary keys are supported".to_string(), }) } } @@ -286,13 +286,13 @@ pub fn hash(bytes: &Vec) -> Byte32 { pub fn compute_group(txs: &[Transaction]) -> Result { if txs.is_empty() { return Err(AlgoKitTransactError::InputError { - message: String::from("Transaction group size cannot be 0"), + err_msg: String::from("Transaction group size cannot be 0"), }); } if txs.len() > MAX_TX_GROUP_SIZE { return Err(AlgoKitTransactError::InputError { - message: format!( + err_msg: format!( "Transaction group size exceeds the max limit of {}", MAX_TX_GROUP_SIZE ), @@ -304,7 +304,7 @@ pub fn compute_group(txs: &[Transaction]) -> Result for AlgoKitTransactError { match e { algokit_transact::AlgoKitTransactError::DecodingError { .. } => { AlgoKitTransactError::DecodingError { - message: e.to_string(), + error_msg: e.to_string(), } } algokit_transact::AlgoKitTransactError::EncodingError { .. } => { AlgoKitTransactError::EncodingError { - message: e.to_string(), + error_msg: e.to_string(), } } algokit_transact::AlgoKitTransactError::MsgpackDecodingError { .. } => { AlgoKitTransactError::DecodingError { - message: e.to_string(), + error_msg: e.to_string(), } } algokit_transact::AlgoKitTransactError::MsgpackEncodingError { .. } => { AlgoKitTransactError::EncodingError { - message: e.to_string(), + error_msg: e.to_string(), } } algokit_transact::AlgoKitTransactError::UnknownTransactionType { .. } => { AlgoKitTransactError::DecodingError { - message: e.to_string(), + error_msg: e.to_string(), } } - algokit_transact::AlgoKitTransactError::InputError { message } => { - AlgoKitTransactError::InputError { message } + algokit_transact::AlgoKitTransactError::InputError { err_msg: message } => { + AlgoKitTransactError::InputError { error_msg: message } } algokit_transact::AlgoKitTransactError::InvalidAddress { .. } => { AlgoKitTransactError::DecodingError { - message: e.to_string(), + error_msg: e.to_string(), } } algokit_transact::AlgoKitTransactError::InvalidMultisigSignature { .. } => { AlgoKitTransactError::DecodingError { - message: e.to_string(), + error_msg: e.to_string(), } } } @@ -122,7 +122,7 @@ impl TryFrom for algokit_transact::KeyPairAccount { let pub_key: [u8; ALGORAND_PUBLIC_KEY_BYTE_LENGTH] = vec_to_array(&value.pub_key, "public key").map_err(|e| { AlgoKitTransactError::DecodingError { - message: format!("Error while decoding a public key: {}", e), + error_msg: format!("Error while decoding a public key: {}", e), } })?; @@ -222,7 +222,7 @@ impl TryFrom for algokit_transact::Transaction { > 1 { return Err(Self::Error::DecodingError { - message: "Multiple transaction type specific fields set".to_string(), + error_msg: "Multiple transaction type specific fields set".to_string(), }); } @@ -449,7 +449,7 @@ impl TryFrom for algokit_transact::SignedTransaction { .map(|sig| vec_to_array(&sig, "signature")) .transpose() .map_err(|e| AlgoKitTransactError::DecodingError { - message: format!( + error_msg: format!( "Error while decoding the signature in a signed transaction: {}", e ), @@ -473,7 +473,7 @@ fn vec_to_array( buf.to_vec() .try_into() .map_err(|_| AlgoKitTransactError::DecodingError { - message: format!( + error_msg: format!( "Expected {} {} bytes but got {} bytes", context, N, @@ -606,7 +606,7 @@ pub fn estimate_transaction_size(transaction: Transaction) -> Result Result for algokit_transact::MultisigSubsignature { .map(|sig| vec_to_array(&sig, "signature")) .transpose() .map_err(|e| AlgoKitTransactError::DecodingError { - message: format!("Error while decoding a subsignature: {}", e), + error_msg: format!("Error while decoding a subsignature: {}", e), })?, }) } @@ -143,7 +143,7 @@ pub fn apply_multisig_subsignature( subsignature .try_into() .map_err(|_| AlgoKitTransactError::EncodingError { - message: format!( + error_msg: format!( "signature should be {} bytes", ALGORAND_SIGNATURE_BYTE_LENGTH ), diff --git a/crates/algokit_transact_ffi/src/transactions/app_call.rs b/crates/algokit_transact_ffi/src/transactions/app_call.rs index e1dae834e..104e49ff9 100644 --- a/crates/algokit_transact_ffi/src/transactions/app_call.rs +++ b/crates/algokit_transact_ffi/src/transactions/app_call.rs @@ -99,7 +99,7 @@ impl TryFrom for algokit_transact::AppCallTransactionFields { fn try_from(tx: Transaction) -> Result { if tx.transaction_type != TransactionType::AppCall || tx.app_call.is_none() { return Err(Self::Error::DecodingError { - message: "AppCall call data missing".to_string(), + error_msg: "AppCall call data missing".to_string(), }); } @@ -135,7 +135,7 @@ impl TryFrom for algokit_transact::AppCallTransactionFields { transaction_fields .validate() .map_err(|errors| AlgoKitTransactError::DecodingError { - message: format!("App call validation failed: {}", errors.join("\n")), + error_msg: format!("App call validation failed: {}", errors.join("\n")), })?; Ok(transaction_fields) diff --git a/crates/algokit_transact_ffi/src/transactions/asset_config.rs b/crates/algokit_transact_ffi/src/transactions/asset_config.rs index 9ecd5c4ac..a6fdf36dc 100644 --- a/crates/algokit_transact_ffi/src/transactions/asset_config.rs +++ b/crates/algokit_transact_ffi/src/transactions/asset_config.rs @@ -139,7 +139,7 @@ impl TryFrom for algokit_transact::AssetConfigTransactionFields { fn try_from(tx: Transaction) -> Result { if tx.transaction_type != TransactionType::AssetConfig || tx.asset_config.is_none() { return Err(Self::Error::DecodingError { - message: "Asset configuration data missing".to_string(), + error_msg: "Asset configuration data missing".to_string(), }); } @@ -170,7 +170,7 @@ impl TryFrom for algokit_transact::AssetConfigTransactionFields { transaction_fields .validate() .map_err(|errors| AlgoKitTransactError::DecodingError { - message: format!("Asset config validation failed: {}", errors.join("\n")), + error_msg: format!("Asset config validation failed: {}", errors.join("\n")), })?; Ok(transaction_fields) diff --git a/crates/algokit_transact_ffi/src/transactions/asset_freeze.rs b/crates/algokit_transact_ffi/src/transactions/asset_freeze.rs index 8dca3f1f5..449039684 100644 --- a/crates/algokit_transact_ffi/src/transactions/asset_freeze.rs +++ b/crates/algokit_transact_ffi/src/transactions/asset_freeze.rs @@ -35,7 +35,7 @@ impl TryFrom for algokit_transact::AssetFreezeTransactionFields { fn try_from(tx: Transaction) -> Result { if tx.transaction_type != TransactionType::AssetFreeze || tx.asset_freeze.is_none() { return Err(Self::Error::DecodingError { - message: "Asset Freeze data missing".to_string(), + error_msg: "Asset Freeze data missing".to_string(), }); } @@ -52,7 +52,7 @@ impl TryFrom for algokit_transact::AssetFreezeTransactionFields { transaction_fields .validate() .map_err(|errors| AlgoKitTransactError::DecodingError { - message: format!("Asset freeze validation failed: {}", errors.join(", ")), + error_msg: format!("Asset freeze validation failed: {}", errors.join(", ")), })?; Ok(transaction_fields) diff --git a/crates/algokit_transact_ffi/src/transactions/asset_transfer.rs b/crates/algokit_transact_ffi/src/transactions/asset_transfer.rs index 4e5f7bbc3..3c82e7c2e 100644 --- a/crates/algokit_transact_ffi/src/transactions/asset_transfer.rs +++ b/crates/algokit_transact_ffi/src/transactions/asset_transfer.rs @@ -31,7 +31,7 @@ impl TryFrom for algokit_transact::AssetTransferTransactionFields { fn try_from(tx: Transaction) -> Result { if tx.transaction_type != TransactionType::AssetTransfer || tx.asset_transfer.is_none() { return Err(Self::Error::DecodingError { - message: "Asset Transfer data missing".to_string(), + error_msg: "Asset Transfer data missing".to_string(), }); } @@ -53,7 +53,7 @@ impl TryFrom for algokit_transact::AssetTransferTransactionFields { transaction_fields .validate() .map_err(|errors| AlgoKitTransactError::DecodingError { - message: format!("Asset transfer validation failed: {}", errors.join(", ")), + error_msg: format!("Asset transfer validation failed: {}", errors.join(", ")), })?; Ok(transaction_fields) diff --git a/crates/algokit_transact_ffi/src/transactions/heartbeat.rs b/crates/algokit_transact_ffi/src/transactions/heartbeat.rs index 0cb33238f..51b69e05c 100644 --- a/crates/algokit_transact_ffi/src/transactions/heartbeat.rs +++ b/crates/algokit_transact_ffi/src/transactions/heartbeat.rs @@ -70,7 +70,7 @@ impl TryFrom for algokit_transact::HeartbeatTransactionFields { fn try_from(tx: Transaction) -> Result { if tx.transaction_type != TransactionType::Heartbeat || tx.heartbeat.is_none() { return Err(Self::Error::DecodingError { - message: "Heartbeat transaction data missing".to_string(), + error_msg: "Heartbeat transaction data missing".to_string(), }); } diff --git a/crates/algokit_transact_ffi/src/transactions/key_registration.rs b/crates/algokit_transact_ffi/src/transactions/key_registration.rs index 33d2aea9c..af0bcc7de 100644 --- a/crates/algokit_transact_ffi/src/transactions/key_registration.rs +++ b/crates/algokit_transact_ffi/src/transactions/key_registration.rs @@ -50,7 +50,7 @@ impl TryFrom for algokit_transact::KeyRegistrationTransactio || tx.key_registration.is_none() { return Err(Self::Error::DecodingError { - message: "Key Registration data missing".to_string(), + error_msg: "Key Registration data missing".to_string(), }); } @@ -80,7 +80,7 @@ impl TryFrom for algokit_transact::KeyRegistrationTransactio transaction_fields .validate() .map_err(|errors| AlgoKitTransactError::DecodingError { - message: format!("Key registration validation failed: {}", errors.join("\n")), + error_msg: format!("Key registration validation failed: {}", errors.join("\n")), })?; Ok(transaction_fields) diff --git a/crates/algokit_transact_ffi/src/transactions/payment.rs b/crates/algokit_transact_ffi/src/transactions/payment.rs index 116f92e09..18310421c 100644 --- a/crates/algokit_transact_ffi/src/transactions/payment.rs +++ b/crates/algokit_transact_ffi/src/transactions/payment.rs @@ -25,7 +25,7 @@ impl TryFrom for algokit_transact::PaymentTransactionFields { fn try_from(tx: Transaction) -> Result { if tx.transaction_type != TransactionType::Payment || tx.payment.is_none() { return Err(Self::Error::DecodingError { - message: "Payment data missing".to_string(), + error_msg: "Payment data missing".to_string(), }); } diff --git a/crates/algokit_transact_ffi/src/transactions/state_proof.rs b/crates/algokit_transact_ffi/src/transactions/state_proof.rs index 5bb872afe..33d3a41f8 100644 --- a/crates/algokit_transact_ffi/src/transactions/state_proof.rs +++ b/crates/algokit_transact_ffi/src/transactions/state_proof.rs @@ -326,7 +326,7 @@ impl TryFrom for algokit_transact::StateProofTransactionFields { fn try_from(tx: Transaction) -> Result { if tx.transaction_type != TransactionType::StateProof || tx.state_proof.is_none() { return Err(Self::Error::DecodingError { - message: "State proof transaction data missing".to_string(), + error_msg: "State proof transaction data missing".to_string(), }); } diff --git a/packages/android/algokit_transact/.gitattributes b/packages/android/algokit_transact/.gitattributes new file mode 100644 index 000000000..f91f64602 --- /dev/null +++ b/packages/android/algokit_transact/.gitattributes @@ -0,0 +1,12 @@ +# +# https://help.github.com/articles/dealing-with-line-endings/ +# +# Linux start script should use lf +/gradlew text eol=lf + +# These are Windows script files and should use crlf +*.bat text eol=crlf + +# Binary files should be left untouched +*.jar binary + diff --git a/packages/android/algokit_transact/.gitignore b/packages/android/algokit_transact/.gitignore new file mode 100644 index 000000000..1b6985c00 --- /dev/null +++ b/packages/android/algokit_transact/.gitignore @@ -0,0 +1,5 @@ +# Ignore Gradle project-specific cache directory +.gradle + +# Ignore Gradle build output directory +build diff --git a/packages/android/algokit_transact/README.md b/packages/android/algokit_transact/README.md new file mode 100644 index 000000000..2dd27b948 --- /dev/null +++ b/packages/android/algokit_transact/README.md @@ -0,0 +1,43 @@ +# algokit_transact + +## Building + +```sh +cargo pkg transact kt +``` + +## Testing + +### Host + +```sh +./gradlew test +``` + +### Android + +First you need a connected android device. You can either use a physical device or start an emulator. + +To see available emulators: + +```sh +~/Library/Android/sdk/emulator/emulator -list-avds +``` + +Then start the emulator: + +```sh +~/Library/Android/sdk/emulator/emulator -avd +``` + +Or to start the first one: + +```sh +~/Library/Android/sdk/emulator/emulator -avd `~/Library/Android/sdk/emulator/emulator -list-avds | head -n 1` +``` + +Then run the tests: + +```sh +./gradlew connectedAndroidTest +``` diff --git a/packages/android/algokit_transact/build.gradle.kts b/packages/android/algokit_transact/build.gradle.kts new file mode 100644 index 000000000..4038d0791 --- /dev/null +++ b/packages/android/algokit_transact/build.gradle.kts @@ -0,0 +1,60 @@ +/* + * This file was generated by the Gradle 'init' task. + * + * This is a general purpose Gradle build. + * Learn more about Gradle by exploring our Samples at https://docs.gradle.org/8.14.2/samples + */ +plugins { + alias(libs.plugins.android.library) + alias(libs.plugins.kotlin.android) +} + +android { + namespace = "com.example.algokit_transact" + compileSdk = 36 + + defaultConfig { + minSdk = 28 + + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + consumerProguardFiles("consumer-rules.pro") + } + + buildTypes { + release { + isMinifyEnabled = false + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + "proguard-rules.pro" + ) + } + } + compileOptions { + sourceCompatibility = JavaVersion.VERSION_21 + targetCompatibility = JavaVersion.VERSION_21 + } + kotlinOptions { + jvmTarget = "21" + } + testOptions { + unitTests { + isIncludeAndroidResources = true + all { + it.systemProperty("jna.library.path", "src/test/resources") + } + } + } +} + +dependencies { + implementation("net.java.dev.jna:jna:5.14.0@aar") + // Use full JNA JAR for unit tests (includes native dispatch libraries) + testImplementation("net.java.dev.jna:jna:5.14.0") + + implementation(libs.androidx.core.ktx) + implementation(libs.androidx.appcompat) + implementation(libs.material) + testImplementation(libs.junit) + androidTestImplementation(libs.androidx.junit) + androidTestImplementation(libs.androidx.espresso.core) +} diff --git a/packages/android/algokit_transact/gradle.properties b/packages/android/algokit_transact/gradle.properties new file mode 100644 index 000000000..d5be73197 --- /dev/null +++ b/packages/android/algokit_transact/gradle.properties @@ -0,0 +1,7 @@ +# This file was generated by the Gradle 'init' task. +# https://docs.gradle.org/current/userguide/build_environment.html#sec:gradle_configuration_properties + +org.gradle.configuration-cache=true +android.useAndroidX=true +android.suppressUnsupportedCompileSdk=36 + diff --git a/packages/android/algokit_transact/gradle/libs.versions.toml b/packages/android/algokit_transact/gradle/libs.versions.toml new file mode 100644 index 000000000..6526d598b --- /dev/null +++ b/packages/android/algokit_transact/gradle/libs.versions.toml @@ -0,0 +1,40 @@ +[versions] +agp = "8.7.3" +kotlin = "2.0.21" +coreKtx = "1.16.0" +junit = "4.13.2" +junitVersion = "1.2.1" +espressoCore = "3.6.1" +appcompat = "1.7.0" +material = "1.12.0" +compose-bom = "2025.05.00" +compose-compiler = "2.0.21" +activity-compose = "1.10.1" +lifecycle-runtime-compose = "2.9.0" + +[libraries] +androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" } +junit = { group = "junit", name = "junit", version.ref = "junit" } +androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" } +androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" } +androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" } +material = { group = "com.google.android.material", name = "material", version.ref = "material" } + +# Compose dependencies +androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "compose-bom" } +androidx-compose-ui = { group = "androidx.compose.ui", name = "ui" } +androidx-compose-ui-graphics = { group = "androidx.compose.ui", name = "ui-graphics" } +androidx-compose-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-tooling-preview" } +androidx-compose-material3 = { group = "androidx.compose.material3", name = "material3" } +androidx-compose-ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling" } +androidx-compose-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" } +androidx-activity-compose = { group = "androidx.activity", name = "activity-compose", version.ref = "activity-compose" } +androidx-lifecycle-runtime-compose = { group = "androidx.lifecycle", name = "lifecycle-runtime-compose", version.ref = "lifecycle-runtime-compose" } + +[plugins] +android-application = { id = "com.android.application", version.ref = "agp" } +android-library = { id = "com.android.library", version.ref = "agp" } +kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } +compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" } + + diff --git a/packages/android/algokit_transact/gradle/wrapper/gradle-wrapper.jar b/packages/android/algokit_transact/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 000000000..1b33c55ba Binary files /dev/null and b/packages/android/algokit_transact/gradle/wrapper/gradle-wrapper.jar differ diff --git a/packages/android/algokit_transact/gradle/wrapper/gradle-wrapper.properties b/packages/android/algokit_transact/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 000000000..ff23a68d7 --- /dev/null +++ b/packages/android/algokit_transact/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,7 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.2-bin.zip +networkTimeout=10000 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/packages/android/algokit_transact/gradlew b/packages/android/algokit_transact/gradlew new file mode 100755 index 000000000..23d15a936 --- /dev/null +++ b/packages/android/algokit_transact/gradlew @@ -0,0 +1,251 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH="\\\"\\\"" + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/packages/android/algokit_transact/gradlew.bat b/packages/android/algokit_transact/gradlew.bat new file mode 100644 index 000000000..db3a6ac20 --- /dev/null +++ b/packages/android/algokit_transact/gradlew.bat @@ -0,0 +1,94 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH= + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/packages/android/algokit_transact/settings.gradle.kts b/packages/android/algokit_transact/settings.gradle.kts new file mode 100644 index 000000000..9f728e75a --- /dev/null +++ b/packages/android/algokit_transact/settings.gradle.kts @@ -0,0 +1,29 @@ +/* + * This file was generated by the Gradle 'init' task. + * + * The settings file is used to specify which projects to include in your build. + * For more detailed information on multi-project builds, please refer to https://docs.gradle.org/8.14.2/userguide/multi_project_builds.html in the Gradle documentation. + */ + +pluginManagement { + repositories { + google { + content { + includeGroupByRegex("com\\.android.*") + includeGroupByRegex("com\\.google.*") + includeGroupByRegex("androidx.*") + } + } + mavenCentral() + gradlePluginPortal() + } +} +dependencyResolutionManagement { + repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) + repositories { + google() + mavenCentral() + } +} + +rootProject.name = "algokit_transact" diff --git a/packages/android/algokit_transact/src/androidTest/kotlin/uniffi/algokit_transact_ffi/AddressConversionTest.kt b/packages/android/algokit_transact/src/androidTest/kotlin/uniffi/algokit_transact_ffi/AddressConversionTest.kt new file mode 100644 index 000000000..e7f74eb7a --- /dev/null +++ b/packages/android/algokit_transact/src/androidTest/kotlin/uniffi/algokit_transact_ffi/AddressConversionTest.kt @@ -0,0 +1,123 @@ +package uniffi.algokit_transact_ffi + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import org.junit.Test +import org.junit.Assert.* +import org.junit.Before +import org.junit.runner.RunWith + +/** + * Instrumented test suite for address conversion functions. + * + * Tests the bidirectional conversion between Algorand addresses and public keys. + * These tests run on an Android device or emulator and test against the actual AAR. + */ +@RunWith(AndroidJUnit4::class) +class AddressConversionTest { + + @Before + fun setup() { + // Ensure the FFI library is initialized before running tests + uniffiEnsureInitialized() + } + + @Test + fun testPublicKeyToAddressConversion() { + // Test converting a public key to an address + // This is a valid 32-byte public key (all zeros for simplicity) + val publicKey = ByteArray(32) { 0 } + + val address = addressFromPublicKey(publicKey) + + // Algorand addresses are 58 characters long (base32 encoded) + assertEquals(58, address.length) + // The address for a zero public key should be a specific value + assertEquals("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAY5HFKQ", address) + } + + @Test + fun testAddressToPublicKeyConversion() { + // Test converting an address back to a public key + val address = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAY5HFKQ" + + val publicKey = publicKeyFromAddress(address) + + // Public keys are 32 bytes + assertEquals(32, publicKey.size) + // Should be all zeros + assertTrue(publicKey.all { it == 0.toByte() }) + } + + @Test + fun testRoundTripConversion() { + // Test that converting public key -> address -> public key preserves the original value + val originalPublicKey = ByteArray(32) { it.toByte() } + + val address = addressFromPublicKey(originalPublicKey) + val recoveredPublicKey = publicKeyFromAddress(address) + + assertArrayEquals(originalPublicKey, recoveredPublicKey) + } + + @Test + fun testRealWorldAddress() { + // Test with a real Algorand address + val realAddress = "7ZUECA7HFLZTXENRV24SHLU4AVPUTMTTDUFUBNBD64C73F3UHRTHAIOF6Q" + + val publicKey = publicKeyFromAddress(realAddress) + val recoveredAddress = addressFromPublicKey(publicKey) + + assertEquals(realAddress, recoveredAddress) + assertEquals(32, publicKey.size) + } + + @Test(expected = AlgoKitTransactException.DecodingException::class) + fun testInvalidAddressFormat() { + // Test that an invalid address throws an exception + val invalidAddress = "INVALID" + + publicKeyFromAddress(invalidAddress) + } + + @Test(expected = AlgoKitTransactException.DecodingException::class) + fun testInvalidAddressChecksum() { + // Test that an address with an invalid checksum throws an exception + // This address has the right length but wrong checksum + val invalidAddress = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA5HFKQ" + + publicKeyFromAddress(invalidAddress) + } + + @Test(expected = AlgoKitTransactException.EncodingException::class) + fun testInvalidPublicKeyLength() { + // Test that a public key with wrong length throws an exception + val invalidPublicKey = ByteArray(16) { 0 } // Too short, should be 32 bytes + + addressFromPublicKey(invalidPublicKey) + } + + @Test + fun testPublicKeyAllOnes() { + // Test with a public key of all 1s + val publicKey = ByteArray(32) { 0xFF.toByte() } + + val address = addressFromPublicKey(publicKey) + val recoveredPublicKey = publicKeyFromAddress(address) + + assertArrayEquals(publicKey, recoveredPublicKey) + assertEquals(58, address.length) + } + + @Test + fun testPublicKeyPattern() { + // Test with a patterned public key (alternating bytes) + val publicKey = ByteArray(32) { i -> + if (i % 2 == 0) 0xAA.toByte() else 0x55.toByte() + } + + val address = addressFromPublicKey(publicKey) + val recoveredPublicKey = publicKeyFromAddress(address) + + assertArrayEquals(publicKey, recoveredPublicKey) + } +} diff --git a/packages/android/algokit_transact/src/main/kotlin/uniffi/algokit_transact_ffi/algokit_transact_ffi.kt b/packages/android/algokit_transact/src/main/kotlin/uniffi/algokit_transact_ffi/algokit_transact_ffi.kt new file mode 100644 index 000000000..b621dbf8e --- /dev/null +++ b/packages/android/algokit_transact/src/main/kotlin/uniffi/algokit_transact_ffi/algokit_transact_ffi.kt @@ -0,0 +1,4394 @@ +// This file was autogenerated by some hot garbage in the `uniffi` crate. +// Trust me, you don't want to mess with it! + +@file:Suppress("NAME_SHADOWING") + +package uniffi.algokit_transact_ffi + +// Common helper code. +// +// Ideally this would live in a separate .kt file where it can be unittested etc +// in isolation, and perhaps even published as a re-useable package. +// +// However, it's important that the details of how this helper code works (e.g. the +// way that different builtin types are passed across the FFI) exactly match what's +// expected by the Rust code on the other side of the interface. In practice right +// now that means coming from the exact some version of `uniffi` that was used to +// compile the Rust component. The easiest way to ensure this is to bundle the Kotlin +// helpers directly inline like we're doing here. + +import com.sun.jna.Library +import com.sun.jna.IntegerType +import com.sun.jna.Native +import com.sun.jna.Pointer +import com.sun.jna.Structure +import com.sun.jna.Callback +import com.sun.jna.ptr.* +import java.nio.ByteBuffer +import java.nio.ByteOrder +import java.nio.CharBuffer +import java.nio.charset.CodingErrorAction +import java.util.concurrent.atomic.AtomicLong +import java.util.concurrent.ConcurrentHashMap + +// This is a helper for safely working with byte buffers returned from the Rust code. +// A rust-owned buffer is represented by its capacity, its current length, and a +// pointer to the underlying data. + +/** + * @suppress + */ +@Structure.FieldOrder("capacity", "len", "data") +open class RustBuffer : Structure() { + // Note: `capacity` and `len` are actually `ULong` values, but JVM only supports signed values. + // When dealing with these fields, make sure to call `toULong()`. + @JvmField var capacity: Long = 0 + @JvmField var len: Long = 0 + @JvmField var data: Pointer? = null + + class ByValue: RustBuffer(), Structure.ByValue + class ByReference: RustBuffer(), Structure.ByReference + + internal fun setValue(other: RustBuffer) { + capacity = other.capacity + len = other.len + data = other.data + } + + companion object { + internal fun alloc(size: ULong = 0UL) = uniffiRustCall() { status -> + // Note: need to convert the size to a `Long` value to make this work with JVM. + UniffiLib.INSTANCE.ffi_algokit_transact_ffi_rustbuffer_alloc(size.toLong(), status) + }.also { + if(it.data == null) { + throw RuntimeException("RustBuffer.alloc() returned null data pointer (size=${size})") + } + } + + internal fun create(capacity: ULong, len: ULong, data: Pointer?): RustBuffer.ByValue { + var buf = RustBuffer.ByValue() + buf.capacity = capacity.toLong() + buf.len = len.toLong() + buf.data = data + return buf + } + + internal fun free(buf: RustBuffer.ByValue) = uniffiRustCall() { status -> + UniffiLib.INSTANCE.ffi_algokit_transact_ffi_rustbuffer_free(buf, status) + } + } + + @Suppress("TooGenericExceptionThrown") + fun asByteBuffer() = + this.data?.getByteBuffer(0, this.len.toLong())?.also { + it.order(ByteOrder.BIG_ENDIAN) + } +} + +/** + * The equivalent of the `*mut RustBuffer` type. + * Required for callbacks taking in an out pointer. + * + * Size is the sum of all values in the struct. + * + * @suppress + */ +class RustBufferByReference : ByReference(16) { + /** + * Set the pointed-to `RustBuffer` to the given value. + */ + fun setValue(value: RustBuffer.ByValue) { + // NOTE: The offsets are as they are in the C-like struct. + val pointer = getPointer() + pointer.setLong(0, value.capacity) + pointer.setLong(8, value.len) + pointer.setPointer(16, value.data) + } + + /** + * Get a `RustBuffer.ByValue` from this reference. + */ + fun getValue(): RustBuffer.ByValue { + val pointer = getPointer() + val value = RustBuffer.ByValue() + value.writeField("capacity", pointer.getLong(0)) + value.writeField("len", pointer.getLong(8)) + value.writeField("data", pointer.getLong(16)) + + return value + } +} + +// This is a helper for safely passing byte references into the rust code. +// It's not actually used at the moment, because there aren't many things that you +// can take a direct pointer to in the JVM, and if we're going to copy something +// then we might as well copy it into a `RustBuffer`. But it's here for API +// completeness. + +@Structure.FieldOrder("len", "data") +internal open class ForeignBytes : Structure() { + @JvmField var len: Int = 0 + @JvmField var data: Pointer? = null + + class ByValue : ForeignBytes(), Structure.ByValue +} +/** + * The FfiConverter interface handles converter types to and from the FFI + * + * All implementing objects should be public to support external types. When a + * type is external we need to import it's FfiConverter. + * + * @suppress + */ +public interface FfiConverter { + // Convert an FFI type to a Kotlin type + fun lift(value: FfiType): KotlinType + + // Convert an Kotlin type to an FFI type + fun lower(value: KotlinType): FfiType + + // Read a Kotlin type from a `ByteBuffer` + fun read(buf: ByteBuffer): KotlinType + + // Calculate bytes to allocate when creating a `RustBuffer` + // + // This must return at least as many bytes as the write() function will + // write. It can return more bytes than needed, for example when writing + // Strings we can't know the exact bytes needed until we the UTF-8 + // encoding, so we pessimistically allocate the largest size possible (3 + // bytes per codepoint). Allocating extra bytes is not really a big deal + // because the `RustBuffer` is short-lived. + fun allocationSize(value: KotlinType): ULong + + // Write a Kotlin type to a `ByteBuffer` + fun write(value: KotlinType, buf: ByteBuffer) + + // Lower a value into a `RustBuffer` + // + // This method lowers a value into a `RustBuffer` rather than the normal + // FfiType. It's used by the callback interface code. Callback interface + // returns are always serialized into a `RustBuffer` regardless of their + // normal FFI type. + fun lowerIntoRustBuffer(value: KotlinType): RustBuffer.ByValue { + val rbuf = RustBuffer.alloc(allocationSize(value)) + try { + val bbuf = rbuf.data!!.getByteBuffer(0, rbuf.capacity).also { + it.order(ByteOrder.BIG_ENDIAN) + } + write(value, bbuf) + rbuf.writeField("len", bbuf.position().toLong()) + return rbuf + } catch (e: Throwable) { + RustBuffer.free(rbuf) + throw e + } + } + + // Lift a value from a `RustBuffer`. + // + // This here mostly because of the symmetry with `lowerIntoRustBuffer()`. + // It's currently only used by the `FfiConverterRustBuffer` class below. + fun liftFromRustBuffer(rbuf: RustBuffer.ByValue): KotlinType { + val byteBuf = rbuf.asByteBuffer()!! + try { + val item = read(byteBuf) + if (byteBuf.hasRemaining()) { + throw RuntimeException("junk remaining in buffer after lifting, something is very wrong!!") + } + return item + } finally { + RustBuffer.free(rbuf) + } + } +} + +/** + * FfiConverter that uses `RustBuffer` as the FfiType + * + * @suppress + */ +public interface FfiConverterRustBuffer: FfiConverter { + override fun lift(value: RustBuffer.ByValue) = liftFromRustBuffer(value) + override fun lower(value: KotlinType) = lowerIntoRustBuffer(value) +} +// A handful of classes and functions to support the generated data structures. +// This would be a good candidate for isolating in its own ffi-support lib. + +internal const val UNIFFI_CALL_SUCCESS = 0.toByte() +internal const val UNIFFI_CALL_ERROR = 1.toByte() +internal const val UNIFFI_CALL_UNEXPECTED_ERROR = 2.toByte() + +@Structure.FieldOrder("code", "error_buf") +internal open class UniffiRustCallStatus : Structure() { + @JvmField var code: Byte = 0 + @JvmField var error_buf: RustBuffer.ByValue = RustBuffer.ByValue() + + class ByValue: UniffiRustCallStatus(), Structure.ByValue + + fun isSuccess(): Boolean { + return code == UNIFFI_CALL_SUCCESS + } + + fun isError(): Boolean { + return code == UNIFFI_CALL_ERROR + } + + fun isPanic(): Boolean { + return code == UNIFFI_CALL_UNEXPECTED_ERROR + } + + companion object { + fun create(code: Byte, errorBuf: RustBuffer.ByValue): UniffiRustCallStatus.ByValue { + val callStatus = UniffiRustCallStatus.ByValue() + callStatus.code = code + callStatus.error_buf = errorBuf + return callStatus + } + } +} + +class InternalException(message: String) : kotlin.Exception(message) + +/** + * Each top-level error class has a companion object that can lift the error from the call status's rust buffer + * + * @suppress + */ +interface UniffiRustCallStatusErrorHandler { + fun lift(error_buf: RustBuffer.ByValue): E; +} + +// Helpers for calling Rust +// In practice we usually need to be synchronized to call this safely, so it doesn't +// synchronize itself + +// Call a rust function that returns a Result<>. Pass in the Error class companion that corresponds to the Err +private inline fun uniffiRustCallWithError(errorHandler: UniffiRustCallStatusErrorHandler, callback: (UniffiRustCallStatus) -> U): U { + var status = UniffiRustCallStatus() + val return_value = callback(status) + uniffiCheckCallStatus(errorHandler, status) + return return_value +} + +// Check UniffiRustCallStatus and throw an error if the call wasn't successful +private fun uniffiCheckCallStatus(errorHandler: UniffiRustCallStatusErrorHandler, status: UniffiRustCallStatus) { + if (status.isSuccess()) { + return + } else if (status.isError()) { + throw errorHandler.lift(status.error_buf) + } else if (status.isPanic()) { + // when the rust code sees a panic, it tries to construct a rustbuffer + // with the message. but if that code panics, then it just sends back + // an empty buffer. + if (status.error_buf.len > 0) { + throw InternalException(FfiConverterString.lift(status.error_buf)) + } else { + throw InternalException("Rust panic") + } + } else { + throw InternalException("Unknown rust call status: $status.code") + } +} + +/** + * UniffiRustCallStatusErrorHandler implementation for times when we don't expect a CALL_ERROR + * + * @suppress + */ +object UniffiNullRustCallStatusErrorHandler: UniffiRustCallStatusErrorHandler { + override fun lift(error_buf: RustBuffer.ByValue): InternalException { + RustBuffer.free(error_buf) + return InternalException("Unexpected CALL_ERROR") + } +} + +// Call a rust function that returns a plain value +private inline fun uniffiRustCall(callback: (UniffiRustCallStatus) -> U): U { + return uniffiRustCallWithError(UniffiNullRustCallStatusErrorHandler, callback) +} + +internal inline fun uniffiTraitInterfaceCall( + callStatus: UniffiRustCallStatus, + makeCall: () -> T, + writeReturn: (T) -> Unit, +) { + try { + writeReturn(makeCall()) + } catch(e: kotlin.Exception) { + callStatus.code = UNIFFI_CALL_UNEXPECTED_ERROR + callStatus.error_buf = FfiConverterString.lower(e.toString()) + } +} + +internal inline fun uniffiTraitInterfaceCallWithError( + callStatus: UniffiRustCallStatus, + makeCall: () -> T, + writeReturn: (T) -> Unit, + lowerError: (E) -> RustBuffer.ByValue +) { + try { + writeReturn(makeCall()) + } catch(e: kotlin.Exception) { + if (e is E) { + callStatus.code = UNIFFI_CALL_ERROR + callStatus.error_buf = lowerError(e) + } else { + callStatus.code = UNIFFI_CALL_UNEXPECTED_ERROR + callStatus.error_buf = FfiConverterString.lower(e.toString()) + } + } +} +// Map handles to objects +// +// This is used pass an opaque 64-bit handle representing a foreign object to the Rust code. +internal class UniffiHandleMap { + private val map = ConcurrentHashMap() + private val counter = java.util.concurrent.atomic.AtomicLong(0) + + val size: Int + get() = map.size + + // Insert a new object into the handle map and get a handle for it + fun insert(obj: T): Long { + val handle = counter.getAndAdd(1) + map.put(handle, obj) + return handle + } + + // Get an object from the handle map + fun get(handle: Long): T { + return map.get(handle) ?: throw InternalException("UniffiHandleMap.get: Invalid handle") + } + + // Remove an entry from the handlemap and get the Kotlin object back + fun remove(handle: Long): T { + return map.remove(handle) ?: throw InternalException("UniffiHandleMap: Invalid handle") + } +} + +// Contains loading, initialization code, +// and the FFI Function declarations in a com.sun.jna.Library. +@Synchronized +private fun findLibraryName(componentName: String): String { + val libOverride = System.getProperty("uniffi.component.$componentName.libraryOverride") + if (libOverride != null) { + return libOverride + } + return "algokit_transact_ffi" +} + +private inline fun loadIndirect( + componentName: String +): Lib { + return Native.load(findLibraryName(componentName), Lib::class.java) +} + +// Define FFI callback types +internal interface UniffiRustFutureContinuationCallback : com.sun.jna.Callback { + fun callback(`data`: Long,`pollResult`: Byte,) +} +internal interface UniffiForeignFutureFree : com.sun.jna.Callback { + fun callback(`handle`: Long,) +} +internal interface UniffiCallbackInterfaceFree : com.sun.jna.Callback { + fun callback(`handle`: Long,) +} +@Structure.FieldOrder("handle", "free") +internal open class UniffiForeignFuture( + @JvmField internal var `handle`: Long = 0.toLong(), + @JvmField internal var `free`: UniffiForeignFutureFree? = null, +) : Structure() { + class UniffiByValue( + `handle`: Long = 0.toLong(), + `free`: UniffiForeignFutureFree? = null, + ): UniffiForeignFuture(`handle`,`free`,), Structure.ByValue + + internal fun uniffiSetValue(other: UniffiForeignFuture) { + `handle` = other.`handle` + `free` = other.`free` + } + +} +@Structure.FieldOrder("returnValue", "callStatus") +internal open class UniffiForeignFutureStructU8( + @JvmField internal var `returnValue`: Byte = 0.toByte(), + @JvmField internal var `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), +) : Structure() { + class UniffiByValue( + `returnValue`: Byte = 0.toByte(), + `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), + ): UniffiForeignFutureStructU8(`returnValue`,`callStatus`,), Structure.ByValue + + internal fun uniffiSetValue(other: UniffiForeignFutureStructU8) { + `returnValue` = other.`returnValue` + `callStatus` = other.`callStatus` + } + +} +internal interface UniffiForeignFutureCompleteU8 : com.sun.jna.Callback { + fun callback(`callbackData`: Long,`result`: UniffiForeignFutureStructU8.UniffiByValue,) +} +@Structure.FieldOrder("returnValue", "callStatus") +internal open class UniffiForeignFutureStructI8( + @JvmField internal var `returnValue`: Byte = 0.toByte(), + @JvmField internal var `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), +) : Structure() { + class UniffiByValue( + `returnValue`: Byte = 0.toByte(), + `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), + ): UniffiForeignFutureStructI8(`returnValue`,`callStatus`,), Structure.ByValue + + internal fun uniffiSetValue(other: UniffiForeignFutureStructI8) { + `returnValue` = other.`returnValue` + `callStatus` = other.`callStatus` + } + +} +internal interface UniffiForeignFutureCompleteI8 : com.sun.jna.Callback { + fun callback(`callbackData`: Long,`result`: UniffiForeignFutureStructI8.UniffiByValue,) +} +@Structure.FieldOrder("returnValue", "callStatus") +internal open class UniffiForeignFutureStructU16( + @JvmField internal var `returnValue`: Short = 0.toShort(), + @JvmField internal var `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), +) : Structure() { + class UniffiByValue( + `returnValue`: Short = 0.toShort(), + `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), + ): UniffiForeignFutureStructU16(`returnValue`,`callStatus`,), Structure.ByValue + + internal fun uniffiSetValue(other: UniffiForeignFutureStructU16) { + `returnValue` = other.`returnValue` + `callStatus` = other.`callStatus` + } + +} +internal interface UniffiForeignFutureCompleteU16 : com.sun.jna.Callback { + fun callback(`callbackData`: Long,`result`: UniffiForeignFutureStructU16.UniffiByValue,) +} +@Structure.FieldOrder("returnValue", "callStatus") +internal open class UniffiForeignFutureStructI16( + @JvmField internal var `returnValue`: Short = 0.toShort(), + @JvmField internal var `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), +) : Structure() { + class UniffiByValue( + `returnValue`: Short = 0.toShort(), + `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), + ): UniffiForeignFutureStructI16(`returnValue`,`callStatus`,), Structure.ByValue + + internal fun uniffiSetValue(other: UniffiForeignFutureStructI16) { + `returnValue` = other.`returnValue` + `callStatus` = other.`callStatus` + } + +} +internal interface UniffiForeignFutureCompleteI16 : com.sun.jna.Callback { + fun callback(`callbackData`: Long,`result`: UniffiForeignFutureStructI16.UniffiByValue,) +} +@Structure.FieldOrder("returnValue", "callStatus") +internal open class UniffiForeignFutureStructU32( + @JvmField internal var `returnValue`: Int = 0, + @JvmField internal var `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), +) : Structure() { + class UniffiByValue( + `returnValue`: Int = 0, + `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), + ): UniffiForeignFutureStructU32(`returnValue`,`callStatus`,), Structure.ByValue + + internal fun uniffiSetValue(other: UniffiForeignFutureStructU32) { + `returnValue` = other.`returnValue` + `callStatus` = other.`callStatus` + } + +} +internal interface UniffiForeignFutureCompleteU32 : com.sun.jna.Callback { + fun callback(`callbackData`: Long,`result`: UniffiForeignFutureStructU32.UniffiByValue,) +} +@Structure.FieldOrder("returnValue", "callStatus") +internal open class UniffiForeignFutureStructI32( + @JvmField internal var `returnValue`: Int = 0, + @JvmField internal var `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), +) : Structure() { + class UniffiByValue( + `returnValue`: Int = 0, + `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), + ): UniffiForeignFutureStructI32(`returnValue`,`callStatus`,), Structure.ByValue + + internal fun uniffiSetValue(other: UniffiForeignFutureStructI32) { + `returnValue` = other.`returnValue` + `callStatus` = other.`callStatus` + } + +} +internal interface UniffiForeignFutureCompleteI32 : com.sun.jna.Callback { + fun callback(`callbackData`: Long,`result`: UniffiForeignFutureStructI32.UniffiByValue,) +} +@Structure.FieldOrder("returnValue", "callStatus") +internal open class UniffiForeignFutureStructU64( + @JvmField internal var `returnValue`: Long = 0.toLong(), + @JvmField internal var `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), +) : Structure() { + class UniffiByValue( + `returnValue`: Long = 0.toLong(), + `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), + ): UniffiForeignFutureStructU64(`returnValue`,`callStatus`,), Structure.ByValue + + internal fun uniffiSetValue(other: UniffiForeignFutureStructU64) { + `returnValue` = other.`returnValue` + `callStatus` = other.`callStatus` + } + +} +internal interface UniffiForeignFutureCompleteU64 : com.sun.jna.Callback { + fun callback(`callbackData`: Long,`result`: UniffiForeignFutureStructU64.UniffiByValue,) +} +@Structure.FieldOrder("returnValue", "callStatus") +internal open class UniffiForeignFutureStructI64( + @JvmField internal var `returnValue`: Long = 0.toLong(), + @JvmField internal var `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), +) : Structure() { + class UniffiByValue( + `returnValue`: Long = 0.toLong(), + `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), + ): UniffiForeignFutureStructI64(`returnValue`,`callStatus`,), Structure.ByValue + + internal fun uniffiSetValue(other: UniffiForeignFutureStructI64) { + `returnValue` = other.`returnValue` + `callStatus` = other.`callStatus` + } + +} +internal interface UniffiForeignFutureCompleteI64 : com.sun.jna.Callback { + fun callback(`callbackData`: Long,`result`: UniffiForeignFutureStructI64.UniffiByValue,) +} +@Structure.FieldOrder("returnValue", "callStatus") +internal open class UniffiForeignFutureStructF32( + @JvmField internal var `returnValue`: Float = 0.0f, + @JvmField internal var `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), +) : Structure() { + class UniffiByValue( + `returnValue`: Float = 0.0f, + `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), + ): UniffiForeignFutureStructF32(`returnValue`,`callStatus`,), Structure.ByValue + + internal fun uniffiSetValue(other: UniffiForeignFutureStructF32) { + `returnValue` = other.`returnValue` + `callStatus` = other.`callStatus` + } + +} +internal interface UniffiForeignFutureCompleteF32 : com.sun.jna.Callback { + fun callback(`callbackData`: Long,`result`: UniffiForeignFutureStructF32.UniffiByValue,) +} +@Structure.FieldOrder("returnValue", "callStatus") +internal open class UniffiForeignFutureStructF64( + @JvmField internal var `returnValue`: Double = 0.0, + @JvmField internal var `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), +) : Structure() { + class UniffiByValue( + `returnValue`: Double = 0.0, + `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), + ): UniffiForeignFutureStructF64(`returnValue`,`callStatus`,), Structure.ByValue + + internal fun uniffiSetValue(other: UniffiForeignFutureStructF64) { + `returnValue` = other.`returnValue` + `callStatus` = other.`callStatus` + } + +} +internal interface UniffiForeignFutureCompleteF64 : com.sun.jna.Callback { + fun callback(`callbackData`: Long,`result`: UniffiForeignFutureStructF64.UniffiByValue,) +} +@Structure.FieldOrder("returnValue", "callStatus") +internal open class UniffiForeignFutureStructPointer( + @JvmField internal var `returnValue`: Pointer = Pointer.NULL, + @JvmField internal var `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), +) : Structure() { + class UniffiByValue( + `returnValue`: Pointer = Pointer.NULL, + `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), + ): UniffiForeignFutureStructPointer(`returnValue`,`callStatus`,), Structure.ByValue + + internal fun uniffiSetValue(other: UniffiForeignFutureStructPointer) { + `returnValue` = other.`returnValue` + `callStatus` = other.`callStatus` + } + +} +internal interface UniffiForeignFutureCompletePointer : com.sun.jna.Callback { + fun callback(`callbackData`: Long,`result`: UniffiForeignFutureStructPointer.UniffiByValue,) +} +@Structure.FieldOrder("returnValue", "callStatus") +internal open class UniffiForeignFutureStructRustBuffer( + @JvmField internal var `returnValue`: RustBuffer.ByValue = RustBuffer.ByValue(), + @JvmField internal var `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), +) : Structure() { + class UniffiByValue( + `returnValue`: RustBuffer.ByValue = RustBuffer.ByValue(), + `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), + ): UniffiForeignFutureStructRustBuffer(`returnValue`,`callStatus`,), Structure.ByValue + + internal fun uniffiSetValue(other: UniffiForeignFutureStructRustBuffer) { + `returnValue` = other.`returnValue` + `callStatus` = other.`callStatus` + } + +} +internal interface UniffiForeignFutureCompleteRustBuffer : com.sun.jna.Callback { + fun callback(`callbackData`: Long,`result`: UniffiForeignFutureStructRustBuffer.UniffiByValue,) +} +@Structure.FieldOrder("callStatus") +internal open class UniffiForeignFutureStructVoid( + @JvmField internal var `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), +) : Structure() { + class UniffiByValue( + `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), + ): UniffiForeignFutureStructVoid(`callStatus`,), Structure.ByValue + + internal fun uniffiSetValue(other: UniffiForeignFutureStructVoid) { + `callStatus` = other.`callStatus` + } + +} +internal interface UniffiForeignFutureCompleteVoid : com.sun.jna.Callback { + fun callback(`callbackData`: Long,`result`: UniffiForeignFutureStructVoid.UniffiByValue,) +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +// For large crates we prevent `MethodTooLargeException` (see #2340) +// N.B. the name of the extension is very misleading, since it is +// rather `InterfaceTooLargeException`, caused by too many methods +// in the interface for large crates. +// +// By splitting the otherwise huge interface into two parts +// * UniffiLib +// * IntegrityCheckingUniffiLib (this) +// we allow for ~2x as many methods in the UniffiLib interface. +// +// The `ffi_uniffi_contract_version` method and all checksum methods are put +// into `IntegrityCheckingUniffiLib` and these methods are called only once, +// when the library is loaded. +internal interface IntegrityCheckingUniffiLib : Library { + // Integrity check functions only + fun uniffi_algokit_transact_ffi_checksum_func_address_from_multisig_signature( +): Short +fun uniffi_algokit_transact_ffi_checksum_func_address_from_public_key( +): Short +fun uniffi_algokit_transact_ffi_checksum_func_apply_multisig_subsignature( +): Short +fun uniffi_algokit_transact_ffi_checksum_func_assign_fee( +): Short +fun uniffi_algokit_transact_ffi_checksum_func_calculate_fee( +): Short +fun uniffi_algokit_transact_ffi_checksum_func_decode_signed_transaction( +): Short +fun uniffi_algokit_transact_ffi_checksum_func_decode_signed_transactions( +): Short +fun uniffi_algokit_transact_ffi_checksum_func_decode_transaction( +): Short +fun uniffi_algokit_transact_ffi_checksum_func_decode_transactions( +): Short +fun uniffi_algokit_transact_ffi_checksum_func_encode_signed_transaction( +): Short +fun uniffi_algokit_transact_ffi_checksum_func_encode_signed_transactions( +): Short +fun uniffi_algokit_transact_ffi_checksum_func_encode_transaction( +): Short +fun uniffi_algokit_transact_ffi_checksum_func_encode_transaction_raw( +): Short +fun uniffi_algokit_transact_ffi_checksum_func_encode_transactions( +): Short +fun uniffi_algokit_transact_ffi_checksum_func_estimate_transaction_size( +): Short +fun uniffi_algokit_transact_ffi_checksum_func_get_algorand_constant( +): Short +fun uniffi_algokit_transact_ffi_checksum_func_get_encoded_transaction_type( +): Short +fun uniffi_algokit_transact_ffi_checksum_func_get_transaction_id( +): Short +fun uniffi_algokit_transact_ffi_checksum_func_get_transaction_id_raw( +): Short +fun uniffi_algokit_transact_ffi_checksum_func_group_transactions( +): Short +fun uniffi_algokit_transact_ffi_checksum_func_merge_multisignatures( +): Short +fun uniffi_algokit_transact_ffi_checksum_func_new_multisig_signature( +): Short +fun uniffi_algokit_transact_ffi_checksum_func_participants_from_multisig_signature( +): Short +fun uniffi_algokit_transact_ffi_checksum_func_public_key_from_address( +): Short +fun ffi_algokit_transact_ffi_uniffi_contract_version( +): Int + +} + +// A JNA Library to expose the extern-C FFI definitions. +// This is an implementation detail which will be called internally by the public API. +internal interface UniffiLib : Library { + companion object { + internal val INSTANCE: UniffiLib by lazy { + val componentName = "algokit_transact_ffi" + // For large crates we prevent `MethodTooLargeException` (see #2340) + // N.B. the name of the extension is very misleading, since it is + // rather `InterfaceTooLargeException`, caused by too many methods + // in the interface for large crates. + // + // By splitting the otherwise huge interface into two parts + // * UniffiLib (this) + // * IntegrityCheckingUniffiLib + // And all checksum methods are put into `IntegrityCheckingUniffiLib` + // we allow for ~2x as many methods in the UniffiLib interface. + // + // Thus we first load the library with `loadIndirect` as `IntegrityCheckingUniffiLib` + // so that we can (optionally!) call `uniffiCheckApiChecksums`... + loadIndirect(componentName) + .also { lib: IntegrityCheckingUniffiLib -> + uniffiCheckContractApiVersion(lib) + uniffiCheckApiChecksums(lib) + } + // ... and then we load the library as `UniffiLib` + // N.B. we cannot use `loadIndirect` once and then try to cast it to `UniffiLib` + // => results in `java.lang.ClassCastException: com.sun.proxy.$Proxy cannot be cast to ...` + // error. So we must call `loadIndirect` twice. For crates large enough + // to trigger this issue, the performance impact is negligible, running on + // a macOS M1 machine the `loadIndirect` call takes ~50ms. + val lib = loadIndirect(componentName) + // No need to check the contract version and checksums, since + // we already did that with `IntegrityCheckingUniffiLib` above. + // Loading of library with integrity check done. + lib + } + + } + + // FFI functions + fun uniffi_algokit_transact_ffi_fn_func_address_from_multisig_signature(`multisigSignature`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, +): RustBuffer.ByValue +fun uniffi_algokit_transact_ffi_fn_func_address_from_public_key(`publicKey`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, +): RustBuffer.ByValue +fun uniffi_algokit_transact_ffi_fn_func_apply_multisig_subsignature(`multisigSignature`: RustBuffer.ByValue,`participant`: RustBuffer.ByValue,`subsignature`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, +): RustBuffer.ByValue +fun uniffi_algokit_transact_ffi_fn_func_assign_fee(`transaction`: RustBuffer.ByValue,`feeParams`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, +): RustBuffer.ByValue +fun uniffi_algokit_transact_ffi_fn_func_calculate_fee(`transaction`: RustBuffer.ByValue,`feeParams`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, +): Long +fun uniffi_algokit_transact_ffi_fn_func_decode_signed_transaction(`encodedSignedTransaction`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, +): RustBuffer.ByValue +fun uniffi_algokit_transact_ffi_fn_func_decode_signed_transactions(`encodedSignedTransactions`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, +): RustBuffer.ByValue +fun uniffi_algokit_transact_ffi_fn_func_decode_transaction(`encodedTx`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, +): RustBuffer.ByValue +fun uniffi_algokit_transact_ffi_fn_func_decode_transactions(`encodedTxs`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, +): RustBuffer.ByValue +fun uniffi_algokit_transact_ffi_fn_func_encode_signed_transaction(`signedTransaction`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, +): RustBuffer.ByValue +fun uniffi_algokit_transact_ffi_fn_func_encode_signed_transactions(`signedTransactions`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, +): RustBuffer.ByValue +fun uniffi_algokit_transact_ffi_fn_func_encode_transaction(`transaction`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, +): RustBuffer.ByValue +fun uniffi_algokit_transact_ffi_fn_func_encode_transaction_raw(`transaction`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, +): RustBuffer.ByValue +fun uniffi_algokit_transact_ffi_fn_func_encode_transactions(`transactions`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, +): RustBuffer.ByValue +fun uniffi_algokit_transact_ffi_fn_func_estimate_transaction_size(`transaction`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, +): Long +fun uniffi_algokit_transact_ffi_fn_func_get_algorand_constant(`constant`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, +): Long +fun uniffi_algokit_transact_ffi_fn_func_get_encoded_transaction_type(`encodedTransaction`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, +): RustBuffer.ByValue +fun uniffi_algokit_transact_ffi_fn_func_get_transaction_id(`transaction`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, +): RustBuffer.ByValue +fun uniffi_algokit_transact_ffi_fn_func_get_transaction_id_raw(`transaction`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, +): RustBuffer.ByValue +fun uniffi_algokit_transact_ffi_fn_func_group_transactions(`transactions`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, +): RustBuffer.ByValue +fun uniffi_algokit_transact_ffi_fn_func_merge_multisignatures(`multisigSignatureA`: RustBuffer.ByValue,`multisigSignatureB`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, +): RustBuffer.ByValue +fun uniffi_algokit_transact_ffi_fn_func_new_multisig_signature(`version`: Byte,`threshold`: Byte,`participants`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, +): RustBuffer.ByValue +fun uniffi_algokit_transact_ffi_fn_func_participants_from_multisig_signature(`multisigSignature`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, +): RustBuffer.ByValue +fun uniffi_algokit_transact_ffi_fn_func_public_key_from_address(`address`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, +): RustBuffer.ByValue +fun ffi_algokit_transact_ffi_rustbuffer_alloc(`size`: Long,uniffi_out_err: UniffiRustCallStatus, +): RustBuffer.ByValue +fun ffi_algokit_transact_ffi_rustbuffer_from_bytes(`bytes`: ForeignBytes.ByValue,uniffi_out_err: UniffiRustCallStatus, +): RustBuffer.ByValue +fun ffi_algokit_transact_ffi_rustbuffer_free(`buf`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, +): Unit +fun ffi_algokit_transact_ffi_rustbuffer_reserve(`buf`: RustBuffer.ByValue,`additional`: Long,uniffi_out_err: UniffiRustCallStatus, +): RustBuffer.ByValue +fun ffi_algokit_transact_ffi_rust_future_poll_u8(`handle`: Long,`callback`: UniffiRustFutureContinuationCallback,`callbackData`: Long, +): Unit +fun ffi_algokit_transact_ffi_rust_future_cancel_u8(`handle`: Long, +): Unit +fun ffi_algokit_transact_ffi_rust_future_free_u8(`handle`: Long, +): Unit +fun ffi_algokit_transact_ffi_rust_future_complete_u8(`handle`: Long,uniffi_out_err: UniffiRustCallStatus, +): Byte +fun ffi_algokit_transact_ffi_rust_future_poll_i8(`handle`: Long,`callback`: UniffiRustFutureContinuationCallback,`callbackData`: Long, +): Unit +fun ffi_algokit_transact_ffi_rust_future_cancel_i8(`handle`: Long, +): Unit +fun ffi_algokit_transact_ffi_rust_future_free_i8(`handle`: Long, +): Unit +fun ffi_algokit_transact_ffi_rust_future_complete_i8(`handle`: Long,uniffi_out_err: UniffiRustCallStatus, +): Byte +fun ffi_algokit_transact_ffi_rust_future_poll_u16(`handle`: Long,`callback`: UniffiRustFutureContinuationCallback,`callbackData`: Long, +): Unit +fun ffi_algokit_transact_ffi_rust_future_cancel_u16(`handle`: Long, +): Unit +fun ffi_algokit_transact_ffi_rust_future_free_u16(`handle`: Long, +): Unit +fun ffi_algokit_transact_ffi_rust_future_complete_u16(`handle`: Long,uniffi_out_err: UniffiRustCallStatus, +): Short +fun ffi_algokit_transact_ffi_rust_future_poll_i16(`handle`: Long,`callback`: UniffiRustFutureContinuationCallback,`callbackData`: Long, +): Unit +fun ffi_algokit_transact_ffi_rust_future_cancel_i16(`handle`: Long, +): Unit +fun ffi_algokit_transact_ffi_rust_future_free_i16(`handle`: Long, +): Unit +fun ffi_algokit_transact_ffi_rust_future_complete_i16(`handle`: Long,uniffi_out_err: UniffiRustCallStatus, +): Short +fun ffi_algokit_transact_ffi_rust_future_poll_u32(`handle`: Long,`callback`: UniffiRustFutureContinuationCallback,`callbackData`: Long, +): Unit +fun ffi_algokit_transact_ffi_rust_future_cancel_u32(`handle`: Long, +): Unit +fun ffi_algokit_transact_ffi_rust_future_free_u32(`handle`: Long, +): Unit +fun ffi_algokit_transact_ffi_rust_future_complete_u32(`handle`: Long,uniffi_out_err: UniffiRustCallStatus, +): Int +fun ffi_algokit_transact_ffi_rust_future_poll_i32(`handle`: Long,`callback`: UniffiRustFutureContinuationCallback,`callbackData`: Long, +): Unit +fun ffi_algokit_transact_ffi_rust_future_cancel_i32(`handle`: Long, +): Unit +fun ffi_algokit_transact_ffi_rust_future_free_i32(`handle`: Long, +): Unit +fun ffi_algokit_transact_ffi_rust_future_complete_i32(`handle`: Long,uniffi_out_err: UniffiRustCallStatus, +): Int +fun ffi_algokit_transact_ffi_rust_future_poll_u64(`handle`: Long,`callback`: UniffiRustFutureContinuationCallback,`callbackData`: Long, +): Unit +fun ffi_algokit_transact_ffi_rust_future_cancel_u64(`handle`: Long, +): Unit +fun ffi_algokit_transact_ffi_rust_future_free_u64(`handle`: Long, +): Unit +fun ffi_algokit_transact_ffi_rust_future_complete_u64(`handle`: Long,uniffi_out_err: UniffiRustCallStatus, +): Long +fun ffi_algokit_transact_ffi_rust_future_poll_i64(`handle`: Long,`callback`: UniffiRustFutureContinuationCallback,`callbackData`: Long, +): Unit +fun ffi_algokit_transact_ffi_rust_future_cancel_i64(`handle`: Long, +): Unit +fun ffi_algokit_transact_ffi_rust_future_free_i64(`handle`: Long, +): Unit +fun ffi_algokit_transact_ffi_rust_future_complete_i64(`handle`: Long,uniffi_out_err: UniffiRustCallStatus, +): Long +fun ffi_algokit_transact_ffi_rust_future_poll_f32(`handle`: Long,`callback`: UniffiRustFutureContinuationCallback,`callbackData`: Long, +): Unit +fun ffi_algokit_transact_ffi_rust_future_cancel_f32(`handle`: Long, +): Unit +fun ffi_algokit_transact_ffi_rust_future_free_f32(`handle`: Long, +): Unit +fun ffi_algokit_transact_ffi_rust_future_complete_f32(`handle`: Long,uniffi_out_err: UniffiRustCallStatus, +): Float +fun ffi_algokit_transact_ffi_rust_future_poll_f64(`handle`: Long,`callback`: UniffiRustFutureContinuationCallback,`callbackData`: Long, +): Unit +fun ffi_algokit_transact_ffi_rust_future_cancel_f64(`handle`: Long, +): Unit +fun ffi_algokit_transact_ffi_rust_future_free_f64(`handle`: Long, +): Unit +fun ffi_algokit_transact_ffi_rust_future_complete_f64(`handle`: Long,uniffi_out_err: UniffiRustCallStatus, +): Double +fun ffi_algokit_transact_ffi_rust_future_poll_pointer(`handle`: Long,`callback`: UniffiRustFutureContinuationCallback,`callbackData`: Long, +): Unit +fun ffi_algokit_transact_ffi_rust_future_cancel_pointer(`handle`: Long, +): Unit +fun ffi_algokit_transact_ffi_rust_future_free_pointer(`handle`: Long, +): Unit +fun ffi_algokit_transact_ffi_rust_future_complete_pointer(`handle`: Long,uniffi_out_err: UniffiRustCallStatus, +): Pointer +fun ffi_algokit_transact_ffi_rust_future_poll_rust_buffer(`handle`: Long,`callback`: UniffiRustFutureContinuationCallback,`callbackData`: Long, +): Unit +fun ffi_algokit_transact_ffi_rust_future_cancel_rust_buffer(`handle`: Long, +): Unit +fun ffi_algokit_transact_ffi_rust_future_free_rust_buffer(`handle`: Long, +): Unit +fun ffi_algokit_transact_ffi_rust_future_complete_rust_buffer(`handle`: Long,uniffi_out_err: UniffiRustCallStatus, +): RustBuffer.ByValue +fun ffi_algokit_transact_ffi_rust_future_poll_void(`handle`: Long,`callback`: UniffiRustFutureContinuationCallback,`callbackData`: Long, +): Unit +fun ffi_algokit_transact_ffi_rust_future_cancel_void(`handle`: Long, +): Unit +fun ffi_algokit_transact_ffi_rust_future_free_void(`handle`: Long, +): Unit +fun ffi_algokit_transact_ffi_rust_future_complete_void(`handle`: Long,uniffi_out_err: UniffiRustCallStatus, +): Unit + +} + +private fun uniffiCheckContractApiVersion(lib: IntegrityCheckingUniffiLib) { + // Get the bindings contract version from our ComponentInterface + val bindings_contract_version = 29 + // Get the scaffolding contract version by calling the into the dylib + val scaffolding_contract_version = lib.ffi_algokit_transact_ffi_uniffi_contract_version() + if (bindings_contract_version != scaffolding_contract_version) { + throw RuntimeException("UniFFI contract version mismatch: try cleaning and rebuilding your project") + } +} +@Suppress("UNUSED_PARAMETER") +private fun uniffiCheckApiChecksums(lib: IntegrityCheckingUniffiLib) { + if (lib.uniffi_algokit_transact_ffi_checksum_func_address_from_multisig_signature() != 51026.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_algokit_transact_ffi_checksum_func_address_from_public_key() != 10716.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_algokit_transact_ffi_checksum_func_apply_multisig_subsignature() != 42634.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_algokit_transact_ffi_checksum_func_assign_fee() != 35003.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_algokit_transact_ffi_checksum_func_calculate_fee() != 7537.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_algokit_transact_ffi_checksum_func_decode_signed_transaction() != 43569.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_algokit_transact_ffi_checksum_func_decode_signed_transactions() != 62888.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_algokit_transact_ffi_checksum_func_decode_transaction() != 56405.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_algokit_transact_ffi_checksum_func_decode_transactions() != 26956.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_algokit_transact_ffi_checksum_func_encode_signed_transaction() != 47064.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_algokit_transact_ffi_checksum_func_encode_signed_transactions() != 1956.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_algokit_transact_ffi_checksum_func_encode_transaction() != 11275.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_algokit_transact_ffi_checksum_func_encode_transaction_raw() != 384.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_algokit_transact_ffi_checksum_func_encode_transactions() != 59611.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_algokit_transact_ffi_checksum_func_estimate_transaction_size() != 60858.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_algokit_transact_ffi_checksum_func_get_algorand_constant() != 49400.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_algokit_transact_ffi_checksum_func_get_encoded_transaction_type() != 42551.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_algokit_transact_ffi_checksum_func_get_transaction_id() != 10957.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_algokit_transact_ffi_checksum_func_get_transaction_id_raw() != 48975.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_algokit_transact_ffi_checksum_func_group_transactions() != 18193.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_algokit_transact_ffi_checksum_func_merge_multisignatures() != 58688.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_algokit_transact_ffi_checksum_func_new_multisig_signature() != 29314.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_algokit_transact_ffi_checksum_func_participants_from_multisig_signature() != 25095.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_algokit_transact_ffi_checksum_func_public_key_from_address() != 58152.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } +} + +/** + * @suppress + */ +public fun uniffiEnsureInitialized() { + UniffiLib.INSTANCE +} + +// Async support + +// Public interface members begin here. + + +// Interface implemented by anything that can contain an object reference. +// +// Such types expose a `destroy()` method that must be called to cleanly +// dispose of the contained objects. Failure to call this method may result +// in memory leaks. +// +// The easiest way to ensure this method is called is to use the `.use` +// helper method to execute a block and destroy the object at the end. +interface Disposable { + fun destroy() + companion object { + fun destroy(vararg args: Any?) { + for (arg in args) { + when (arg) { + is Disposable -> arg.destroy() + is ArrayList<*> -> { + for (idx in arg.indices) { + val element = arg[idx] + if (element is Disposable) { + element.destroy() + } + } + } + is Map<*, *> -> { + for (element in arg.values) { + if (element is Disposable) { + element.destroy() + } + } + } + is Iterable<*> -> { + for (element in arg) { + if (element is Disposable) { + element.destroy() + } + } + } + } + } + } + } +} + +/** + * @suppress + */ +inline fun T.use(block: (T) -> R) = + try { + block(this) + } finally { + try { + // N.B. our implementation is on the nullable type `Disposable?`. + this?.destroy() + } catch (e: Throwable) { + // swallow + } + } + +/** + * Used to instantiate an interface without an actual pointer, for fakes in tests, mostly. + * + * @suppress + * */ +object NoPointer + +/** + * @suppress + */ +public object FfiConverterUByte: FfiConverter { + override fun lift(value: Byte): UByte { + return value.toUByte() + } + + override fun read(buf: ByteBuffer): UByte { + return lift(buf.get()) + } + + override fun lower(value: UByte): Byte { + return value.toByte() + } + + override fun allocationSize(value: UByte) = 1UL + + override fun write(value: UByte, buf: ByteBuffer) { + buf.put(value.toByte()) + } +} + +/** + * @suppress + */ +public object FfiConverterUInt: FfiConverter { + override fun lift(value: Int): UInt { + return value.toUInt() + } + + override fun read(buf: ByteBuffer): UInt { + return lift(buf.getInt()) + } + + override fun lower(value: UInt): Int { + return value.toInt() + } + + override fun allocationSize(value: UInt) = 4UL + + override fun write(value: UInt, buf: ByteBuffer) { + buf.putInt(value.toInt()) + } +} + +/** + * @suppress + */ +public object FfiConverterULong: FfiConverter { + override fun lift(value: Long): ULong { + return value.toULong() + } + + override fun read(buf: ByteBuffer): ULong { + return lift(buf.getLong()) + } + + override fun lower(value: ULong): Long { + return value.toLong() + } + + override fun allocationSize(value: ULong) = 8UL + + override fun write(value: ULong, buf: ByteBuffer) { + buf.putLong(value.toLong()) + } +} + +/** + * @suppress + */ +public object FfiConverterBoolean: FfiConverter { + override fun lift(value: Byte): Boolean { + return value.toInt() != 0 + } + + override fun read(buf: ByteBuffer): Boolean { + return lift(buf.get()) + } + + override fun lower(value: Boolean): Byte { + return if (value) 1.toByte() else 0.toByte() + } + + override fun allocationSize(value: Boolean) = 1UL + + override fun write(value: Boolean, buf: ByteBuffer) { + buf.put(lower(value)) + } +} + +/** + * @suppress + */ +public object FfiConverterString: FfiConverter { + // Note: we don't inherit from FfiConverterRustBuffer, because we use a + // special encoding when lowering/lifting. We can use `RustBuffer.len` to + // store our length and avoid writing it out to the buffer. + override fun lift(value: RustBuffer.ByValue): String { + try { + val byteArr = ByteArray(value.len.toInt()) + value.asByteBuffer()!!.get(byteArr) + return byteArr.toString(Charsets.UTF_8) + } finally { + RustBuffer.free(value) + } + } + + override fun read(buf: ByteBuffer): String { + val len = buf.getInt() + val byteArr = ByteArray(len) + buf.get(byteArr) + return byteArr.toString(Charsets.UTF_8) + } + + fun toUtf8(value: String): ByteBuffer { + // Make sure we don't have invalid UTF-16, check for lone surrogates. + return Charsets.UTF_8.newEncoder().run { + onMalformedInput(CodingErrorAction.REPORT) + encode(CharBuffer.wrap(value)) + } + } + + override fun lower(value: String): RustBuffer.ByValue { + val byteBuf = toUtf8(value) + // Ideally we'd pass these bytes to `ffi_bytebuffer_from_bytes`, but doing so would require us + // to copy them into a JNA `Memory`. So we might as well directly copy them into a `RustBuffer`. + val rbuf = RustBuffer.alloc(byteBuf.limit().toULong()) + rbuf.asByteBuffer()!!.put(byteBuf) + return rbuf + } + + // We aren't sure exactly how many bytes our string will be once it's UTF-8 + // encoded. Allocate 3 bytes per UTF-16 code unit which will always be + // enough. + override fun allocationSize(value: String): ULong { + val sizeForLength = 4UL + val sizeForString = value.length.toULong() * 3UL + return sizeForLength + sizeForString + } + + override fun write(value: String, buf: ByteBuffer) { + val byteBuf = toUtf8(value) + buf.putInt(byteBuf.limit()) + buf.put(byteBuf) + } +} + +/** + * @suppress + */ +public object FfiConverterByteArray: FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): ByteArray { + val len = buf.getInt() + val byteArr = ByteArray(len) + buf.get(byteArr) + return byteArr + } + override fun allocationSize(value: ByteArray): ULong { + return 4UL + value.size.toULong() + } + override fun write(value: ByteArray, buf: ByteBuffer) { + buf.putInt(value.size) + buf.put(value) + } +} + + + +/** + * Represents an app call transaction that interacts with Algorand Smart Contracts. + * + * App call transactions are used to create, update, delete, opt-in to, + * close out of, or clear state from Algorand applications (smart contracts). + */ +data class AppCallTransactionFields ( + /** + * ID of the app being called. + * + * Set this to 0 to indicate an app creation call. + */ + var `appId`: kotlin.ULong, + /** + * Defines what additional actions occur with the transaction. + */ + var `onComplete`: OnApplicationComplete, + /** + * Logic executed for every app call transaction, except when + * on-completion is set to "clear". + * + * Approval programs may reject the transaction. + * Only required for app creation and update transactions. + */ + var `approvalProgram`: kotlin.ByteArray? = null, + /** + * Logic executed for app call transactions with on-completion set to "clear". + * + * Clear state programs cannot reject the transaction. + * Only required for app creation and update transactions. + */ + var `clearStateProgram`: kotlin.ByteArray? = null, + /** + * Holds the maximum number of global state values. + * + * Only required for app creation transactions. + * This cannot be changed after creation. + */ + var `globalStateSchema`: StateSchema? = null, + /** + * Holds the maximum number of local state values. + * + * Only required for app creation transactions. + * This cannot be changed after creation. + */ + var `localStateSchema`: StateSchema? = null, + /** + * Number of additional pages allocated to the app's approval + * and clear state programs. + * + * Each extra program page is 2048 bytes. The sum of approval program + * and clear state program may not exceed 2048*(1+extra_program_pages) bytes. + * Currently, the maximum value is 3. + * This cannot be changed after creation. + */ + var `extraProgramPages`: kotlin.UInt? = null, + /** + * Transaction specific arguments available in the app's + * approval program and clear state program. + */ + var `args`: List? = null, + /** + * List of accounts in addition to the sender that may be accessed + * from the app's approval program and clear state program. + */ + var `accountReferences`: List? = null, + /** + * List of apps in addition to the current app that may be called + * from the app's approval program and clear state program. + */ + var `appReferences`: List? = null, + /** + * Lists the assets whose parameters may be accessed by this app's + * approval program and clear state program. + * + * The access is read-only. + */ + var `assetReferences`: List? = null, + /** + * The boxes that should be made available for the runtime of the program. + */ + var `boxReferences`: List? = null +) { + + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeAppCallTransactionFields: FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): AppCallTransactionFields { + return AppCallTransactionFields( + FfiConverterULong.read(buf), + FfiConverterTypeOnApplicationComplete.read(buf), + FfiConverterOptionalByteArray.read(buf), + FfiConverterOptionalByteArray.read(buf), + FfiConverterOptionalTypeStateSchema.read(buf), + FfiConverterOptionalTypeStateSchema.read(buf), + FfiConverterOptionalUInt.read(buf), + FfiConverterOptionalSequenceByteArray.read(buf), + FfiConverterOptionalSequenceString.read(buf), + FfiConverterOptionalSequenceULong.read(buf), + FfiConverterOptionalSequenceULong.read(buf), + FfiConverterOptionalSequenceTypeBoxReference.read(buf), + ) + } + + override fun allocationSize(value: AppCallTransactionFields) = ( + FfiConverterULong.allocationSize(value.`appId`) + + FfiConverterTypeOnApplicationComplete.allocationSize(value.`onComplete`) + + FfiConverterOptionalByteArray.allocationSize(value.`approvalProgram`) + + FfiConverterOptionalByteArray.allocationSize(value.`clearStateProgram`) + + FfiConverterOptionalTypeStateSchema.allocationSize(value.`globalStateSchema`) + + FfiConverterOptionalTypeStateSchema.allocationSize(value.`localStateSchema`) + + FfiConverterOptionalUInt.allocationSize(value.`extraProgramPages`) + + FfiConverterOptionalSequenceByteArray.allocationSize(value.`args`) + + FfiConverterOptionalSequenceString.allocationSize(value.`accountReferences`) + + FfiConverterOptionalSequenceULong.allocationSize(value.`appReferences`) + + FfiConverterOptionalSequenceULong.allocationSize(value.`assetReferences`) + + FfiConverterOptionalSequenceTypeBoxReference.allocationSize(value.`boxReferences`) + ) + + override fun write(value: AppCallTransactionFields, buf: ByteBuffer) { + FfiConverterULong.write(value.`appId`, buf) + FfiConverterTypeOnApplicationComplete.write(value.`onComplete`, buf) + FfiConverterOptionalByteArray.write(value.`approvalProgram`, buf) + FfiConverterOptionalByteArray.write(value.`clearStateProgram`, buf) + FfiConverterOptionalTypeStateSchema.write(value.`globalStateSchema`, buf) + FfiConverterOptionalTypeStateSchema.write(value.`localStateSchema`, buf) + FfiConverterOptionalUInt.write(value.`extraProgramPages`, buf) + FfiConverterOptionalSequenceByteArray.write(value.`args`, buf) + FfiConverterOptionalSequenceString.write(value.`accountReferences`, buf) + FfiConverterOptionalSequenceULong.write(value.`appReferences`, buf) + FfiConverterOptionalSequenceULong.write(value.`assetReferences`, buf) + FfiConverterOptionalSequenceTypeBoxReference.write(value.`boxReferences`, buf) + } +} + + + +/** + * Parameters to define an asset config transaction. + * + * For asset creation, the asset ID field must be 0. + * For asset reconfiguration, the asset ID field must be set. Only fields manager, reserve, freeze, and clawback can be set. + * For asset destroy, the asset ID field must be set, all other fields must not be set. + * + * **Note:** The manager, reserve, freeze, and clawback addresses + * are immutably empty if they are not set. If manager is not set then + * all fields are immutable from that point forward. + */ +data class AssetConfigTransactionFields ( + /** + * ID of the asset to operate on. + * + * For asset creation, this must be 0. + * For asset reconfiguration this is the ID of the existing asset to be reconfigured, + * For asset destroy this is the ID of the existing asset to be destroyed. + */ + var `assetId`: kotlin.ULong, + /** + * The total amount of the smallest divisible (decimal) unit to create. + * + * Required when creating a new asset. + * For example, if creating a asset with 2 decimals and wanting a total supply of 100 units, this value should be 10000. + * + * This field can only be specified upon asset creation. + */ + var `total`: kotlin.ULong? = null, + /** + * The amount of decimal places the asset should have. + * + * If unspecified then the asset will be in whole units (i.e. `0`). + * * If 0, the asset is not divisible; + * * If 1, the base unit of the asset is in tenths; + * * If 2, the base unit of the asset is in hundredths; + * * If 3, the base unit of the asset is in thousandths; + * + * and so on up to 19 decimal places. + * + * This field can only be specified upon asset creation. + */ + var `decimals`: kotlin.UInt? = null, + /** + * Whether the asset is frozen by default for all accounts. + * Defaults to `false`. + * + * If `true` then for anyone apart from the creator to hold the + * asset it needs to be unfrozen per account using an asset freeze + * transaction from the `freeze` account, which must be set on creation. + * + * This field can only be specified upon asset creation. + */ + var `defaultFrozen`: kotlin.Boolean? = null, + /** + * The optional name of the asset. + * + * Max size is 32 bytes. + * + * This field can only be specified upon asset creation. + */ + var `assetName`: kotlin.String? = null, + /** + * The optional name of the unit of this asset (e.g. ticker name). + * + * Max size is 8 bytes. + * + * This field can only be specified upon asset creation. + */ + var `unitName`: kotlin.String? = null, + /** + * Specifies an optional URL where more information about the asset can be retrieved (e.g. metadata). + * + * Max size is 96 bytes. + * + * This field can only be specified upon asset creation. + */ + var `url`: kotlin.String? = null, + /** + * 32-byte hash of some metadata that is relevant to your asset and/or asset holders. + * + * The format of this metadata is up to the application. + * + * This field can only be specified upon asset creation. + */ + var `metadataHash`: kotlin.ByteArray? = null, + /** + * The address of the optional account that can manage the configuration of the asset and destroy it. + * + * The fields it can change are `manager`, `reserve`, `clawback`, and `freeze`. + * + * If not set or set to the Zero address the asset becomes permanently immutable. + */ + var `manager`: kotlin.String? = null, + /** + * The address of the optional account that holds the reserve (uncirculated supply) units of the asset. + * + * This address has no specific authority in the protocol itself and is informational only. + * + * Some standards like [ARC-19](https://github.com/algorandfoundation/ARCs/blob/main/ARCs/arc-0019.md) + * rely on this field to hold meaningful data. + * + * It can be used in the case where you want to signal to holders of your asset that the uncirculated units + * of the asset reside in an account that is different from the default creator account. + * + * If not set or set to the Zero address is permanently empty. + */ + var `reserve`: kotlin.String? = null, + /** + * The address of the optional account that can be used to freeze or unfreeze holdings of this asset for any account. + * + * If empty, freezing is not permitted. + * + * If not set or set to the Zero address is permanently empty. + */ + var `freeze`: kotlin.String? = null, + /** + * The address of the optional account that can clawback holdings of this asset from any account. + * + * **This field should be used with caution** as the clawback account has the ability to **unconditionally take assets from any account**. + * + * If empty, clawback is not permitted. + * + * If not set or set to the Zero address is permanently empty. + */ + var `clawback`: kotlin.String? = null +) { + + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeAssetConfigTransactionFields: FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): AssetConfigTransactionFields { + return AssetConfigTransactionFields( + FfiConverterULong.read(buf), + FfiConverterOptionalULong.read(buf), + FfiConverterOptionalUInt.read(buf), + FfiConverterOptionalBoolean.read(buf), + FfiConverterOptionalString.read(buf), + FfiConverterOptionalString.read(buf), + FfiConverterOptionalString.read(buf), + FfiConverterOptionalByteArray.read(buf), + FfiConverterOptionalString.read(buf), + FfiConverterOptionalString.read(buf), + FfiConverterOptionalString.read(buf), + FfiConverterOptionalString.read(buf), + ) + } + + override fun allocationSize(value: AssetConfigTransactionFields) = ( + FfiConverterULong.allocationSize(value.`assetId`) + + FfiConverterOptionalULong.allocationSize(value.`total`) + + FfiConverterOptionalUInt.allocationSize(value.`decimals`) + + FfiConverterOptionalBoolean.allocationSize(value.`defaultFrozen`) + + FfiConverterOptionalString.allocationSize(value.`assetName`) + + FfiConverterOptionalString.allocationSize(value.`unitName`) + + FfiConverterOptionalString.allocationSize(value.`url`) + + FfiConverterOptionalByteArray.allocationSize(value.`metadataHash`) + + FfiConverterOptionalString.allocationSize(value.`manager`) + + FfiConverterOptionalString.allocationSize(value.`reserve`) + + FfiConverterOptionalString.allocationSize(value.`freeze`) + + FfiConverterOptionalString.allocationSize(value.`clawback`) + ) + + override fun write(value: AssetConfigTransactionFields, buf: ByteBuffer) { + FfiConverterULong.write(value.`assetId`, buf) + FfiConverterOptionalULong.write(value.`total`, buf) + FfiConverterOptionalUInt.write(value.`decimals`, buf) + FfiConverterOptionalBoolean.write(value.`defaultFrozen`, buf) + FfiConverterOptionalString.write(value.`assetName`, buf) + FfiConverterOptionalString.write(value.`unitName`, buf) + FfiConverterOptionalString.write(value.`url`, buf) + FfiConverterOptionalByteArray.write(value.`metadataHash`, buf) + FfiConverterOptionalString.write(value.`manager`, buf) + FfiConverterOptionalString.write(value.`reserve`, buf) + FfiConverterOptionalString.write(value.`freeze`, buf) + FfiConverterOptionalString.write(value.`clawback`, buf) + } +} + + + +/** + * Represents an asset freeze transaction that freezes or unfreezes asset holdings. + * + * Asset freeze transactions are used by the asset freeze account to control + * whether a specific account can transfer a particular asset. + */ +data class AssetFreezeTransactionFields ( + /** + * The ID of the asset being frozen/unfrozen. + */ + var `assetId`: kotlin.ULong, + /** + * The target account whose asset holdings will be affected. + */ + var `freezeTarget`: kotlin.String, + /** + * The new freeze status. + * + * `true` to freeze the asset holdings (prevent transfers), + * `false` to unfreeze the asset holdings (allow transfers). + */ + var `frozen`: kotlin.Boolean +) { + + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeAssetFreezeTransactionFields: FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): AssetFreezeTransactionFields { + return AssetFreezeTransactionFields( + FfiConverterULong.read(buf), + FfiConverterString.read(buf), + FfiConverterBoolean.read(buf), + ) + } + + override fun allocationSize(value: AssetFreezeTransactionFields) = ( + FfiConverterULong.allocationSize(value.`assetId`) + + FfiConverterString.allocationSize(value.`freezeTarget`) + + FfiConverterBoolean.allocationSize(value.`frozen`) + ) + + override fun write(value: AssetFreezeTransactionFields, buf: ByteBuffer) { + FfiConverterULong.write(value.`assetId`, buf) + FfiConverterString.write(value.`freezeTarget`, buf) + FfiConverterBoolean.write(value.`frozen`, buf) + } +} + + + +data class AssetTransferTransactionFields ( + var `assetId`: kotlin.ULong, + var `amount`: kotlin.ULong, + var `receiver`: kotlin.String, + var `assetSender`: kotlin.String? = null, + var `closeRemainderTo`: kotlin.String? = null +) { + + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeAssetTransferTransactionFields: FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): AssetTransferTransactionFields { + return AssetTransferTransactionFields( + FfiConverterULong.read(buf), + FfiConverterULong.read(buf), + FfiConverterString.read(buf), + FfiConverterOptionalString.read(buf), + FfiConverterOptionalString.read(buf), + ) + } + + override fun allocationSize(value: AssetTransferTransactionFields) = ( + FfiConverterULong.allocationSize(value.`assetId`) + + FfiConverterULong.allocationSize(value.`amount`) + + FfiConverterString.allocationSize(value.`receiver`) + + FfiConverterOptionalString.allocationSize(value.`assetSender`) + + FfiConverterOptionalString.allocationSize(value.`closeRemainderTo`) + ) + + override fun write(value: AssetTransferTransactionFields, buf: ByteBuffer) { + FfiConverterULong.write(value.`assetId`, buf) + FfiConverterULong.write(value.`amount`, buf) + FfiConverterString.write(value.`receiver`, buf) + FfiConverterOptionalString.write(value.`assetSender`, buf) + FfiConverterOptionalString.write(value.`closeRemainderTo`, buf) + } +} + + + +/** + * Box reference for app call transactions. + * + * References a specific box that should be made available for the runtime + * of the program. + */ +data class BoxReference ( + /** + * App ID that owns the box. + * A value of 0 indicates the current app. + */ + var `appId`: kotlin.ULong, + /** + * Name of the box. + */ + var `name`: kotlin.ByteArray +) { + + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeBoxReference: FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): BoxReference { + return BoxReference( + FfiConverterULong.read(buf), + FfiConverterByteArray.read(buf), + ) + } + + override fun allocationSize(value: BoxReference) = ( + FfiConverterULong.allocationSize(value.`appId`) + + FfiConverterByteArray.allocationSize(value.`name`) + ) + + override fun write(value: BoxReference, buf: ByteBuffer) { + FfiConverterULong.write(value.`appId`, buf) + FfiConverterByteArray.write(value.`name`, buf) + } +} + + + +/** + * Represents a signature in the merkle signature scheme using falcon signatures + * as an underlying crypto scheme. It consists of an ephemeral public key, a signature, a merkle + * verification path and an index. The merkle signature considered valid only if the Signature is + * verified under the ephemeral public key and the Merkle verification path verifies that the + * ephemeral public key is located at the given index of the tree (for the root given in the + * long-term public key). More details can be found on Algorand's spec + */ +data class FalconSignatureStruct ( + var `signature`: kotlin.ByteArray, + var `vectorCommitmentIndex`: kotlin.ULong, + var `proof`: MerkleArrayProof, + var `verifyingKey`: FalconVerifier +) { + + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeFalconSignatureStruct: FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): FalconSignatureStruct { + return FalconSignatureStruct( + FfiConverterByteArray.read(buf), + FfiConverterULong.read(buf), + FfiConverterTypeMerkleArrayProof.read(buf), + FfiConverterTypeFalconVerifier.read(buf), + ) + } + + override fun allocationSize(value: FalconSignatureStruct) = ( + FfiConverterByteArray.allocationSize(value.`signature`) + + FfiConverterULong.allocationSize(value.`vectorCommitmentIndex`) + + FfiConverterTypeMerkleArrayProof.allocationSize(value.`proof`) + + FfiConverterTypeFalconVerifier.allocationSize(value.`verifyingKey`) + ) + + override fun write(value: FalconSignatureStruct, buf: ByteBuffer) { + FfiConverterByteArray.write(value.`signature`, buf) + FfiConverterULong.write(value.`vectorCommitmentIndex`, buf) + FfiConverterTypeMerkleArrayProof.write(value.`proof`, buf) + FfiConverterTypeFalconVerifier.write(value.`verifyingKey`, buf) + } +} + + + +data class FalconVerifier ( + var `publicKey`: kotlin.ByteArray +) { + + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeFalconVerifier: FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): FalconVerifier { + return FalconVerifier( + FfiConverterByteArray.read(buf), + ) + } + + override fun allocationSize(value: FalconVerifier) = ( + FfiConverterByteArray.allocationSize(value.`publicKey`) + ) + + override fun write(value: FalconVerifier, buf: ByteBuffer) { + FfiConverterByteArray.write(value.`publicKey`, buf) + } +} + + + +data class FeeParams ( + var `feePerByte`: kotlin.ULong, + var `minFee`: kotlin.ULong, + var `extraFee`: kotlin.ULong? = null, + var `maxFee`: kotlin.ULong? = null +) { + + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeFeeParams: FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): FeeParams { + return FeeParams( + FfiConverterULong.read(buf), + FfiConverterULong.read(buf), + FfiConverterOptionalULong.read(buf), + FfiConverterOptionalULong.read(buf), + ) + } + + override fun allocationSize(value: FeeParams) = ( + FfiConverterULong.allocationSize(value.`feePerByte`) + + FfiConverterULong.allocationSize(value.`minFee`) + + FfiConverterOptionalULong.allocationSize(value.`extraFee`) + + FfiConverterOptionalULong.allocationSize(value.`maxFee`) + ) + + override fun write(value: FeeParams, buf: ByteBuffer) { + FfiConverterULong.write(value.`feePerByte`, buf) + FfiConverterULong.write(value.`minFee`, buf) + FfiConverterOptionalULong.write(value.`extraFee`, buf) + FfiConverterOptionalULong.write(value.`maxFee`, buf) + } +} + + + +data class HashFactory ( + var `hashType`: kotlin.ULong +) { + + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeHashFactory: FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): HashFactory { + return HashFactory( + FfiConverterULong.read(buf), + ) + } + + override fun allocationSize(value: HashFactory) = ( + FfiConverterULong.allocationSize(value.`hashType`) + ) + + override fun write(value: HashFactory, buf: ByteBuffer) { + FfiConverterULong.write(value.`hashType`, buf) + } +} + + + +/** + * Parameters for a heartbeat transaction proof. + */ +data class HeartbeatProof ( + /** + * Signature (64 bytes). + */ + var `sig`: kotlin.ByteArray, + /** + * Public key (32 bytes). + */ + var `pk`: kotlin.ByteArray, + /** + * Public key 2 (32 bytes). + */ + var `pk2`: kotlin.ByteArray, + /** + * Public key 1 signature (64 bytes). + */ + var `pk1Sig`: kotlin.ByteArray, + /** + * Public key 2 signature (64 bytes). + */ + var `pk2Sig`: kotlin.ByteArray +) { + + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeHeartbeatProof: FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): HeartbeatProof { + return HeartbeatProof( + FfiConverterByteArray.read(buf), + FfiConverterByteArray.read(buf), + FfiConverterByteArray.read(buf), + FfiConverterByteArray.read(buf), + FfiConverterByteArray.read(buf), + ) + } + + override fun allocationSize(value: HeartbeatProof) = ( + FfiConverterByteArray.allocationSize(value.`sig`) + + FfiConverterByteArray.allocationSize(value.`pk`) + + FfiConverterByteArray.allocationSize(value.`pk2`) + + FfiConverterByteArray.allocationSize(value.`pk1Sig`) + + FfiConverterByteArray.allocationSize(value.`pk2Sig`) + ) + + override fun write(value: HeartbeatProof, buf: ByteBuffer) { + FfiConverterByteArray.write(value.`sig`, buf) + FfiConverterByteArray.write(value.`pk`, buf) + FfiConverterByteArray.write(value.`pk2`, buf) + FfiConverterByteArray.write(value.`pk1Sig`, buf) + FfiConverterByteArray.write(value.`pk2Sig`, buf) + } +} + + + +/** + * Parameters to define a heartbeat transaction. + * + * Used to maintain participation in Algorand consensus. + */ +data class HeartbeatTransactionFields ( + /** + * Heartbeat address. + */ + var `address`: kotlin.String, + /** + * Heartbeat proof. + */ + var `proof`: HeartbeatProof, + /** + * Heartbeat seed. + */ + var `seed`: kotlin.ByteArray, + /** + * Heartbeat vote ID (32 bytes). + */ + var `voteId`: kotlin.ByteArray, + /** + * Heartbeat key dilution. + */ + var `keyDilution`: kotlin.ULong +) { + + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeHeartbeatTransactionFields: FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): HeartbeatTransactionFields { + return HeartbeatTransactionFields( + FfiConverterString.read(buf), + FfiConverterTypeHeartbeatProof.read(buf), + FfiConverterByteArray.read(buf), + FfiConverterByteArray.read(buf), + FfiConverterULong.read(buf), + ) + } + + override fun allocationSize(value: HeartbeatTransactionFields) = ( + FfiConverterString.allocationSize(value.`address`) + + FfiConverterTypeHeartbeatProof.allocationSize(value.`proof`) + + FfiConverterByteArray.allocationSize(value.`seed`) + + FfiConverterByteArray.allocationSize(value.`voteId`) + + FfiConverterULong.allocationSize(value.`keyDilution`) + ) + + override fun write(value: HeartbeatTransactionFields, buf: ByteBuffer) { + FfiConverterString.write(value.`address`, buf) + FfiConverterTypeHeartbeatProof.write(value.`proof`, buf) + FfiConverterByteArray.write(value.`seed`, buf) + FfiConverterByteArray.write(value.`voteId`, buf) + FfiConverterULong.write(value.`keyDilution`, buf) + } +} + + + +data class KeyPairAccount ( + var `pubKey`: kotlin.ByteArray +) { + + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeKeyPairAccount: FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): KeyPairAccount { + return KeyPairAccount( + FfiConverterByteArray.read(buf), + ) + } + + override fun allocationSize(value: KeyPairAccount) = ( + FfiConverterByteArray.allocationSize(value.`pubKey`) + ) + + override fun write(value: KeyPairAccount, buf: ByteBuffer) { + FfiConverterByteArray.write(value.`pubKey`, buf) + } +} + + + +data class KeyRegistrationTransactionFields ( + /** + * Root participation public key (32 bytes) + */ + var `voteKey`: kotlin.ByteArray? = null, + /** + * VRF public key (32 bytes) + */ + var `selectionKey`: kotlin.ByteArray? = null, + /** + * State proof key (64 bytes) + */ + var `stateProofKey`: kotlin.ByteArray? = null, + /** + * First round for which the participation key is valid + */ + var `voteFirst`: kotlin.ULong? = null, + /** + * Last round for which the participation key is valid + */ + var `voteLast`: kotlin.ULong? = null, + /** + * Key dilution for the 2-level participation key + */ + var `voteKeyDilution`: kotlin.ULong? = null, + /** + * Mark account as non-reward earning + */ + var `nonParticipation`: kotlin.Boolean? = null +) { + + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeKeyRegistrationTransactionFields: FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): KeyRegistrationTransactionFields { + return KeyRegistrationTransactionFields( + FfiConverterOptionalByteArray.read(buf), + FfiConverterOptionalByteArray.read(buf), + FfiConverterOptionalByteArray.read(buf), + FfiConverterOptionalULong.read(buf), + FfiConverterOptionalULong.read(buf), + FfiConverterOptionalULong.read(buf), + FfiConverterOptionalBoolean.read(buf), + ) + } + + override fun allocationSize(value: KeyRegistrationTransactionFields) = ( + FfiConverterOptionalByteArray.allocationSize(value.`voteKey`) + + FfiConverterOptionalByteArray.allocationSize(value.`selectionKey`) + + FfiConverterOptionalByteArray.allocationSize(value.`stateProofKey`) + + FfiConverterOptionalULong.allocationSize(value.`voteFirst`) + + FfiConverterOptionalULong.allocationSize(value.`voteLast`) + + FfiConverterOptionalULong.allocationSize(value.`voteKeyDilution`) + + FfiConverterOptionalBoolean.allocationSize(value.`nonParticipation`) + ) + + override fun write(value: KeyRegistrationTransactionFields, buf: ByteBuffer) { + FfiConverterOptionalByteArray.write(value.`voteKey`, buf) + FfiConverterOptionalByteArray.write(value.`selectionKey`, buf) + FfiConverterOptionalByteArray.write(value.`stateProofKey`, buf) + FfiConverterOptionalULong.write(value.`voteFirst`, buf) + FfiConverterOptionalULong.write(value.`voteLast`, buf) + FfiConverterOptionalULong.write(value.`voteKeyDilution`, buf) + FfiConverterOptionalBoolean.write(value.`nonParticipation`, buf) + } +} + + + +data class MerkleArrayProof ( + var `path`: List, + var `hashFactory`: HashFactory, + var `treeDepth`: kotlin.ULong +) { + + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeMerkleArrayProof: FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): MerkleArrayProof { + return MerkleArrayProof( + FfiConverterSequenceByteArray.read(buf), + FfiConverterTypeHashFactory.read(buf), + FfiConverterULong.read(buf), + ) + } + + override fun allocationSize(value: MerkleArrayProof) = ( + FfiConverterSequenceByteArray.allocationSize(value.`path`) + + FfiConverterTypeHashFactory.allocationSize(value.`hashFactory`) + + FfiConverterULong.allocationSize(value.`treeDepth`) + ) + + override fun write(value: MerkleArrayProof, buf: ByteBuffer) { + FfiConverterSequenceByteArray.write(value.`path`, buf) + FfiConverterTypeHashFactory.write(value.`hashFactory`, buf) + FfiConverterULong.write(value.`treeDepth`, buf) + } +} + + + +data class MerkleSignatureVerifier ( + var `commitment`: kotlin.ByteArray, + var `keyLifetime`: kotlin.ULong +) { + + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeMerkleSignatureVerifier: FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): MerkleSignatureVerifier { + return MerkleSignatureVerifier( + FfiConverterByteArray.read(buf), + FfiConverterULong.read(buf), + ) + } + + override fun allocationSize(value: MerkleSignatureVerifier) = ( + FfiConverterByteArray.allocationSize(value.`commitment`) + + FfiConverterULong.allocationSize(value.`keyLifetime`) + ) + + override fun write(value: MerkleSignatureVerifier, buf: ByteBuffer) { + FfiConverterByteArray.write(value.`commitment`, buf) + FfiConverterULong.write(value.`keyLifetime`, buf) + } +} + + + +/** + * Representation of an Algorand multisignature signature. + */ +data class MultisigSignature ( + /** + * Multisig version. + */ + var `version`: kotlin.UByte, + /** + * Minimum number of signatures required. + */ + var `threshold`: kotlin.UByte, + /** + * List of subsignatures for each participant. + */ + var `subsignatures`: List +) { + + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeMultisigSignature: FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): MultisigSignature { + return MultisigSignature( + FfiConverterUByte.read(buf), + FfiConverterUByte.read(buf), + FfiConverterSequenceTypeMultisigSubsignature.read(buf), + ) + } + + override fun allocationSize(value: MultisigSignature) = ( + FfiConverterUByte.allocationSize(value.`version`) + + FfiConverterUByte.allocationSize(value.`threshold`) + + FfiConverterSequenceTypeMultisigSubsignature.allocationSize(value.`subsignatures`) + ) + + override fun write(value: MultisigSignature, buf: ByteBuffer) { + FfiConverterUByte.write(value.`version`, buf) + FfiConverterUByte.write(value.`threshold`, buf) + FfiConverterSequenceTypeMultisigSubsignature.write(value.`subsignatures`, buf) + } +} + + + +/** + * Representation of a single subsignature in a multisignature transaction. + * + * Each subsignature contains the participant's address and an optional signature. + */ +data class MultisigSubsignature ( + /** + * Address of the participant. + */ + var `address`: kotlin.String, + /** + * Optional signature bytes for the participant. + */ + var `signature`: kotlin.ByteArray? = null +) { + + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeMultisigSubsignature: FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): MultisigSubsignature { + return MultisigSubsignature( + FfiConverterString.read(buf), + FfiConverterOptionalByteArray.read(buf), + ) + } + + override fun allocationSize(value: MultisigSubsignature) = ( + FfiConverterString.allocationSize(value.`address`) + + FfiConverterOptionalByteArray.allocationSize(value.`signature`) + ) + + override fun write(value: MultisigSubsignature, buf: ByteBuffer) { + FfiConverterString.write(value.`address`, buf) + FfiConverterOptionalByteArray.write(value.`signature`, buf) + } +} + + + +/** + * A Participant corresponds to an account whose AccountData.Status is Online, and for which the + * expected sigRound satisfies AccountData.VoteFirstValid <= sigRound <= AccountData.VoteLastValid. + * + * In the Algorand ledger, it is possible for multiple accounts to have the same PK. Thus, the PK is + * not necessarily unique among Participants. However, each account will produce a unique Participant + * struct, to avoid potential DoS attacks where one account claims to have the same VoteID PK as + * another account. + */ +data class Participant ( + var `verifier`: MerkleSignatureVerifier, + var `weight`: kotlin.ULong +) { + + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeParticipant: FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): Participant { + return Participant( + FfiConverterTypeMerkleSignatureVerifier.read(buf), + FfiConverterULong.read(buf), + ) + } + + override fun allocationSize(value: Participant) = ( + FfiConverterTypeMerkleSignatureVerifier.allocationSize(value.`verifier`) + + FfiConverterULong.allocationSize(value.`weight`) + ) + + override fun write(value: Participant, buf: ByteBuffer) { + FfiConverterTypeMerkleSignatureVerifier.write(value.`verifier`, buf) + FfiConverterULong.write(value.`weight`, buf) + } +} + + + +data class PaymentTransactionFields ( + var `receiver`: kotlin.String, + var `amount`: kotlin.ULong, + var `closeRemainderTo`: kotlin.String? = null +) { + + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypePaymentTransactionFields: FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): PaymentTransactionFields { + return PaymentTransactionFields( + FfiConverterString.read(buf), + FfiConverterULong.read(buf), + FfiConverterOptionalString.read(buf), + ) + } + + override fun allocationSize(value: PaymentTransactionFields) = ( + FfiConverterString.allocationSize(value.`receiver`) + + FfiConverterULong.allocationSize(value.`amount`) + + FfiConverterOptionalString.allocationSize(value.`closeRemainderTo`) + ) + + override fun write(value: PaymentTransactionFields, buf: ByteBuffer) { + FfiConverterString.write(value.`receiver`, buf) + FfiConverterULong.write(value.`amount`, buf) + FfiConverterOptionalString.write(value.`closeRemainderTo`, buf) + } +} + + + +/** + * A single array position revealed as part of a state proof. It reveals an element of the + * signature array and the corresponding element of the participants array. + */ +data class Reveal ( + var `position`: kotlin.ULong, + var `sigslot`: SigslotCommit, + var `participant`: Participant +) { + + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeReveal: FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): Reveal { + return Reveal( + FfiConverterULong.read(buf), + FfiConverterTypeSigslotCommit.read(buf), + FfiConverterTypeParticipant.read(buf), + ) + } + + override fun allocationSize(value: Reveal) = ( + FfiConverterULong.allocationSize(value.`position`) + + FfiConverterTypeSigslotCommit.allocationSize(value.`sigslot`) + + FfiConverterTypeParticipant.allocationSize(value.`participant`) + ) + + override fun write(value: Reveal, buf: ByteBuffer) { + FfiConverterULong.write(value.`position`, buf) + FfiConverterTypeSigslotCommit.write(value.`sigslot`, buf) + FfiConverterTypeParticipant.write(value.`participant`, buf) + } +} + + + +data class SignedTransaction ( + /** + * The transaction that has been signed. + */ + var `transaction`: Transaction, + /** + * Optional Ed25519 signature authorizing the transaction. + */ + var `signature`: kotlin.ByteArray? = null, + /** + * Optional auth address applicable if the transaction sender is a rekeyed account. + */ + var `authAddress`: kotlin.String? = null, + /** + * Optional multisig signature if the transaction is a multisig transaction. + */ + var `multisignature`: MultisigSignature? = null +) { + + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeSignedTransaction: FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): SignedTransaction { + return SignedTransaction( + FfiConverterTypeTransaction.read(buf), + FfiConverterOptionalByteArray.read(buf), + FfiConverterOptionalString.read(buf), + FfiConverterOptionalTypeMultisigSignature.read(buf), + ) + } + + override fun allocationSize(value: SignedTransaction) = ( + FfiConverterTypeTransaction.allocationSize(value.`transaction`) + + FfiConverterOptionalByteArray.allocationSize(value.`signature`) + + FfiConverterOptionalString.allocationSize(value.`authAddress`) + + FfiConverterOptionalTypeMultisigSignature.allocationSize(value.`multisignature`) + ) + + override fun write(value: SignedTransaction, buf: ByteBuffer) { + FfiConverterTypeTransaction.write(value.`transaction`, buf) + FfiConverterOptionalByteArray.write(value.`signature`, buf) + FfiConverterOptionalString.write(value.`authAddress`, buf) + FfiConverterOptionalTypeMultisigSignature.write(value.`multisignature`, buf) + } +} + + + +data class SigslotCommit ( + var `sig`: FalconSignatureStruct, + var `lowerSigWeight`: kotlin.ULong +) { + + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeSigslotCommit: FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): SigslotCommit { + return SigslotCommit( + FfiConverterTypeFalconSignatureStruct.read(buf), + FfiConverterULong.read(buf), + ) + } + + override fun allocationSize(value: SigslotCommit) = ( + FfiConverterTypeFalconSignatureStruct.allocationSize(value.`sig`) + + FfiConverterULong.allocationSize(value.`lowerSigWeight`) + ) + + override fun write(value: SigslotCommit, buf: ByteBuffer) { + FfiConverterTypeFalconSignatureStruct.write(value.`sig`, buf) + FfiConverterULong.write(value.`lowerSigWeight`, buf) + } +} + + + +data class StateProof ( + var `sigCommit`: kotlin.ByteArray, + var `signedWeight`: kotlin.ULong, + var `sigProofs`: MerkleArrayProof, + var `partProofs`: MerkleArrayProof, + var `merkleSignatureSaltVersion`: kotlin.ULong, + var `reveals`: List, + var `positionsToReveal`: List +) { + + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeStateProof: FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): StateProof { + return StateProof( + FfiConverterByteArray.read(buf), + FfiConverterULong.read(buf), + FfiConverterTypeMerkleArrayProof.read(buf), + FfiConverterTypeMerkleArrayProof.read(buf), + FfiConverterULong.read(buf), + FfiConverterSequenceTypeReveal.read(buf), + FfiConverterSequenceULong.read(buf), + ) + } + + override fun allocationSize(value: StateProof) = ( + FfiConverterByteArray.allocationSize(value.`sigCommit`) + + FfiConverterULong.allocationSize(value.`signedWeight`) + + FfiConverterTypeMerkleArrayProof.allocationSize(value.`sigProofs`) + + FfiConverterTypeMerkleArrayProof.allocationSize(value.`partProofs`) + + FfiConverterULong.allocationSize(value.`merkleSignatureSaltVersion`) + + FfiConverterSequenceTypeReveal.allocationSize(value.`reveals`) + + FfiConverterSequenceULong.allocationSize(value.`positionsToReveal`) + ) + + override fun write(value: StateProof, buf: ByteBuffer) { + FfiConverterByteArray.write(value.`sigCommit`, buf) + FfiConverterULong.write(value.`signedWeight`, buf) + FfiConverterTypeMerkleArrayProof.write(value.`sigProofs`, buf) + FfiConverterTypeMerkleArrayProof.write(value.`partProofs`, buf) + FfiConverterULong.write(value.`merkleSignatureSaltVersion`, buf) + FfiConverterSequenceTypeReveal.write(value.`reveals`, buf) + FfiConverterSequenceULong.write(value.`positionsToReveal`, buf) + } +} + + + +data class StateProofMessage ( + var `blockHeadersCommitment`: kotlin.ByteArray, + var `votersCommitment`: kotlin.ByteArray, + var `lnProvenWeight`: kotlin.ULong, + var `firstAttestedRound`: kotlin.ULong, + var `lastAttestedRound`: kotlin.ULong +) { + + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeStateProofMessage: FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): StateProofMessage { + return StateProofMessage( + FfiConverterByteArray.read(buf), + FfiConverterByteArray.read(buf), + FfiConverterULong.read(buf), + FfiConverterULong.read(buf), + FfiConverterULong.read(buf), + ) + } + + override fun allocationSize(value: StateProofMessage) = ( + FfiConverterByteArray.allocationSize(value.`blockHeadersCommitment`) + + FfiConverterByteArray.allocationSize(value.`votersCommitment`) + + FfiConverterULong.allocationSize(value.`lnProvenWeight`) + + FfiConverterULong.allocationSize(value.`firstAttestedRound`) + + FfiConverterULong.allocationSize(value.`lastAttestedRound`) + ) + + override fun write(value: StateProofMessage, buf: ByteBuffer) { + FfiConverterByteArray.write(value.`blockHeadersCommitment`, buf) + FfiConverterByteArray.write(value.`votersCommitment`, buf) + FfiConverterULong.write(value.`lnProvenWeight`, buf) + FfiConverterULong.write(value.`firstAttestedRound`, buf) + FfiConverterULong.write(value.`lastAttestedRound`, buf) + } +} + + + +data class StateProofTransactionFields ( + var `stateProofType`: kotlin.ULong? = null, + var `stateProof`: StateProof? = null, + var `message`: StateProofMessage? = null +) { + + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeStateProofTransactionFields: FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): StateProofTransactionFields { + return StateProofTransactionFields( + FfiConverterOptionalULong.read(buf), + FfiConverterOptionalTypeStateProof.read(buf), + FfiConverterOptionalTypeStateProofMessage.read(buf), + ) + } + + override fun allocationSize(value: StateProofTransactionFields) = ( + FfiConverterOptionalULong.allocationSize(value.`stateProofType`) + + FfiConverterOptionalTypeStateProof.allocationSize(value.`stateProof`) + + FfiConverterOptionalTypeStateProofMessage.allocationSize(value.`message`) + ) + + override fun write(value: StateProofTransactionFields, buf: ByteBuffer) { + FfiConverterOptionalULong.write(value.`stateProofType`, buf) + FfiConverterOptionalTypeStateProof.write(value.`stateProof`, buf) + FfiConverterOptionalTypeStateProofMessage.write(value.`message`, buf) + } +} + + + +/** + * Schema for app state storage. + * + * Defines the maximum number of values that may be stored in app + * key/value storage for both global and local state. + */ +data class StateSchema ( + /** + * Maximum number of integer values that may be stored. + */ + var `numUints`: kotlin.UInt, + /** + * Maximum number of byte slice values that may be stored. + */ + var `numByteSlices`: kotlin.UInt +) { + + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeStateSchema: FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): StateSchema { + return StateSchema( + FfiConverterUInt.read(buf), + FfiConverterUInt.read(buf), + ) + } + + override fun allocationSize(value: StateSchema) = ( + FfiConverterUInt.allocationSize(value.`numUints`) + + FfiConverterUInt.allocationSize(value.`numByteSlices`) + ) + + override fun write(value: StateSchema, buf: ByteBuffer) { + FfiConverterUInt.write(value.`numUints`, buf) + FfiConverterUInt.write(value.`numByteSlices`, buf) + } +} + + + +data class Transaction ( + /** + * The type of transaction + */ + var `transactionType`: TransactionType, + /** + * The sender of the transaction + */ + var `sender`: kotlin.String, + /** + * Optional transaction fee in microALGO. + * + * If not set, the fee will be interpreted as 0 by the network. + */ + var `fee`: kotlin.ULong? = null, + var `firstValid`: kotlin.ULong, + var `lastValid`: kotlin.ULong, + var `genesisHash`: kotlin.ByteArray?, + var `genesisId`: kotlin.String?, + var `note`: kotlin.ByteArray? = null, + var `rekeyTo`: kotlin.String? = null, + var `lease`: kotlin.ByteArray? = null, + var `group`: kotlin.ByteArray? = null, + var `payment`: PaymentTransactionFields? = null, + var `assetTransfer`: AssetTransferTransactionFields? = null, + var `assetConfig`: AssetConfigTransactionFields? = null, + var `appCall`: AppCallTransactionFields? = null, + var `keyRegistration`: KeyRegistrationTransactionFields? = null, + var `assetFreeze`: AssetFreezeTransactionFields? = null, + var `heartbeat`: HeartbeatTransactionFields? = null, + var `stateProof`: StateProofTransactionFields? = null +) { + + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeTransaction: FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): Transaction { + return Transaction( + FfiConverterTypeTransactionType.read(buf), + FfiConverterString.read(buf), + FfiConverterOptionalULong.read(buf), + FfiConverterULong.read(buf), + FfiConverterULong.read(buf), + FfiConverterOptionalByteArray.read(buf), + FfiConverterOptionalString.read(buf), + FfiConverterOptionalByteArray.read(buf), + FfiConverterOptionalString.read(buf), + FfiConverterOptionalByteArray.read(buf), + FfiConverterOptionalByteArray.read(buf), + FfiConverterOptionalTypePaymentTransactionFields.read(buf), + FfiConverterOptionalTypeAssetTransferTransactionFields.read(buf), + FfiConverterOptionalTypeAssetConfigTransactionFields.read(buf), + FfiConverterOptionalTypeAppCallTransactionFields.read(buf), + FfiConverterOptionalTypeKeyRegistrationTransactionFields.read(buf), + FfiConverterOptionalTypeAssetFreezeTransactionFields.read(buf), + FfiConverterOptionalTypeHeartbeatTransactionFields.read(buf), + FfiConverterOptionalTypeStateProofTransactionFields.read(buf), + ) + } + + override fun allocationSize(value: Transaction) = ( + FfiConverterTypeTransactionType.allocationSize(value.`transactionType`) + + FfiConverterString.allocationSize(value.`sender`) + + FfiConverterOptionalULong.allocationSize(value.`fee`) + + FfiConverterULong.allocationSize(value.`firstValid`) + + FfiConverterULong.allocationSize(value.`lastValid`) + + FfiConverterOptionalByteArray.allocationSize(value.`genesisHash`) + + FfiConverterOptionalString.allocationSize(value.`genesisId`) + + FfiConverterOptionalByteArray.allocationSize(value.`note`) + + FfiConverterOptionalString.allocationSize(value.`rekeyTo`) + + FfiConverterOptionalByteArray.allocationSize(value.`lease`) + + FfiConverterOptionalByteArray.allocationSize(value.`group`) + + FfiConverterOptionalTypePaymentTransactionFields.allocationSize(value.`payment`) + + FfiConverterOptionalTypeAssetTransferTransactionFields.allocationSize(value.`assetTransfer`) + + FfiConverterOptionalTypeAssetConfigTransactionFields.allocationSize(value.`assetConfig`) + + FfiConverterOptionalTypeAppCallTransactionFields.allocationSize(value.`appCall`) + + FfiConverterOptionalTypeKeyRegistrationTransactionFields.allocationSize(value.`keyRegistration`) + + FfiConverterOptionalTypeAssetFreezeTransactionFields.allocationSize(value.`assetFreeze`) + + FfiConverterOptionalTypeHeartbeatTransactionFields.allocationSize(value.`heartbeat`) + + FfiConverterOptionalTypeStateProofTransactionFields.allocationSize(value.`stateProof`) + ) + + override fun write(value: Transaction, buf: ByteBuffer) { + FfiConverterTypeTransactionType.write(value.`transactionType`, buf) + FfiConverterString.write(value.`sender`, buf) + FfiConverterOptionalULong.write(value.`fee`, buf) + FfiConverterULong.write(value.`firstValid`, buf) + FfiConverterULong.write(value.`lastValid`, buf) + FfiConverterOptionalByteArray.write(value.`genesisHash`, buf) + FfiConverterOptionalString.write(value.`genesisId`, buf) + FfiConverterOptionalByteArray.write(value.`note`, buf) + FfiConverterOptionalString.write(value.`rekeyTo`, buf) + FfiConverterOptionalByteArray.write(value.`lease`, buf) + FfiConverterOptionalByteArray.write(value.`group`, buf) + FfiConverterOptionalTypePaymentTransactionFields.write(value.`payment`, buf) + FfiConverterOptionalTypeAssetTransferTransactionFields.write(value.`assetTransfer`, buf) + FfiConverterOptionalTypeAssetConfigTransactionFields.write(value.`assetConfig`, buf) + FfiConverterOptionalTypeAppCallTransactionFields.write(value.`appCall`, buf) + FfiConverterOptionalTypeKeyRegistrationTransactionFields.write(value.`keyRegistration`, buf) + FfiConverterOptionalTypeAssetFreezeTransactionFields.write(value.`assetFreeze`, buf) + FfiConverterOptionalTypeHeartbeatTransactionFields.write(value.`heartbeat`, buf) + FfiConverterOptionalTypeStateProofTransactionFields.write(value.`stateProof`, buf) + } +} + + + + + +sealed class AlgoKitTransactException: kotlin.Exception() { + + class EncodingException( + + val `errorMsg`: kotlin.String + ) : AlgoKitTransactException() { + override val message + get() = "errorMsg=${ `errorMsg` }" + } + + class DecodingException( + + val `errorMsg`: kotlin.String + ) : AlgoKitTransactException() { + override val message + get() = "errorMsg=${ `errorMsg` }" + } + + class InputException( + + val `errorMsg`: kotlin.String + ) : AlgoKitTransactException() { + override val message + get() = "errorMsg=${ `errorMsg` }" + } + + class MsgPackException( + + val `errorMsg`: kotlin.String + ) : AlgoKitTransactException() { + override val message + get() = "errorMsg=${ `errorMsg` }" + } + + + companion object ErrorHandler : UniffiRustCallStatusErrorHandler { + override fun lift(error_buf: RustBuffer.ByValue): AlgoKitTransactException = FfiConverterTypeAlgoKitTransactError.lift(error_buf) + } + + +} + +/** + * @suppress + */ +public object FfiConverterTypeAlgoKitTransactError : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): AlgoKitTransactException { + + + return when(buf.getInt()) { + 1 -> AlgoKitTransactException.EncodingException( + FfiConverterString.read(buf), + ) + 2 -> AlgoKitTransactException.DecodingException( + FfiConverterString.read(buf), + ) + 3 -> AlgoKitTransactException.InputException( + FfiConverterString.read(buf), + ) + 4 -> AlgoKitTransactException.MsgPackException( + FfiConverterString.read(buf), + ) + else -> throw RuntimeException("invalid error enum value, something is very wrong!!") + } + } + + override fun allocationSize(value: AlgoKitTransactException): ULong { + return when(value) { + is AlgoKitTransactException.EncodingException -> ( + // Add the size for the Int that specifies the variant plus the size needed for all fields + 4UL + + FfiConverterString.allocationSize(value.`errorMsg`) + ) + is AlgoKitTransactException.DecodingException -> ( + // Add the size for the Int that specifies the variant plus the size needed for all fields + 4UL + + FfiConverterString.allocationSize(value.`errorMsg`) + ) + is AlgoKitTransactException.InputException -> ( + // Add the size for the Int that specifies the variant plus the size needed for all fields + 4UL + + FfiConverterString.allocationSize(value.`errorMsg`) + ) + is AlgoKitTransactException.MsgPackException -> ( + // Add the size for the Int that specifies the variant plus the size needed for all fields + 4UL + + FfiConverterString.allocationSize(value.`errorMsg`) + ) + } + } + + override fun write(value: AlgoKitTransactException, buf: ByteBuffer) { + when(value) { + is AlgoKitTransactException.EncodingException -> { + buf.putInt(1) + FfiConverterString.write(value.`errorMsg`, buf) + Unit + } + is AlgoKitTransactException.DecodingException -> { + buf.putInt(2) + FfiConverterString.write(value.`errorMsg`, buf) + Unit + } + is AlgoKitTransactException.InputException -> { + buf.putInt(3) + FfiConverterString.write(value.`errorMsg`, buf) + Unit + } + is AlgoKitTransactException.MsgPackException -> { + buf.putInt(4) + FfiConverterString.write(value.`errorMsg`, buf) + Unit + } + }.let { /* this makes the `when` an expression, which ensures it is exhaustive */ } + } + +} + + + +/** + * Enum containing all constants used in this crate. + */ + +enum class AlgorandConstant { + + /** + * Length of hash digests (32) + */ + HASH_LENGTH, + /** + * Length of the checksum used in Algorand addresses (4) + */ + CHECKSUM_LENGTH, + /** + * Length of a base32-encoded Algorand address (58) + */ + ADDRESS_LENGTH, + /** + * Length of an Algorand public key in bytes (32) + */ + PUBLIC_KEY_LENGTH, + /** + * Length of an Algorand secret key in bytes (32) + */ + SECRET_KEY_LENGTH, + /** + * Length of an Algorand signature in bytes (64) + */ + SIGNATURE_LENGTH, + /** + * Increment in the encoded byte size when a signature is attached to a transaction (75) + */ + SIGNATURE_ENCODING_INCR_LENGTH, + /** + * The maximum number of transactions in a group (16) + */ + MAX_TX_GROUP_SIZE; + companion object +} + + +/** + * @suppress + */ +public object FfiConverterTypeAlgorandConstant: FfiConverterRustBuffer { + override fun read(buf: ByteBuffer) = try { + AlgorandConstant.values()[buf.getInt() - 1] + } catch (e: IndexOutOfBoundsException) { + throw RuntimeException("invalid enum value, something is very wrong!!", e) + } + + override fun allocationSize(value: AlgorandConstant) = 4UL + + override fun write(value: AlgorandConstant, buf: ByteBuffer) { + buf.putInt(value.ordinal + 1) + } +} + + + + + +/** + * On-completion actions for app transactions. + * + * These values define what additional actions occur with the transaction. + */ + +enum class OnApplicationComplete { + + /** + * NoOp indicates that an app transaction will simply call its + * approval program without any additional action. + */ + NO_OP, + /** + * OptIn indicates that an app transaction will allocate some + * local state for the app in the sender's account. + */ + OPT_IN, + /** + * CloseOut indicates that an app transaction will deallocate + * some local state for the app from the user's account. + */ + CLOSE_OUT, + /** + * ClearState is similar to CloseOut, but may never fail. This + * allows users to reclaim their minimum balance from an app + * they no longer wish to opt in to. + */ + CLEAR_STATE, + /** + * UpdateApplication indicates that an app transaction will + * update the approval program and clear state program for the app. + */ + UPDATE_APPLICATION, + /** + * DeleteApplication indicates that an app transaction will + * delete the app parameters for the app from the creator's + * balance record. + */ + DELETE_APPLICATION; + companion object +} + + +/** + * @suppress + */ +public object FfiConverterTypeOnApplicationComplete: FfiConverterRustBuffer { + override fun read(buf: ByteBuffer) = try { + OnApplicationComplete.values()[buf.getInt() - 1] + } catch (e: IndexOutOfBoundsException) { + throw RuntimeException("invalid enum value, something is very wrong!!", e) + } + + override fun allocationSize(value: OnApplicationComplete) = 4UL + + override fun write(value: OnApplicationComplete, buf: ByteBuffer) { + buf.putInt(value.ordinal + 1) + } +} + + + + + + +enum class TransactionType { + + PAYMENT, + ASSET_TRANSFER, + ASSET_FREEZE, + ASSET_CONFIG, + KEY_REGISTRATION, + APP_CALL, + HEARTBEAT, + STATE_PROOF; + companion object +} + + +/** + * @suppress + */ +public object FfiConverterTypeTransactionType: FfiConverterRustBuffer { + override fun read(buf: ByteBuffer) = try { + TransactionType.values()[buf.getInt() - 1] + } catch (e: IndexOutOfBoundsException) { + throw RuntimeException("invalid enum value, something is very wrong!!", e) + } + + override fun allocationSize(value: TransactionType) = 4UL + + override fun write(value: TransactionType, buf: ByteBuffer) { + buf.putInt(value.ordinal + 1) + } +} + + + + + + +/** + * @suppress + */ +public object FfiConverterOptionalUInt: FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): kotlin.UInt? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterUInt.read(buf) + } + + override fun allocationSize(value: kotlin.UInt?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterUInt.allocationSize(value) + } + } + + override fun write(value: kotlin.UInt?, buf: ByteBuffer) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterUInt.write(value, buf) + } + } +} + + + + +/** + * @suppress + */ +public object FfiConverterOptionalULong: FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): kotlin.ULong? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterULong.read(buf) + } + + override fun allocationSize(value: kotlin.ULong?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterULong.allocationSize(value) + } + } + + override fun write(value: kotlin.ULong?, buf: ByteBuffer) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterULong.write(value, buf) + } + } +} + + + + +/** + * @suppress + */ +public object FfiConverterOptionalBoolean: FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): kotlin.Boolean? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterBoolean.read(buf) + } + + override fun allocationSize(value: kotlin.Boolean?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterBoolean.allocationSize(value) + } + } + + override fun write(value: kotlin.Boolean?, buf: ByteBuffer) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterBoolean.write(value, buf) + } + } +} + + + + +/** + * @suppress + */ +public object FfiConverterOptionalString: FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): kotlin.String? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterString.read(buf) + } + + override fun allocationSize(value: kotlin.String?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterString.allocationSize(value) + } + } + + override fun write(value: kotlin.String?, buf: ByteBuffer) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterString.write(value, buf) + } + } +} + + + + +/** + * @suppress + */ +public object FfiConverterOptionalByteArray: FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): kotlin.ByteArray? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterByteArray.read(buf) + } + + override fun allocationSize(value: kotlin.ByteArray?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterByteArray.allocationSize(value) + } + } + + override fun write(value: kotlin.ByteArray?, buf: ByteBuffer) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterByteArray.write(value, buf) + } + } +} + + + + +/** + * @suppress + */ +public object FfiConverterOptionalTypeAppCallTransactionFields: FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): AppCallTransactionFields? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterTypeAppCallTransactionFields.read(buf) + } + + override fun allocationSize(value: AppCallTransactionFields?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterTypeAppCallTransactionFields.allocationSize(value) + } + } + + override fun write(value: AppCallTransactionFields?, buf: ByteBuffer) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterTypeAppCallTransactionFields.write(value, buf) + } + } +} + + + + +/** + * @suppress + */ +public object FfiConverterOptionalTypeAssetConfigTransactionFields: FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): AssetConfigTransactionFields? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterTypeAssetConfigTransactionFields.read(buf) + } + + override fun allocationSize(value: AssetConfigTransactionFields?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterTypeAssetConfigTransactionFields.allocationSize(value) + } + } + + override fun write(value: AssetConfigTransactionFields?, buf: ByteBuffer) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterTypeAssetConfigTransactionFields.write(value, buf) + } + } +} + + + + +/** + * @suppress + */ +public object FfiConverterOptionalTypeAssetFreezeTransactionFields: FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): AssetFreezeTransactionFields? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterTypeAssetFreezeTransactionFields.read(buf) + } + + override fun allocationSize(value: AssetFreezeTransactionFields?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterTypeAssetFreezeTransactionFields.allocationSize(value) + } + } + + override fun write(value: AssetFreezeTransactionFields?, buf: ByteBuffer) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterTypeAssetFreezeTransactionFields.write(value, buf) + } + } +} + + + + +/** + * @suppress + */ +public object FfiConverterOptionalTypeAssetTransferTransactionFields: FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): AssetTransferTransactionFields? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterTypeAssetTransferTransactionFields.read(buf) + } + + override fun allocationSize(value: AssetTransferTransactionFields?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterTypeAssetTransferTransactionFields.allocationSize(value) + } + } + + override fun write(value: AssetTransferTransactionFields?, buf: ByteBuffer) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterTypeAssetTransferTransactionFields.write(value, buf) + } + } +} + + + + +/** + * @suppress + */ +public object FfiConverterOptionalTypeHeartbeatTransactionFields: FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): HeartbeatTransactionFields? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterTypeHeartbeatTransactionFields.read(buf) + } + + override fun allocationSize(value: HeartbeatTransactionFields?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterTypeHeartbeatTransactionFields.allocationSize(value) + } + } + + override fun write(value: HeartbeatTransactionFields?, buf: ByteBuffer) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterTypeHeartbeatTransactionFields.write(value, buf) + } + } +} + + + + +/** + * @suppress + */ +public object FfiConverterOptionalTypeKeyRegistrationTransactionFields: FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): KeyRegistrationTransactionFields? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterTypeKeyRegistrationTransactionFields.read(buf) + } + + override fun allocationSize(value: KeyRegistrationTransactionFields?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterTypeKeyRegistrationTransactionFields.allocationSize(value) + } + } + + override fun write(value: KeyRegistrationTransactionFields?, buf: ByteBuffer) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterTypeKeyRegistrationTransactionFields.write(value, buf) + } + } +} + + + + +/** + * @suppress + */ +public object FfiConverterOptionalTypeMultisigSignature: FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): MultisigSignature? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterTypeMultisigSignature.read(buf) + } + + override fun allocationSize(value: MultisigSignature?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterTypeMultisigSignature.allocationSize(value) + } + } + + override fun write(value: MultisigSignature?, buf: ByteBuffer) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterTypeMultisigSignature.write(value, buf) + } + } +} + + + + +/** + * @suppress + */ +public object FfiConverterOptionalTypePaymentTransactionFields: FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): PaymentTransactionFields? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterTypePaymentTransactionFields.read(buf) + } + + override fun allocationSize(value: PaymentTransactionFields?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterTypePaymentTransactionFields.allocationSize(value) + } + } + + override fun write(value: PaymentTransactionFields?, buf: ByteBuffer) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterTypePaymentTransactionFields.write(value, buf) + } + } +} + + + + +/** + * @suppress + */ +public object FfiConverterOptionalTypeStateProof: FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): StateProof? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterTypeStateProof.read(buf) + } + + override fun allocationSize(value: StateProof?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterTypeStateProof.allocationSize(value) + } + } + + override fun write(value: StateProof?, buf: ByteBuffer) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterTypeStateProof.write(value, buf) + } + } +} + + + + +/** + * @suppress + */ +public object FfiConverterOptionalTypeStateProofMessage: FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): StateProofMessage? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterTypeStateProofMessage.read(buf) + } + + override fun allocationSize(value: StateProofMessage?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterTypeStateProofMessage.allocationSize(value) + } + } + + override fun write(value: StateProofMessage?, buf: ByteBuffer) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterTypeStateProofMessage.write(value, buf) + } + } +} + + + + +/** + * @suppress + */ +public object FfiConverterOptionalTypeStateProofTransactionFields: FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): StateProofTransactionFields? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterTypeStateProofTransactionFields.read(buf) + } + + override fun allocationSize(value: StateProofTransactionFields?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterTypeStateProofTransactionFields.allocationSize(value) + } + } + + override fun write(value: StateProofTransactionFields?, buf: ByteBuffer) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterTypeStateProofTransactionFields.write(value, buf) + } + } +} + + + + +/** + * @suppress + */ +public object FfiConverterOptionalTypeStateSchema: FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): StateSchema? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterTypeStateSchema.read(buf) + } + + override fun allocationSize(value: StateSchema?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterTypeStateSchema.allocationSize(value) + } + } + + override fun write(value: StateSchema?, buf: ByteBuffer) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterTypeStateSchema.write(value, buf) + } + } +} + + + + +/** + * @suppress + */ +public object FfiConverterOptionalSequenceULong: FfiConverterRustBuffer?> { + override fun read(buf: ByteBuffer): List? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterSequenceULong.read(buf) + } + + override fun allocationSize(value: List?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterSequenceULong.allocationSize(value) + } + } + + override fun write(value: List?, buf: ByteBuffer) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterSequenceULong.write(value, buf) + } + } +} + + + + +/** + * @suppress + */ +public object FfiConverterOptionalSequenceString: FfiConverterRustBuffer?> { + override fun read(buf: ByteBuffer): List? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterSequenceString.read(buf) + } + + override fun allocationSize(value: List?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterSequenceString.allocationSize(value) + } + } + + override fun write(value: List?, buf: ByteBuffer) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterSequenceString.write(value, buf) + } + } +} + + + + +/** + * @suppress + */ +public object FfiConverterOptionalSequenceByteArray: FfiConverterRustBuffer?> { + override fun read(buf: ByteBuffer): List? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterSequenceByteArray.read(buf) + } + + override fun allocationSize(value: List?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterSequenceByteArray.allocationSize(value) + } + } + + override fun write(value: List?, buf: ByteBuffer) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterSequenceByteArray.write(value, buf) + } + } +} + + + + +/** + * @suppress + */ +public object FfiConverterOptionalSequenceTypeBoxReference: FfiConverterRustBuffer?> { + override fun read(buf: ByteBuffer): List? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterSequenceTypeBoxReference.read(buf) + } + + override fun allocationSize(value: List?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterSequenceTypeBoxReference.allocationSize(value) + } + } + + override fun write(value: List?, buf: ByteBuffer) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterSequenceTypeBoxReference.write(value, buf) + } + } +} + + + + +/** + * @suppress + */ +public object FfiConverterSequenceULong: FfiConverterRustBuffer> { + override fun read(buf: ByteBuffer): List { + val len = buf.getInt() + return List(len) { + FfiConverterULong.read(buf) + } + } + + override fun allocationSize(value: List): ULong { + val sizeForLength = 4UL + val sizeForItems = value.map { FfiConverterULong.allocationSize(it) }.sum() + return sizeForLength + sizeForItems + } + + override fun write(value: List, buf: ByteBuffer) { + buf.putInt(value.size) + value.iterator().forEach { + FfiConverterULong.write(it, buf) + } + } +} + + + + +/** + * @suppress + */ +public object FfiConverterSequenceString: FfiConverterRustBuffer> { + override fun read(buf: ByteBuffer): List { + val len = buf.getInt() + return List(len) { + FfiConverterString.read(buf) + } + } + + override fun allocationSize(value: List): ULong { + val sizeForLength = 4UL + val sizeForItems = value.map { FfiConverterString.allocationSize(it) }.sum() + return sizeForLength + sizeForItems + } + + override fun write(value: List, buf: ByteBuffer) { + buf.putInt(value.size) + value.iterator().forEach { + FfiConverterString.write(it, buf) + } + } +} + + + + +/** + * @suppress + */ +public object FfiConverterSequenceByteArray: FfiConverterRustBuffer> { + override fun read(buf: ByteBuffer): List { + val len = buf.getInt() + return List(len) { + FfiConverterByteArray.read(buf) + } + } + + override fun allocationSize(value: List): ULong { + val sizeForLength = 4UL + val sizeForItems = value.map { FfiConverterByteArray.allocationSize(it) }.sum() + return sizeForLength + sizeForItems + } + + override fun write(value: List, buf: ByteBuffer) { + buf.putInt(value.size) + value.iterator().forEach { + FfiConverterByteArray.write(it, buf) + } + } +} + + + + +/** + * @suppress + */ +public object FfiConverterSequenceTypeBoxReference: FfiConverterRustBuffer> { + override fun read(buf: ByteBuffer): List { + val len = buf.getInt() + return List(len) { + FfiConverterTypeBoxReference.read(buf) + } + } + + override fun allocationSize(value: List): ULong { + val sizeForLength = 4UL + val sizeForItems = value.map { FfiConverterTypeBoxReference.allocationSize(it) }.sum() + return sizeForLength + sizeForItems + } + + override fun write(value: List, buf: ByteBuffer) { + buf.putInt(value.size) + value.iterator().forEach { + FfiConverterTypeBoxReference.write(it, buf) + } + } +} + + + + +/** + * @suppress + */ +public object FfiConverterSequenceTypeMultisigSubsignature: FfiConverterRustBuffer> { + override fun read(buf: ByteBuffer): List { + val len = buf.getInt() + return List(len) { + FfiConverterTypeMultisigSubsignature.read(buf) + } + } + + override fun allocationSize(value: List): ULong { + val sizeForLength = 4UL + val sizeForItems = value.map { FfiConverterTypeMultisigSubsignature.allocationSize(it) }.sum() + return sizeForLength + sizeForItems + } + + override fun write(value: List, buf: ByteBuffer) { + buf.putInt(value.size) + value.iterator().forEach { + FfiConverterTypeMultisigSubsignature.write(it, buf) + } + } +} + + + + +/** + * @suppress + */ +public object FfiConverterSequenceTypeReveal: FfiConverterRustBuffer> { + override fun read(buf: ByteBuffer): List { + val len = buf.getInt() + return List(len) { + FfiConverterTypeReveal.read(buf) + } + } + + override fun allocationSize(value: List): ULong { + val sizeForLength = 4UL + val sizeForItems = value.map { FfiConverterTypeReveal.allocationSize(it) }.sum() + return sizeForLength + sizeForItems + } + + override fun write(value: List, buf: ByteBuffer) { + buf.putInt(value.size) + value.iterator().forEach { + FfiConverterTypeReveal.write(it, buf) + } + } +} + + + + +/** + * @suppress + */ +public object FfiConverterSequenceTypeSignedTransaction: FfiConverterRustBuffer> { + override fun read(buf: ByteBuffer): List { + val len = buf.getInt() + return List(len) { + FfiConverterTypeSignedTransaction.read(buf) + } + } + + override fun allocationSize(value: List): ULong { + val sizeForLength = 4UL + val sizeForItems = value.map { FfiConverterTypeSignedTransaction.allocationSize(it) }.sum() + return sizeForLength + sizeForItems + } + + override fun write(value: List, buf: ByteBuffer) { + buf.putInt(value.size) + value.iterator().forEach { + FfiConverterTypeSignedTransaction.write(it, buf) + } + } +} + + + + +/** + * @suppress + */ +public object FfiConverterSequenceTypeTransaction: FfiConverterRustBuffer> { + override fun read(buf: ByteBuffer): List { + val len = buf.getInt() + return List(len) { + FfiConverterTypeTransaction.read(buf) + } + } + + override fun allocationSize(value: List): ULong { + val sizeForLength = 4UL + val sizeForItems = value.map { FfiConverterTypeTransaction.allocationSize(it) }.sum() + return sizeForLength + sizeForItems + } + + override fun write(value: List, buf: ByteBuffer) { + buf.putInt(value.size) + value.iterator().forEach { + FfiConverterTypeTransaction.write(it, buf) + } + } +} + /** + * Returns the address of the multisignature account. + * + * # Errors + * /// Returns [`AlgoKitTransactError`] if the multisignature signature is invalid or the address cannot be derived. + */ + @Throws(AlgoKitTransactException::class) fun `addressFromMultisigSignature`(`multisigSignature`: MultisigSignature): kotlin.String { + return FfiConverterString.lift( + uniffiRustCallWithError(AlgoKitTransactException) { _status -> + UniffiLib.INSTANCE.uniffi_algokit_transact_ffi_fn_func_address_from_multisig_signature( + FfiConverterTypeMultisigSignature.lower(`multisigSignature`),_status) +} + ) + } + + + @Throws(AlgoKitTransactException::class) fun `addressFromPublicKey`(`publicKey`: kotlin.ByteArray): kotlin.String { + return FfiConverterString.lift( + uniffiRustCallWithError(AlgoKitTransactException) { _status -> + UniffiLib.INSTANCE.uniffi_algokit_transact_ffi_fn_func_address_from_public_key( + FfiConverterByteArray.lower(`publicKey`),_status) +} + ) + } + + + /** + * Applies a subsignature for a participant to a multisignature signature, replacing any existing signature. + * + * # Errors + * + * Returns [`AlgoKitTransactError`] if the participant address is invalid or not found, or if the signature bytes are invalid. + */ + @Throws(AlgoKitTransactException::class) fun `applyMultisigSubsignature`(`multisigSignature`: MultisigSignature, `participant`: kotlin.String, `subsignature`: kotlin.ByteArray): MultisigSignature { + return FfiConverterTypeMultisigSignature.lift( + uniffiRustCallWithError(AlgoKitTransactException) { _status -> + UniffiLib.INSTANCE.uniffi_algokit_transact_ffi_fn_func_apply_multisig_subsignature( + FfiConverterTypeMultisigSignature.lower(`multisigSignature`),FfiConverterString.lower(`participant`),FfiConverterByteArray.lower(`subsignature`),_status) +} + ) + } + + + @Throws(AlgoKitTransactException::class) fun `assignFee`(`transaction`: Transaction, `feeParams`: FeeParams): Transaction { + return FfiConverterTypeTransaction.lift( + uniffiRustCallWithError(AlgoKitTransactException) { _status -> + UniffiLib.INSTANCE.uniffi_algokit_transact_ffi_fn_func_assign_fee( + FfiConverterTypeTransaction.lower(`transaction`),FfiConverterTypeFeeParams.lower(`feeParams`),_status) +} + ) + } + + + @Throws(AlgoKitTransactException::class) fun `calculateFee`(`transaction`: Transaction, `feeParams`: FeeParams): kotlin.ULong { + return FfiConverterULong.lift( + uniffiRustCallWithError(AlgoKitTransactException) { _status -> + UniffiLib.INSTANCE.uniffi_algokit_transact_ffi_fn_func_calculate_fee( + FfiConverterTypeTransaction.lower(`transaction`),FfiConverterTypeFeeParams.lower(`feeParams`),_status) +} + ) + } + + + /** + * Decodes a signed transaction. + * + * # Parameters + * * `encoded_signed_transaction` - The MsgPack encoded signed transaction bytes + * + * # Returns + * The decoded SignedTransaction or an error if decoding fails. + */ + @Throws(AlgoKitTransactException::class) fun `decodeSignedTransaction`(`encodedSignedTransaction`: kotlin.ByteArray): SignedTransaction { + return FfiConverterTypeSignedTransaction.lift( + uniffiRustCallWithError(AlgoKitTransactException) { _status -> + UniffiLib.INSTANCE.uniffi_algokit_transact_ffi_fn_func_decode_signed_transaction( + FfiConverterByteArray.lower(`encodedSignedTransaction`),_status) +} + ) + } + + + /** + * Decodes a collection of MsgPack bytes into a signed transaction collection. + * + * # Parameters + * * `encoded_signed_transactions` - A collection of MsgPack encoded bytes, each representing a signed transaction. + * + * # Returns + * A collection of decoded signed transactions or an error if decoding fails. + */ + @Throws(AlgoKitTransactException::class) fun `decodeSignedTransactions`(`encodedSignedTransactions`: List): List { + return FfiConverterSequenceTypeSignedTransaction.lift( + uniffiRustCallWithError(AlgoKitTransactException) { _status -> + UniffiLib.INSTANCE.uniffi_algokit_transact_ffi_fn_func_decode_signed_transactions( + FfiConverterSequenceByteArray.lower(`encodedSignedTransactions`),_status) +} + ) + } + + + /** + * Decodes MsgPack bytes into a transaction. + * + * # Parameters + * * `encoded_tx` - MsgPack encoded bytes representing a transaction. + * + * # Returns + * A decoded transaction or an error if decoding fails. + */ + @Throws(AlgoKitTransactException::class) fun `decodeTransaction`(`encodedTx`: kotlin.ByteArray): Transaction { + return FfiConverterTypeTransaction.lift( + uniffiRustCallWithError(AlgoKitTransactException) { _status -> + UniffiLib.INSTANCE.uniffi_algokit_transact_ffi_fn_func_decode_transaction( + FfiConverterByteArray.lower(`encodedTx`),_status) +} + ) + } + + + /** + * Decodes a collection of MsgPack bytes into a transaction collection. + * + * # Parameters + * * `encoded_txs` - A collection of MsgPack encoded bytes, each representing a transaction. + * + * # Returns + * A collection of decoded transactions or an error if decoding fails. + */ + @Throws(AlgoKitTransactException::class) fun `decodeTransactions`(`encodedTxs`: List): List { + return FfiConverterSequenceTypeTransaction.lift( + uniffiRustCallWithError(AlgoKitTransactException) { _status -> + UniffiLib.INSTANCE.uniffi_algokit_transact_ffi_fn_func_decode_transactions( + FfiConverterSequenceByteArray.lower(`encodedTxs`),_status) +} + ) + } + + + /** + * Encode a signed transaction to MsgPack for sending on the network. + * + * This method performs canonical encoding. No domain separation prefix is applicable. + * + * # Parameters + * * `signed_transaction` - The signed transaction to encode + * + * # Returns + * The MsgPack encoded bytes or an error if encoding fails. + */ + @Throws(AlgoKitTransactException::class) fun `encodeSignedTransaction`(`signedTransaction`: SignedTransaction): kotlin.ByteArray { + return FfiConverterByteArray.lift( + uniffiRustCallWithError(AlgoKitTransactException) { _status -> + UniffiLib.INSTANCE.uniffi_algokit_transact_ffi_fn_func_encode_signed_transaction( + FfiConverterTypeSignedTransaction.lower(`signedTransaction`),_status) +} + ) + } + + + /** + * Encode signed transactions to MsgPack for sending on the network. + * + * This method performs canonical encoding. No domain separation prefix is applicable. + * + * # Parameters + * * `signed_transactions` - A collection of signed transactions to encode + * + * # Returns + * A collection of MsgPack encoded bytes or an error if encoding fails. + */ + @Throws(AlgoKitTransactException::class) fun `encodeSignedTransactions`(`signedTransactions`: List): List { + return FfiConverterSequenceByteArray.lift( + uniffiRustCallWithError(AlgoKitTransactException) { _status -> + UniffiLib.INSTANCE.uniffi_algokit_transact_ffi_fn_func_encode_signed_transactions( + FfiConverterSequenceTypeSignedTransaction.lower(`signedTransactions`),_status) +} + ) + } + + + /** + * Encode the transaction with the domain separation (e.g. "TX") prefix + */ + @Throws(AlgoKitTransactException::class) fun `encodeTransaction`(`transaction`: Transaction): kotlin.ByteArray { + return FfiConverterByteArray.lift( + uniffiRustCallWithError(AlgoKitTransactException) { _status -> + UniffiLib.INSTANCE.uniffi_algokit_transact_ffi_fn_func_encode_transaction( + FfiConverterTypeTransaction.lower(`transaction`),_status) +} + ) + } + + + /** + * Encode the transaction without the domain separation (e.g. "TX") prefix + * This is useful for encoding the transaction for signing with tools that automatically add "TX" prefix to the transaction bytes. + */ + @Throws(AlgoKitTransactException::class) fun `encodeTransactionRaw`(`transaction`: Transaction): kotlin.ByteArray { + return FfiConverterByteArray.lift( + uniffiRustCallWithError(AlgoKitTransactException) { _status -> + UniffiLib.INSTANCE.uniffi_algokit_transact_ffi_fn_func_encode_transaction_raw( + FfiConverterTypeTransaction.lower(`transaction`),_status) +} + ) + } + + + /** + * Encode transactions to MsgPack with the domain separation (e.g. "TX") prefix. + * + * # Parameters + * * `transactions` - A collection of transactions to encode + * + * # Returns + * A collection of MsgPack encoded bytes or an error if encoding fails. + */ + @Throws(AlgoKitTransactException::class) fun `encodeTransactions`(`transactions`: List): List { + return FfiConverterSequenceByteArray.lift( + uniffiRustCallWithError(AlgoKitTransactException) { _status -> + UniffiLib.INSTANCE.uniffi_algokit_transact_ffi_fn_func_encode_transactions( + FfiConverterSequenceTypeTransaction.lower(`transactions`),_status) +} + ) + } + + + /** + * Return the size of the transaction in bytes as if it was already signed and encoded. + * This is useful for estimating the fee for the transaction. + */ + @Throws(AlgoKitTransactException::class) fun `estimateTransactionSize`(`transaction`: Transaction): kotlin.ULong { + return FfiConverterULong.lift( + uniffiRustCallWithError(AlgoKitTransactException) { _status -> + UniffiLib.INSTANCE.uniffi_algokit_transact_ffi_fn_func_estimate_transaction_size( + FfiConverterTypeTransaction.lower(`transaction`),_status) +} + ) + } + + fun `getAlgorandConstant`(`constant`: AlgorandConstant): kotlin.ULong { + return FfiConverterULong.lift( + uniffiRustCall() { _status -> + UniffiLib.INSTANCE.uniffi_algokit_transact_ffi_fn_func_get_algorand_constant( + FfiConverterTypeAlgorandConstant.lower(`constant`),_status) +} + ) + } + + + /** + * Get the transaction type from the encoded transaction. + * This is particularly useful when decoding a transaction that has an unknown type + */ + @Throws(AlgoKitTransactException::class) fun `getEncodedTransactionType`(`encodedTransaction`: kotlin.ByteArray): TransactionType { + return FfiConverterTypeTransactionType.lift( + uniffiRustCallWithError(AlgoKitTransactException) { _status -> + UniffiLib.INSTANCE.uniffi_algokit_transact_ffi_fn_func_get_encoded_transaction_type( + FfiConverterByteArray.lower(`encodedTransaction`),_status) +} + ) + } + + + /** + * Get the base32 transaction ID string for a transaction. + */ + @Throws(AlgoKitTransactException::class) fun `getTransactionId`(`transaction`: Transaction): kotlin.String { + return FfiConverterString.lift( + uniffiRustCallWithError(AlgoKitTransactException) { _status -> + UniffiLib.INSTANCE.uniffi_algokit_transact_ffi_fn_func_get_transaction_id( + FfiConverterTypeTransaction.lower(`transaction`),_status) +} + ) + } + + + /** + * Get the raw 32-byte transaction ID for a transaction. + */ + @Throws(AlgoKitTransactException::class) fun `getTransactionIdRaw`(`transaction`: Transaction): kotlin.ByteArray { + return FfiConverterByteArray.lift( + uniffiRustCallWithError(AlgoKitTransactException) { _status -> + UniffiLib.INSTANCE.uniffi_algokit_transact_ffi_fn_func_get_transaction_id_raw( + FfiConverterTypeTransaction.lower(`transaction`),_status) +} + ) + } + + + /** + * Groups a collection of transactions by calculating and assigning the group to each transaction. + */ + @Throws(AlgoKitTransactException::class) fun `groupTransactions`(`transactions`: List): List { + return FfiConverterSequenceTypeTransaction.lift( + uniffiRustCallWithError(AlgoKitTransactException) { _status -> + UniffiLib.INSTANCE.uniffi_algokit_transact_ffi_fn_func_group_transactions( + FfiConverterSequenceTypeTransaction.lower(`transactions`),_status) +} + ) + } + + + /** + * Merges two multisignature signatures, replacing signatures in the first with those from the second where present. + * + * # Errors + * + * Returns [`AlgoKitTransactError`] if the multisignature parameters or participants do not match. + */ + @Throws(AlgoKitTransactException::class) fun `mergeMultisignatures`(`multisigSignatureA`: MultisigSignature, `multisigSignatureB`: MultisigSignature): MultisigSignature { + return FfiConverterTypeMultisigSignature.lift( + uniffiRustCallWithError(AlgoKitTransactException) { _status -> + UniffiLib.INSTANCE.uniffi_algokit_transact_ffi_fn_func_merge_multisignatures( + FfiConverterTypeMultisigSignature.lower(`multisigSignatureA`),FfiConverterTypeMultisigSignature.lower(`multisigSignatureB`),_status) +} + ) + } + + + /** + * Creates an empty multisignature signature from a list of participant addresses. + * + * # Errors + * + * Returns [`AlgoKitTransactError`] if any address is invalid or the multisignature parameters are invalid. + */ + @Throws(AlgoKitTransactException::class) fun `newMultisigSignature`(`version`: kotlin.UByte, `threshold`: kotlin.UByte, `participants`: List): MultisigSignature { + return FfiConverterTypeMultisigSignature.lift( + uniffiRustCallWithError(AlgoKitTransactException) { _status -> + UniffiLib.INSTANCE.uniffi_algokit_transact_ffi_fn_func_new_multisig_signature( + FfiConverterUByte.lower(`version`),FfiConverterUByte.lower(`threshold`),FfiConverterSequenceString.lower(`participants`),_status) +} + ) + } + + + /** + * Returns the list of participant addresses from a multisignature signature. + * + * # Errors + * Returns [`AlgoKitTransactError`] if the multisignature is invalid. + */ + @Throws(AlgoKitTransactException::class) fun `participantsFromMultisigSignature`(`multisigSignature`: MultisigSignature): List { + return FfiConverterSequenceString.lift( + uniffiRustCallWithError(AlgoKitTransactException) { _status -> + UniffiLib.INSTANCE.uniffi_algokit_transact_ffi_fn_func_participants_from_multisig_signature( + FfiConverterTypeMultisigSignature.lower(`multisigSignature`),_status) +} + ) + } + + + @Throws(AlgoKitTransactException::class) fun `publicKeyFromAddress`(`address`: kotlin.String): kotlin.ByteArray { + return FfiConverterByteArray.lift( + uniffiRustCallWithError(AlgoKitTransactException) { _status -> + UniffiLib.INSTANCE.uniffi_algokit_transact_ffi_fn_func_public_key_from_address( + FfiConverterString.lower(`address`),_status) +} + ) + } + + + diff --git a/packages/android/algokit_transact/src/test/kotlin/uniffi/algokit_transact_ffi/AddressConversionTest.kt b/packages/android/algokit_transact/src/test/kotlin/uniffi/algokit_transact_ffi/AddressConversionTest.kt new file mode 100644 index 000000000..cd207d38d --- /dev/null +++ b/packages/android/algokit_transact/src/test/kotlin/uniffi/algokit_transact_ffi/AddressConversionTest.kt @@ -0,0 +1,119 @@ +package uniffi.algokit_transact_ffi + +import org.junit.Test +import org.junit.Assert.* +import org.junit.Before + +/** + * Test suite for address conversion functions. + * + * Tests the bidirectional conversion between Algorand addresses and public keys. + */ +class AddressConversionTest { + + @Before + fun setup() { + // Ensure the FFI library is initialized before running tests + uniffiEnsureInitialized() + } + + @Test + fun testPublicKeyToAddressConversion() { + // Test converting a public key to an address + // This is a valid 32-byte public key (all zeros for simplicity) + val publicKey = ByteArray(32) { 0 } + + val address = addressFromPublicKey(publicKey) + + // Algorand addresses are 58 characters long (base32 encoded) + assertEquals(58, address.length) + // The address for a zero public key should be a specific value + assertEquals("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAY5HFKQ", address) + } + + @Test + fun testAddressToPublicKeyConversion() { + // Test converting an address back to a public key + val address = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAY5HFKQ" + + val publicKey = publicKeyFromAddress(address) + + // Public keys are 32 bytes + assertEquals(32, publicKey.size) + // Should be all zeros + assertTrue(publicKey.all { it == 0.toByte() }) + } + + @Test + fun testRoundTripConversion() { + // Test that converting public key -> address -> public key preserves the original value + val originalPublicKey = ByteArray(32) { it.toByte() } + + val address = addressFromPublicKey(originalPublicKey) + val recoveredPublicKey = publicKeyFromAddress(address) + + assertArrayEquals(originalPublicKey, recoveredPublicKey) + } + + @Test + fun testRealWorldAddress() { + // Test with a real Algorand address + val realAddress = "7ZUECA7HFLZTXENRV24SHLU4AVPUTMTTDUFUBNBD64C73F3UHRTHAIOF6Q" + + val publicKey = publicKeyFromAddress(realAddress) + val recoveredAddress = addressFromPublicKey(publicKey) + + assertEquals(realAddress, recoveredAddress) + assertEquals(32, publicKey.size) + } + + @Test(expected = AlgoKitTransactException.DecodingException::class) + fun testInvalidAddressFormat() { + // Test that an invalid address throws an exception + val invalidAddress = "INVALID" + + publicKeyFromAddress(invalidAddress) + } + + @Test(expected = AlgoKitTransactException.DecodingException::class) + fun testInvalidAddressChecksum() { + // Test that an address with an invalid checksum throws an exception + // This address has the right length but wrong checksum + val invalidAddress = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA5HFKQ" + + publicKeyFromAddress(invalidAddress) + } + + @Test(expected = AlgoKitTransactException.EncodingException::class) + fun testInvalidPublicKeyLength() { + // Test that a public key with wrong length throws an exception + val invalidPublicKey = ByteArray(16) { 0 } // Too short, should be 32 bytes + + addressFromPublicKey(invalidPublicKey) + } + + @Test + fun testPublicKeyAllOnes() { + // Test with a public key of all 1s + val publicKey = ByteArray(32) { 0xFF.toByte() } + + val address = addressFromPublicKey(publicKey) + val recoveredPublicKey = publicKeyFromAddress(address) + + assertArrayEquals(publicKey, recoveredPublicKey) + assertEquals(58, address.length) + } + + @Test + fun testPublicKeyPattern() { + // Test with a patterned public key (alternating bytes) + val publicKey = ByteArray(32) { i -> + if (i % 2 == 0) 0xAA.toByte() else 0x55.toByte() + } + + val address = addressFromPublicKey(publicKey) + val recoveredPublicKey = publicKeyFromAddress(address) + + assertArrayEquals(publicKey, recoveredPublicKey) + } +} diff --git a/packages/swift/AlgoKitTransact/Frameworks/algokit_transact.xcframework/Info.plist b/packages/swift/AlgoKitTransact/Frameworks/algokit_transact.xcframework/Info.plist index 0f6ddbd08..c10702a52 100644 --- a/packages/swift/AlgoKitTransact/Frameworks/algokit_transact.xcframework/Info.plist +++ b/packages/swift/AlgoKitTransact/Frameworks/algokit_transact.xcframework/Info.plist @@ -6,74 +6,74 @@ BinaryPath - libalgokit_transact_ffi-ios-sim.a + libalgokit_transact_ffi-macos.a HeadersPath Headers LibraryIdentifier - ios-arm64_x86_64-simulator + macos-arm64_x86_64 LibraryPath - libalgokit_transact_ffi-ios-sim.a + libalgokit_transact_ffi-macos.a SupportedArchitectures arm64 x86_64 SupportedPlatform - ios - SupportedPlatformVariant - simulator + macos BinaryPath - libalgokit_transact_ffi-macos.a + libalgokit_transact_ffi-ios-sim.a HeadersPath Headers LibraryIdentifier - macos-arm64_x86_64 + ios-arm64_x86_64-simulator LibraryPath - libalgokit_transact_ffi-macos.a + libalgokit_transact_ffi-ios-sim.a SupportedArchitectures arm64 x86_64 SupportedPlatform - macos + ios + SupportedPlatformVariant + simulator BinaryPath - libalgokit_transact_ffi-catalyst.a + libalgokit_transact_ffi.a HeadersPath Headers LibraryIdentifier - ios-arm64_x86_64-maccatalyst + ios-arm64 LibraryPath - libalgokit_transact_ffi-catalyst.a + libalgokit_transact_ffi.a SupportedArchitectures arm64 - x86_64 SupportedPlatform ios - SupportedPlatformVariant - maccatalyst BinaryPath - libalgokit_transact_ffi.a + libalgokit_transact_ffi-catalyst.a HeadersPath Headers LibraryIdentifier - ios-arm64 + ios-arm64_x86_64-maccatalyst LibraryPath - libalgokit_transact_ffi.a + libalgokit_transact_ffi-catalyst.a SupportedArchitectures arm64 + x86_64 SupportedPlatform ios + SupportedPlatformVariant + maccatalyst CFBundlePackageType diff --git a/packages/swift/AlgoKitTransact/Frameworks/algokit_transact.xcframework/ios-arm64/Headers/algokit_transact.swift b/packages/swift/AlgoKitTransact/Frameworks/algokit_transact.xcframework/ios-arm64/Headers/algokit_transact.swift index 4d0fa70f5..20d5e17fc 100644 --- a/packages/swift/AlgoKitTransact/Frameworks/algokit_transact.xcframework/ios-arm64/Headers/algokit_transact.swift +++ b/packages/swift/AlgoKitTransact/Frameworks/algokit_transact.xcframework/ios-arm64/Headers/algokit_transact.swift @@ -3597,13 +3597,13 @@ public enum AlgoKitTransactError: Swift.Error { - case EncodingError(message: String + case EncodingError(errorMsg: String ) - case DecodingError(message: String + case DecodingError(errorMsg: String ) - case InputError(message: String + case InputError(errorMsg: String ) - case MsgPackError(message: String + case MsgPackError(errorMsg: String ) } @@ -3622,16 +3622,16 @@ public struct FfiConverterTypeAlgoKitTransactError: FfiConverterRustBuffer { case 1: return .EncodingError( - message: try FfiConverterString.read(from: &buf) + errorMsg: try FfiConverterString.read(from: &buf) ) case 2: return .DecodingError( - message: try FfiConverterString.read(from: &buf) + errorMsg: try FfiConverterString.read(from: &buf) ) case 3: return .InputError( - message: try FfiConverterString.read(from: &buf) + errorMsg: try FfiConverterString.read(from: &buf) ) case 4: return .MsgPackError( - message: try FfiConverterString.read(from: &buf) + errorMsg: try FfiConverterString.read(from: &buf) ) default: throw UniffiInternalError.unexpectedEnumCase @@ -3645,24 +3645,24 @@ public struct FfiConverterTypeAlgoKitTransactError: FfiConverterRustBuffer { - case let .EncodingError(message): + case let .EncodingError(errorMsg): writeInt(&buf, Int32(1)) - FfiConverterString.write(message, into: &buf) + FfiConverterString.write(errorMsg, into: &buf) - case let .DecodingError(message): + case let .DecodingError(errorMsg): writeInt(&buf, Int32(2)) - FfiConverterString.write(message, into: &buf) + FfiConverterString.write(errorMsg, into: &buf) - case let .InputError(message): + case let .InputError(errorMsg): writeInt(&buf, Int32(3)) - FfiConverterString.write(message, into: &buf) + FfiConverterString.write(errorMsg, into: &buf) - case let .MsgPackError(message): + case let .MsgPackError(errorMsg): writeInt(&buf, Int32(4)) - FfiConverterString.write(message, into: &buf) + FfiConverterString.write(errorMsg, into: &buf) } } diff --git a/packages/swift/AlgoKitTransact/Frameworks/algokit_transact.xcframework/ios-arm64/libalgokit_transact_ffi.a b/packages/swift/AlgoKitTransact/Frameworks/algokit_transact.xcframework/ios-arm64/libalgokit_transact_ffi.a index adaad9ed6..2da601686 100644 Binary files a/packages/swift/AlgoKitTransact/Frameworks/algokit_transact.xcframework/ios-arm64/libalgokit_transact_ffi.a and b/packages/swift/AlgoKitTransact/Frameworks/algokit_transact.xcframework/ios-arm64/libalgokit_transact_ffi.a differ diff --git a/packages/swift/AlgoKitTransact/Frameworks/algokit_transact.xcframework/ios-arm64_x86_64-maccatalyst/Headers/algokit_transact.swift b/packages/swift/AlgoKitTransact/Frameworks/algokit_transact.xcframework/ios-arm64_x86_64-maccatalyst/Headers/algokit_transact.swift index 4d0fa70f5..20d5e17fc 100644 --- a/packages/swift/AlgoKitTransact/Frameworks/algokit_transact.xcframework/ios-arm64_x86_64-maccatalyst/Headers/algokit_transact.swift +++ b/packages/swift/AlgoKitTransact/Frameworks/algokit_transact.xcframework/ios-arm64_x86_64-maccatalyst/Headers/algokit_transact.swift @@ -3597,13 +3597,13 @@ public enum AlgoKitTransactError: Swift.Error { - case EncodingError(message: String + case EncodingError(errorMsg: String ) - case DecodingError(message: String + case DecodingError(errorMsg: String ) - case InputError(message: String + case InputError(errorMsg: String ) - case MsgPackError(message: String + case MsgPackError(errorMsg: String ) } @@ -3622,16 +3622,16 @@ public struct FfiConverterTypeAlgoKitTransactError: FfiConverterRustBuffer { case 1: return .EncodingError( - message: try FfiConverterString.read(from: &buf) + errorMsg: try FfiConverterString.read(from: &buf) ) case 2: return .DecodingError( - message: try FfiConverterString.read(from: &buf) + errorMsg: try FfiConverterString.read(from: &buf) ) case 3: return .InputError( - message: try FfiConverterString.read(from: &buf) + errorMsg: try FfiConverterString.read(from: &buf) ) case 4: return .MsgPackError( - message: try FfiConverterString.read(from: &buf) + errorMsg: try FfiConverterString.read(from: &buf) ) default: throw UniffiInternalError.unexpectedEnumCase @@ -3645,24 +3645,24 @@ public struct FfiConverterTypeAlgoKitTransactError: FfiConverterRustBuffer { - case let .EncodingError(message): + case let .EncodingError(errorMsg): writeInt(&buf, Int32(1)) - FfiConverterString.write(message, into: &buf) + FfiConverterString.write(errorMsg, into: &buf) - case let .DecodingError(message): + case let .DecodingError(errorMsg): writeInt(&buf, Int32(2)) - FfiConverterString.write(message, into: &buf) + FfiConverterString.write(errorMsg, into: &buf) - case let .InputError(message): + case let .InputError(errorMsg): writeInt(&buf, Int32(3)) - FfiConverterString.write(message, into: &buf) + FfiConverterString.write(errorMsg, into: &buf) - case let .MsgPackError(message): + case let .MsgPackError(errorMsg): writeInt(&buf, Int32(4)) - FfiConverterString.write(message, into: &buf) + FfiConverterString.write(errorMsg, into: &buf) } } diff --git a/packages/swift/AlgoKitTransact/Frameworks/algokit_transact.xcframework/ios-arm64_x86_64-maccatalyst/libalgokit_transact_ffi-catalyst.a b/packages/swift/AlgoKitTransact/Frameworks/algokit_transact.xcframework/ios-arm64_x86_64-maccatalyst/libalgokit_transact_ffi-catalyst.a index e5a9e84e9..93f021b31 100644 Binary files a/packages/swift/AlgoKitTransact/Frameworks/algokit_transact.xcframework/ios-arm64_x86_64-maccatalyst/libalgokit_transact_ffi-catalyst.a and b/packages/swift/AlgoKitTransact/Frameworks/algokit_transact.xcframework/ios-arm64_x86_64-maccatalyst/libalgokit_transact_ffi-catalyst.a differ diff --git a/packages/swift/AlgoKitTransact/Frameworks/algokit_transact.xcframework/ios-arm64_x86_64-simulator/Headers/algokit_transact.swift b/packages/swift/AlgoKitTransact/Frameworks/algokit_transact.xcframework/ios-arm64_x86_64-simulator/Headers/algokit_transact.swift index 4d0fa70f5..20d5e17fc 100644 --- a/packages/swift/AlgoKitTransact/Frameworks/algokit_transact.xcframework/ios-arm64_x86_64-simulator/Headers/algokit_transact.swift +++ b/packages/swift/AlgoKitTransact/Frameworks/algokit_transact.xcframework/ios-arm64_x86_64-simulator/Headers/algokit_transact.swift @@ -3597,13 +3597,13 @@ public enum AlgoKitTransactError: Swift.Error { - case EncodingError(message: String + case EncodingError(errorMsg: String ) - case DecodingError(message: String + case DecodingError(errorMsg: String ) - case InputError(message: String + case InputError(errorMsg: String ) - case MsgPackError(message: String + case MsgPackError(errorMsg: String ) } @@ -3622,16 +3622,16 @@ public struct FfiConverterTypeAlgoKitTransactError: FfiConverterRustBuffer { case 1: return .EncodingError( - message: try FfiConverterString.read(from: &buf) + errorMsg: try FfiConverterString.read(from: &buf) ) case 2: return .DecodingError( - message: try FfiConverterString.read(from: &buf) + errorMsg: try FfiConverterString.read(from: &buf) ) case 3: return .InputError( - message: try FfiConverterString.read(from: &buf) + errorMsg: try FfiConverterString.read(from: &buf) ) case 4: return .MsgPackError( - message: try FfiConverterString.read(from: &buf) + errorMsg: try FfiConverterString.read(from: &buf) ) default: throw UniffiInternalError.unexpectedEnumCase @@ -3645,24 +3645,24 @@ public struct FfiConverterTypeAlgoKitTransactError: FfiConverterRustBuffer { - case let .EncodingError(message): + case let .EncodingError(errorMsg): writeInt(&buf, Int32(1)) - FfiConverterString.write(message, into: &buf) + FfiConverterString.write(errorMsg, into: &buf) - case let .DecodingError(message): + case let .DecodingError(errorMsg): writeInt(&buf, Int32(2)) - FfiConverterString.write(message, into: &buf) + FfiConverterString.write(errorMsg, into: &buf) - case let .InputError(message): + case let .InputError(errorMsg): writeInt(&buf, Int32(3)) - FfiConverterString.write(message, into: &buf) + FfiConverterString.write(errorMsg, into: &buf) - case let .MsgPackError(message): + case let .MsgPackError(errorMsg): writeInt(&buf, Int32(4)) - FfiConverterString.write(message, into: &buf) + FfiConverterString.write(errorMsg, into: &buf) } } diff --git a/packages/swift/AlgoKitTransact/Frameworks/algokit_transact.xcframework/ios-arm64_x86_64-simulator/libalgokit_transact_ffi-ios-sim.a b/packages/swift/AlgoKitTransact/Frameworks/algokit_transact.xcframework/ios-arm64_x86_64-simulator/libalgokit_transact_ffi-ios-sim.a index db75de7c5..4e3fb8355 100644 Binary files a/packages/swift/AlgoKitTransact/Frameworks/algokit_transact.xcframework/ios-arm64_x86_64-simulator/libalgokit_transact_ffi-ios-sim.a and b/packages/swift/AlgoKitTransact/Frameworks/algokit_transact.xcframework/ios-arm64_x86_64-simulator/libalgokit_transact_ffi-ios-sim.a differ diff --git a/packages/swift/AlgoKitTransact/Frameworks/algokit_transact.xcframework/macos-arm64_x86_64/Headers/algokit_transact.swift b/packages/swift/AlgoKitTransact/Frameworks/algokit_transact.xcframework/macos-arm64_x86_64/Headers/algokit_transact.swift index 4d0fa70f5..20d5e17fc 100644 --- a/packages/swift/AlgoKitTransact/Frameworks/algokit_transact.xcframework/macos-arm64_x86_64/Headers/algokit_transact.swift +++ b/packages/swift/AlgoKitTransact/Frameworks/algokit_transact.xcframework/macos-arm64_x86_64/Headers/algokit_transact.swift @@ -3597,13 +3597,13 @@ public enum AlgoKitTransactError: Swift.Error { - case EncodingError(message: String + case EncodingError(errorMsg: String ) - case DecodingError(message: String + case DecodingError(errorMsg: String ) - case InputError(message: String + case InputError(errorMsg: String ) - case MsgPackError(message: String + case MsgPackError(errorMsg: String ) } @@ -3622,16 +3622,16 @@ public struct FfiConverterTypeAlgoKitTransactError: FfiConverterRustBuffer { case 1: return .EncodingError( - message: try FfiConverterString.read(from: &buf) + errorMsg: try FfiConverterString.read(from: &buf) ) case 2: return .DecodingError( - message: try FfiConverterString.read(from: &buf) + errorMsg: try FfiConverterString.read(from: &buf) ) case 3: return .InputError( - message: try FfiConverterString.read(from: &buf) + errorMsg: try FfiConverterString.read(from: &buf) ) case 4: return .MsgPackError( - message: try FfiConverterString.read(from: &buf) + errorMsg: try FfiConverterString.read(from: &buf) ) default: throw UniffiInternalError.unexpectedEnumCase @@ -3645,24 +3645,24 @@ public struct FfiConverterTypeAlgoKitTransactError: FfiConverterRustBuffer { - case let .EncodingError(message): + case let .EncodingError(errorMsg): writeInt(&buf, Int32(1)) - FfiConverterString.write(message, into: &buf) + FfiConverterString.write(errorMsg, into: &buf) - case let .DecodingError(message): + case let .DecodingError(errorMsg): writeInt(&buf, Int32(2)) - FfiConverterString.write(message, into: &buf) + FfiConverterString.write(errorMsg, into: &buf) - case let .InputError(message): + case let .InputError(errorMsg): writeInt(&buf, Int32(3)) - FfiConverterString.write(message, into: &buf) + FfiConverterString.write(errorMsg, into: &buf) - case let .MsgPackError(message): + case let .MsgPackError(errorMsg): writeInt(&buf, Int32(4)) - FfiConverterString.write(message, into: &buf) + FfiConverterString.write(errorMsg, into: &buf) } } diff --git a/packages/swift/AlgoKitTransact/Frameworks/algokit_transact.xcframework/macos-arm64_x86_64/libalgokit_transact_ffi-macos.a b/packages/swift/AlgoKitTransact/Frameworks/algokit_transact.xcframework/macos-arm64_x86_64/libalgokit_transact_ffi-macos.a index b0cebfa26..3e3e216c3 100644 Binary files a/packages/swift/AlgoKitTransact/Frameworks/algokit_transact.xcframework/macos-arm64_x86_64/libalgokit_transact_ffi-macos.a and b/packages/swift/AlgoKitTransact/Frameworks/algokit_transact.xcframework/macos-arm64_x86_64/libalgokit_transact_ffi-macos.a differ diff --git a/packages/swift/AlgoKitTransact/Package.swift b/packages/swift/AlgoKitTransact/Package.swift index 94740469c..bf71171bb 100644 --- a/packages/swift/AlgoKitTransact/Package.swift +++ b/packages/swift/AlgoKitTransact/Package.swift @@ -4,37 +4,37 @@ import PackageDescription let package = Package( - name: "AlgoKitTransact", - products: [ - // Products define the executables and libraries a package produces, making them visible to other packages. - .library( - name: "AlgoKitTransact", - targets: ["AlgoKitTransact"]) - ], - dependencies: [ - .package(url: "https://github.com/pebble8888/ed25519swift.git", from: "1.2.7") - ], - targets: [ - // Targets are the basic building blocks of a package, defining a module or a test suite. - // Targets can depend on other targets in this package and products from dependencies. - .binaryTarget( - name: "algokit_transactFFI", - path: "Frameworks/algokit_transact.xcframework" - ), - .target( - name: "AlgoKitTransact", - dependencies: ["algokit_transactFFI"], - path: "Sources/AlgoKitTransact" - ), - .testTarget( - name: "AlgoKitTransactTests", - dependencies: [ - "AlgoKitTransact", - "ed25519swift", - ], - resources: [ - .process("Resources/test_data.json") - ] - ), - ] + name: "AlgoKitTransact", + products: [ + // Products define the executables and libraries a package produces, making them visible to other packages. + .library( + name: "AlgoKitTransact", + targets: ["AlgoKitTransact"]) + ], + dependencies: [ + .package(url: "https://github.com/pebble8888/ed25519swift.git", from: "1.2.7") + ], + targets: [ + // Targets are the basic building blocks of a package, defining a module or a test suite. + // Targets can depend on other targets in this package and products from dependencies. + .binaryTarget( + name: "algokit_transactFFI", + path: "Frameworks/algokit_transact.xcframework" + ), + .target( + name: "AlgoKitTransact", + dependencies: ["algokit_transactFFI"], + path: "Sources/AlgoKitTransact" + ), + .testTarget( + name: "AlgoKitTransactTests", + dependencies: [ + "AlgoKitTransact", + "ed25519swift", + ], + resources: [ + .process("Resources/test_data.json") + ] + ), + ] ) diff --git a/packages/swift/AlgoKitTransact/Sources/AlgoKitTransact/AlgoKitTransact.swift b/packages/swift/AlgoKitTransact/Sources/AlgoKitTransact/AlgoKitTransact.swift index 4d0fa70f5..20d5e17fc 100644 --- a/packages/swift/AlgoKitTransact/Sources/AlgoKitTransact/AlgoKitTransact.swift +++ b/packages/swift/AlgoKitTransact/Sources/AlgoKitTransact/AlgoKitTransact.swift @@ -3597,13 +3597,13 @@ public enum AlgoKitTransactError: Swift.Error { - case EncodingError(message: String + case EncodingError(errorMsg: String ) - case DecodingError(message: String + case DecodingError(errorMsg: String ) - case InputError(message: String + case InputError(errorMsg: String ) - case MsgPackError(message: String + case MsgPackError(errorMsg: String ) } @@ -3622,16 +3622,16 @@ public struct FfiConverterTypeAlgoKitTransactError: FfiConverterRustBuffer { case 1: return .EncodingError( - message: try FfiConverterString.read(from: &buf) + errorMsg: try FfiConverterString.read(from: &buf) ) case 2: return .DecodingError( - message: try FfiConverterString.read(from: &buf) + errorMsg: try FfiConverterString.read(from: &buf) ) case 3: return .InputError( - message: try FfiConverterString.read(from: &buf) + errorMsg: try FfiConverterString.read(from: &buf) ) case 4: return .MsgPackError( - message: try FfiConverterString.read(from: &buf) + errorMsg: try FfiConverterString.read(from: &buf) ) default: throw UniffiInternalError.unexpectedEnumCase @@ -3645,24 +3645,24 @@ public struct FfiConverterTypeAlgoKitTransactError: FfiConverterRustBuffer { - case let .EncodingError(message): + case let .EncodingError(errorMsg): writeInt(&buf, Int32(1)) - FfiConverterString.write(message, into: &buf) + FfiConverterString.write(errorMsg, into: &buf) - case let .DecodingError(message): + case let .DecodingError(errorMsg): writeInt(&buf, Int32(2)) - FfiConverterString.write(message, into: &buf) + FfiConverterString.write(errorMsg, into: &buf) - case let .InputError(message): + case let .InputError(errorMsg): writeInt(&buf, Int32(3)) - FfiConverterString.write(message, into: &buf) + FfiConverterString.write(errorMsg, into: &buf) - case let .MsgPackError(message): + case let .MsgPackError(errorMsg): writeInt(&buf, Int32(4)) - FfiConverterString.write(message, into: &buf) + FfiConverterString.write(errorMsg, into: &buf) } } diff --git a/packages/swift/AlgoKitTransact/Tests/AlgoKitTransactTests/GenericTransactionTests.swift b/packages/swift/AlgoKitTransact/Tests/AlgoKitTransactTests/GenericTransactionTests.swift index 86369556c..927cd7074 100644 --- a/packages/swift/AlgoKitTransact/Tests/AlgoKitTransactTests/GenericTransactionTests.swift +++ b/packages/swift/AlgoKitTransact/Tests/AlgoKitTransactTests/GenericTransactionTests.swift @@ -15,9 +15,6 @@ func genericTransactionMalformedBytes() throws { do { _ = try decodeTransaction(encodedTx: badBytes) #expect(Bool(false), "Expected DecodingError to be thrown") - } catch AlgoKitTransactError.InputError { - // Success - expected error was thrown - #expect(Bool(true)) } catch AlgoKitTransactError.DecodingError { // Success - expected error was thrown #expect(Bool(true)) diff --git a/packages/swift/AlgoKitTransact/Tests/AlgoKitTransactTests/PaymentTests.swift b/packages/swift/AlgoKitTransact/Tests/AlgoKitTransactTests/PaymentTests.swift index 20cb5fe86..8e8c81c73 100644 --- a/packages/swift/AlgoKitTransact/Tests/AlgoKitTransactTests/PaymentTests.swift +++ b/packages/swift/AlgoKitTransact/Tests/AlgoKitTransactTests/PaymentTests.swift @@ -36,9 +36,9 @@ func paymentExample() throws { signature: Data(sig) ) - let encodedSignedTxn = try encodeSignedTransaction(signedTransaction: signedTxn) + let encodedStxn = try encodeSignedTransaction(signedTransaction: signedTxn) - #expect(!encodedSignedTxn.isEmpty) + #expect(encodedStxn.count > 0) } @Test("Payment: get encoded transaction type") @@ -75,14 +75,14 @@ func paymentEncodeWithSignature() throws { let signature = Ed25519.sign( message: simplePayment.unsignedBytes, secretKey: simplePayment.signingPrivateKey) - let signedTx = try encodeSignedTransaction( - signedTransaction: SignedTransaction( - transaction: makeTransaction(from: simplePayment), - signature: Data(signature) - ) + let signedTx = SignedTransaction( + transaction: makeTransaction(from: simplePayment), + signature: Data(signature) ) - #expect([UInt8](signedTx) == simplePayment.signedBytes) + let encodedStxn = try encodeSignedTransaction(signedTransaction: signedTx) + + #expect([UInt8](encodedStxn) == simplePayment.signedBytes) } @Test("Payment: encode") diff --git a/packages/swift/AlgoKitTransact/Tests/AlgoKitTransactTests/TestUtils.swift b/packages/swift/AlgoKitTransact/Tests/AlgoKitTransactTests/TestUtils.swift index 74ce84f65..d4bb3c775 100644 --- a/packages/swift/AlgoKitTransact/Tests/AlgoKitTransactTests/TestUtils.swift +++ b/packages/swift/AlgoKitTransact/Tests/AlgoKitTransactTests/TestUtils.swift @@ -3,10 +3,6 @@ import Foundation @testable import AlgoKitTransact struct TransactionTestData: Codable { - struct AddressData: Codable { - let address: String - let pubKey: [UInt8] - } struct TransactionData: Codable { let sender: String @@ -57,7 +53,8 @@ func makeTransaction(from testData: TransactionTestData) -> Transaction { genesisHash: Data(testData.transaction.genesisHash), genesisId: testData.transaction.genesisId, note: testData.transaction.note != nil ? Data(testData.transaction.note!) : nil, - rekeyTo: testData.transaction.rekeyTo, + rekeyTo: testData.transaction.rekeyTo != nil + ? testData.transaction.rekeyTo! : nil, lease: testData.transaction.lease != nil ? Data(testData.transaction.lease!) : nil, group: testData.transaction.group != nil ? Data(testData.transaction.group!) : nil, payment: PaymentTransactionFields( diff --git a/tools/build_pkgs/src/android.rs b/tools/build_pkgs/src/android.rs new file mode 100644 index 000000000..0139bd232 --- /dev/null +++ b/tools/build_pkgs/src/android.rs @@ -0,0 +1,66 @@ +use crate::{Package, get_repo_root, run}; +use color_eyre::eyre::Result; + +pub fn build(package: &Package) -> Result<()> { + let gradle_root_dir = get_repo_root() + .join("packages") + .join("android") + .join(package.to_string()); + + let so_file_output_dir = gradle_root_dir.join("src").join("main").join("jniLibs"); + let kotlin_out_dir = gradle_root_dir.join("src").join("main").join("kotlin"); + + // Build for Android targets + let cargo_build_cmd = format!( + "cargo ndk -o {} --manifest-path {} -t armeabi-v7a -t arm64-v8a -t x86_64 build --release", + so_file_output_dir.display(), + package.crate_manifest().display() + ); + + run(&cargo_build_cmd, None, None)?; + + // Build for host platform (for running unit tests) + println!("Building for host platform to enable unit tests..."); + let host_build_cmd = format!( + "cargo build --manifest-path {} --release", + package.crate_manifest().display() + ); + run(&host_build_cmd, None, None)?; + + // Copy host library to test resources so JNA can find it + let test_resources_dir = gradle_root_dir.join("src").join("test").join("resources"); + + std::fs::create_dir_all(&test_resources_dir)?; + + let host_dylib = package.dylib(None); + let test_lib_dest = test_resources_dir.join(host_dylib.file_name().unwrap()); + + std::fs::copy(&host_dylib, &test_lib_dest)?; + println!( + "Copied host library from {} to {} for unit tests", + host_dylib.display(), + test_lib_dest.display() + ); + + if kotlin_out_dir.exists() { + std::fs::remove_dir_all(&kotlin_out_dir)?; + } + + run( + &format!( + "cargo run -p uniffi-bindgen generate --library {} --language kotlin --out-dir {}", + package.dylib(Some("aarch64-linux-android")).display(), + kotlin_out_dir.display() + ), + None, + None, + )?; + + run( + "sh -c './gradlew assembleRelease'", + Some(&gradle_root_dir), + None, + )?; + + Ok(()) +} diff --git a/tools/build_pkgs/src/main.rs b/tools/build_pkgs/src/main.rs index a7dfd61aa..c859754ab 100644 --- a/tools/build_pkgs/src/main.rs +++ b/tools/build_pkgs/src/main.rs @@ -1,3 +1,4 @@ +mod android; mod python; mod swift; @@ -16,6 +17,8 @@ enum Language { #[value(alias = "py")] Python, Swift, + #[value(alias = "aar")] + Android, } impl Display for Language { @@ -23,6 +26,7 @@ impl Display for Language { match self { Language::Python => f.write_str("python"), Language::Swift => f.write_str("swift"), + Language::Android => f.write_str("android"), } } } @@ -32,6 +36,7 @@ impl Language { match self { Self::Python => python::build(pkg), Self::Swift => swift::build(pkg), + Self::Android => android::build(pkg), } } @@ -70,23 +75,29 @@ impl Package { self.crate_dir().join("Cargo.toml") } - fn dylib(&self) -> PathBuf { + fn dylib(&self, target: Option<&str>) -> PathBuf { let mut prefix = "lib"; - let ext = if cfg!(target_os = "windows") { + let ext = if target.map_or(cfg!(target_os = "windows"), |t| t.contains("windows")) { prefix = ""; "dll" - } else if cfg!(target_os = "macos") { + } else if target.map_or(cfg!(target_os = "macos"), |t| t.contains("darwin")) { "dylib" } else { "so" }; - get_repo_root().join("target").join("release").join(format!( - "{}{}.{}", - prefix, - self.crate_name(), - ext - )) + let mut lib_path = get_repo_root().join("target"); + + if let Some(target) = target { + lib_path = lib_path.join(target); + } + + lib_path = + lib_path + .join("release") + .join(format!("{}{}.{}", prefix, self.crate_name(), ext)); + + lib_path } } diff --git a/tools/build_pkgs/src/python.rs b/tools/build_pkgs/src/python.rs index 391139dab..57de192c6 100644 --- a/tools/build_pkgs/src/python.rs +++ b/tools/build_pkgs/src/python.rs @@ -20,7 +20,7 @@ pub fn build(package: &Package) -> Result<()> { run( &format!( r#"cargo --color always run -p uniffi-bindgen generate --no-format --library "{}" --language python --out-dir "{}""#, - package.dylib().display(), + package.dylib(None).display(), module_dir.display() ), None, @@ -28,8 +28,8 @@ pub fn build(package: &Package) -> Result<()> { )?; std::fs::copy( - package.dylib(), - module_dir.join(package.dylib().file_name().unwrap()), + package.dylib(None), + module_dir.join(package.dylib(None).file_name().unwrap()), )?; run("poetry install --only build", Some(&package_dir), None)?;