Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
8e54d34
spike: add kotlin
joe-p May 7, 2025
5e597cf
wip: add android project
joe-p May 7, 2025
503ccd5
feat: add in library module
michaeltchuang May 14, 2025
f0f7677
add build scripts section
joe-p May 16, 2025
3cf8657
use cargo ndk
joe-p Jun 4, 2025
9587d18
fix: use working copy of transact rust function
michaeltchuang Jun 4, 2025
e6ba286
fix: clean up code
michaeltchuang Jun 4, 2025
6a1aea2
ci: add in mavenLocal publish
michaeltchuang Jun 5, 2025
f157dc5
Merge branch 'main' into spike/kotlin
joe-p Jun 24, 2025
d9a75e2
wip: add kotlin build script
joe-p Jun 24, 2025
308e03b
chore: update README
joe-p Jun 24, 2025
5f03448
chore: update gitignore
joe-p Jun 24, 2025
577b8df
Merge branch 'main' into spike/kotlin
joe-p Sep 17, 2025
82ac644
fix: build errors from latest main changes
michaeltchuang Sep 17, 2025
2ecf988
Merge pull request #6 from michaeltchuang/spike/kotlin
joe-p Sep 19, 2025
d6c122e
fix: replace message with error_msg for kotlin
joe-p Sep 19, 2025
6490bcf
fix: change sample app function reference
michaeltchuang Sep 19, 2025
f2827b3
Merge pull request #7 from michaeltchuang/spike/kotlin
joe-p Sep 19, 2025
c7112db
build: rm kotlin out dir before generating kotlin file
joe-p Sep 19, 2025
889a07f
wip: format swift
joe-p Sep 25, 2025
2643459
wip: swift fix build issues
joe-p Sep 25, 2025
a8dba73
wip: update swift tests
joe-p Sep 25, 2025
8bcd074
wip: new project dir
joe-p Nov 13, 2025
0c09642
chore: fix script
joe-p Nov 13, 2025
af47c41
Merge branch 'main' into spike/kotlin
joe-p Nov 13, 2025
5aa70da
chore: fix merge issues
joe-p Nov 13, 2025
d8a592e
docs: typo
joe-p Nov 13, 2025
e3912aa
chore: rebuild kt
joe-p Nov 13, 2025
22719b7
ci: kotlin ci
joe-p Nov 13, 2025
507817d
ci: specify ndk
joe-p Nov 13, 2025
8dbf107
ci: use sh -c
joe-p Nov 13, 2025
49a7036
ci: only publish on push
joe-p Nov 13, 2025
978793e
ci: remove redundant AAR step
joe-p Nov 13, 2025
919f6c8
chore: rename kotlin to android
joe-p Nov 13, 2025
e9a0056
ci: add test step
joe-p Nov 13, 2025
e6ff7b9
ci: set jdk to 21
joe-p Nov 13, 2025
5800e17
ci: ensure JNA can find libs
joe-p Nov 13, 2025
7690d36
wip: try android emulator test
joe-p Nov 13, 2025
e7d57ed
wip: specify api level
joe-p Nov 13, 2025
e135a9b
wip: specify arch
joe-p Nov 14, 2025
b8bbf90
Merge branch 'main' into spike/kotlin
joe-p Dec 11, 2025
2ff65b1
chore: generate swift and kotlin
joe-p Dec 11, 2025
f1422c3
fix: logs as Vec<u8> instead of String
joe-p Dec 11, 2025
59f0c1b
fix: delta values as Vec<u8>
joe-p Dec 11, 2025
6f7ce6b
wip: test
joe-p Dec 11, 2025
afa4c9e
wip: t1
joe-p Dec 11, 2025
7d43c51
feat: use serde_path_to_error
joe-p Dec 11, 2025
603a3e1
chore: fix typo
joe-p Dec 11, 2025
256d1af
chore: consolidate DecodingError
joe-p Dec 11, 2025
b8b8ce2
chore: rm MsgpackDecodingError
joe-p Dec 11, 2025
5273286
chore: free up more space on runner
joe-p Dec 11, 2025
3998ad8
ci: install x11 for emulator
joe-p Dec 12, 2025
85a5653
wip: lg
joe-p Dec 11, 2025
3c54afc
Merge pull request #9 from joe-p/spike/kotlin
joe-p Jan 10, 2026
1c4e0b0
Merge branch 'main' into feat/serde_path_to_err
joe-p Jan 10, 2026
dfb6117
chore: move serde_path_to_error to workspace
joe-p Jan 10, 2026
6ea9dac
Merge pull request #10 from joe-p/feat/serde_path_to_err
joe-p Jan 10, 2026
e2222d5
Merge pull request #11 from joe-p/fix/block_logs
joe-p Jan 10, 2026
4e1d4b9
fix: make timestamp optional in genesis response
joe-p Jan 10, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 76 additions & 0 deletions .github/workflows/android_ci.yml
Original file line number Diff line number Diff line change
@@ -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
13 changes: 13 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
/target
*.dylib
*.a
*.so
.zed/
.venv/
crates/**/dist/
Expand All @@ -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
Expand All @@ -22,6 +34,7 @@ AGENTS.md
.opencode/
.references/
.kiro/
.kotlin/

packages/python/**/*algokit_*.py
packages/python**/*.dll
Expand Down
15 changes: 15 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ snafu = { version = "0.8" }
base32 = { version = "0.5.1" }
sha2 = { version = "0.10.8" }
rstest = { version = "0.25.0" }
serde_path_to_error = { version = "^0.1" }

[workspace.metadata.bin]
polytest = { version = "0.3.0", locked = true }
Expand Down
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -490,6 +490,10 @@ def _generate_base_files(self, context: dict[str, Any], output_dir: Path) -> dic
files[src_dir / "msgpack_value_bytes.rs"] = self.template_engine.render_template(
"base/msgpack_value_bytes.rs.j2", context
)
# Provide msgpack helper to deserialize msgpack strings as raw bytes
files[src_dir / "msgpack_string_bytes.rs"] = self.template_engine.render_template(
"base/msgpack_string_bytes.rs.j2", context
)

return files

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ pub async fn {{ operation.rust_function_name }}(
match content_type {
ContentType::Json => {
let content = resp.text().await?;
serde_json::from_str(&content).map_err(Error::from)
serde_path_to_error::deserialize(&mut serde_json::Deserializer::from_str(&content)).map_err(Error::from)
},
ContentType::Text => Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `{{ get_success_response_type(operation) }}`"))),
ContentType::Unsupported(unknown_type) => Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `{{ get_success_response_type(operation) }}`")))),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -208,9 +208,9 @@ pub async fn {{ operation.rust_function_name }}(
.unwrap_or("application/json");

match ContentType::from(content_type) {
ContentType::Json => serde_json::from_slice(&response.body).map_err(|e| Error::Serde { message: e.to_string() }),
ContentType::Json => serde_path_to_error::deserialize(&mut serde_json::Deserializer::from_slice(&response.body)).map_err(|e| Error::Serde { message: e.to_string() }),
{% if operation.supports_msgpack %}
ContentType::MsgPack => rmp_serde::from_slice(&response.body).map_err(|e| Error::Serde { message: e.to_string() }),
ContentType::MsgPack => serde_path_to_error::deserialize(&mut rmp_serde::Deserializer::new(std::io::Cursor::new(&response.body))).map_err(|e| Error::Serde { message: e.to_string() }),
{% else %}
ContentType::MsgPack => Err(Error::Serde { message: "MsgPack not supported".to_string() }),
{% endif %}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ serde_with = { version = "^3.8", default-features = false, features = [
"macros",
] }
serde_json = "^1.0"
serde_path_to_error = { workspace = true }
serde_repr = "^0.1"
serde_bytes = "^0.11"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ uniffi::setup_scaffolding!();
pub mod apis;
pub mod models;
{% if client_type == "Algod" %}
pub mod msgpack_string_bytes;
pub mod msgpack_value_bytes;
{% endif %}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/// Custom serde module for deserializing msgpack strings as raw bytes.
///
/// Msgpack strings may contain arbitrary bytes that aren't valid UTF-8.
/// This module deserializes the raw string bytes into Vec<u8> without
/// requiring UTF-8 validity.
use serde::{Deserialize, Deserializer, Serializer};

/// Deserialize a msgpack string as raw bytes
pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<Vec<u8>>, D::Error>
where
D: Deserializer<'de>,
{
// Use rmpv::Value to capture the raw msgpack value
let value: Option<rmpv::Value> = Option::deserialize(deserializer)?;

match value {
Some(rmpv::Value::String(s)) => {
// rmpv::Utf8String gives us access to raw bytes even if not valid UTF-8
Ok(Some(s.into_bytes()))
}
Some(rmpv::Value::Binary(b)) => Ok(Some(b)),
Some(_) => Err(serde::de::Error::custom(
"expected string or binary, got other type",
)),
None => Ok(None),
}
}

/// Serialize bytes as a msgpack binary
pub fn serialize<S>(value: &Option<Vec<u8>>, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
match value {
Some(bytes) => serializer.serialize_bytes(bytes),
None => serializer.serialize_none(),
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,10 @@ pub struct BlockAppEvalDelta {
#[serde_as(as = "Option<Vec<Bytes>>")]
#[serde(rename = "sa", skip_serializing_if = "Option::is_none")]
pub shared_accounts: Option<Vec<Vec<u8>>>,
/// [lg] Application log outputs as strings (msgpack strings).
/// [lg] Application log outputs.
#[serde_as(as = "Option<Vec<Bytes>>")]
#[serde(rename = "lg", skip_serializing_if = "Option::is_none")]
pub logs: Option<Vec<String>>,
pub logs: Option<Vec<Vec<u8>>>,
}

impl AlgorandMsgpack for BlockAppEvalDelta {
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,13 @@ pub struct BlockEvalDelta {
#[serde(rename = "at")]
pub action: u32,
/// [bs] bytes value.
#[serde(rename = "bs", skip_serializing_if = "Option::is_none")]
pub bytes: Option<String>,
#[serde(
with = "crate::msgpack_string_bytes",
default,
rename = "bs",
skip_serializing_if = "Option::is_none"
)]
pub bytes: Option<Vec<u8>>,
/// [ui] uint value.
#[serde(rename = "ui", skip_serializing_if = "Option::is_none")]
pub uint: Option<u64>,
Expand Down
Loading