Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
0883d5a
feat: prepare tinywallet to serve as an out-of-process signing backend
senamakel Aug 11, 2026
9ab62cd
fix(abi): handle empty input in ABI decoding
senamakel Aug 11, 2026
3fd972f
refactor(abi): move sha3 import into test-only keccak function
senamakel Aug 11, 2026
c42c3e8
fix(abi): correct test assertion for empty input handling
senamakel Aug 11, 2026
5db5c02
feat(features): add abi feature gate for ERC-20 transfer calldata
senamakel Aug 11, 2026
9be8e2d
chore(workspace): add workspace config and update vendored tinybus
senamakel Aug 11, 2026
0af6679
chore(deps): update `serde` dependency to 1.0.200
senamakel Aug 11, 2026
0810e1e
fix(service): handle empty wallet name in create wallet endpoint
senamakel Aug 11, 2026
f11ed44
fix(module): remove unused import to resolve compiler warning
senamakel Aug 11, 2026
a2c851a
test(service): add test module for service layer
senamakel Aug 11, 2026
d5e9595
feat: add tinybus workspace with module and wallet crates
senamakel Aug 11, 2026
ad9bc3c
feat(tinywallet-module): add base58 encoding for Solana transaction i…
senamakel Aug 11, 2026
89723eb
fix(test): update test to verify new validation logic
senamakel Aug 11, 2026
b7be0df
chore(tinywallet-module): add bitcoin dependency for signing in servi…
senamakel Aug 11, 2026
d814fa5
chore: reformat long lines in service and test files
senamakel Aug 11, 2026
72ca9ad
refactor(service): accept reference in build_failed helper
senamakel Aug 11, 2026
a5f9cae
fix(tests): restore missing e2e test for wallet module
senamakel Aug 11, 2026
ff2c365
feat(tinywallet-module): add ed25519-dalek and tokio dependencies
senamakel Aug 11, 2026
06c5d32
docs(specs): add tinybus module specification
senamakel Aug 11, 2026
b11bea1
feat(ci): add native module bundle and GitHub release workflow
senamakel Aug 11, 2026
0bf7632
ci(workflows): add module e2e test and fix release version bump
senamakel Aug 11, 2026
bd0655c
ci: exclude vendored submodules from coverage threshold check
senamakel Aug 11, 2026
fe3e110
test(btc): add branch-coverage tests for hand-rolled address parser
senamakel Aug 11, 2026
3ff6850
test(abi): add test for malformed address rejection without panic
senamakel Aug 11, 2026
fb46595
fix(ci): scope msrv build to the published library
senamakel Aug 11, 2026
2bf453c
fix(ci): clarify jq comment about vendored submodules
senamakel Aug 11, 2026
83a7b87
refactor(btc): replace hardcoded HRP list with generic bech32 shape d…
senamakel Aug 11, 2026
3341f4f
test(btc): add tests for invalid base58 and foreign bech32 addresses
senamakel Aug 11, 2026
22a1171
fix(btc): flatten error map closure and simplify test formatting
senamakel Aug 11, 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
37 changes: 36 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,11 @@ jobs:
below_threshold="$(jq -r '
.data[0].files[]
| select(.filename | contains("/src/"))
# Vendored submodules carry code from another repository, whose
# coverage is not this one to enforce. They only entered the report
# when the module crate made tinybus part of the build graph.
# (No apostrophes here: the whole jq program is single-quoted.)
| select(.filename | contains("/vendor/") | not)
| select(.summary.lines.percent < 90)
| "\(.filename): \(.summary.lines.percent)%"
' "$report")"
Expand All @@ -74,6 +79,31 @@ jobs:
exit 1
fi


module-e2e:
name: TinyBus module E2E
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
with:
persist-credentials: false
submodules: true

- uses: dtolnay/rust-toolchain@stable

- uses: Swatinem/rust-cache@v2

- name: Build the loadable module
run: cargo build --locked --release --package tinywallet-module

# The only test that exercises the real cdylib, the ABI and manifest
# gates, the dynamic loader and a broker routing frames. It asserts that
# signing through the module equals signing in-process, byte for byte.
- name: Load the module and sign on every chain
env:
TINYWALLET_TEST_MODULE: ${{ github.workspace }}/target/release/libtinywallet_module.so
run: cargo test --locked --release --package tinywallet-module --test module_e2e -- --ignored

docs:
name: Docs
runs-on: ubuntu-latest
Expand Down Expand Up @@ -119,8 +149,13 @@ jobs:

- uses: Swatinem/rust-cache@v2

# Scoped to the published library on purpose. `tinywallet-module` is
# `publish = false` and depends on tinybus, whose macros use let-chains
# and so need a newer compiler than this crate promises its consumers.
# Holding the module to the library's MSRV would either fail here or
# force the library's MSRV up for a crate nobody depends on.
- name: Build with the declared MSRV
run: cargo build --all-targets --all-features
run: cargo build --package tinywallet --all-targets --all-features

supply-chain:
name: Supply chain
Expand Down
223 changes: 220 additions & 3 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ jobs:
if: ${{ github.ref == 'refs/heads/main' }}
runs-on: ubuntu-latest
environment: Production
outputs:
crate_name: ${{ steps.version.outputs.crate_name }}
next_version: ${{ steps.version.outputs.next_version }}
tag: ${{ steps.version.outputs.tag }}
steps:
- uses: actions/checkout@v7
with:
Expand Down Expand Up @@ -107,8 +111,19 @@ jobs:
NEXT_VERSION: ${{ steps.version.outputs.next_version }}
run: |
set -euo pipefail
perl -0pi -e 's/(\[package\][\s\S]*?\nversion = ")[^"]+(")/$1$ENV{NEXT_VERSION}$2/' Cargo.toml
cargo update -p "$CRATE_NAME" --precise "$NEXT_VERSION"
bump() {
perl -0pi -e 's/(\[package\][\s\S]*?\nversion = ")[^"]+(")/$1$ENV{NEXT_VERSION}$2/' "$1"
}
bump Cargo.toml
# The module crate is bumped in lockstep, not left behind. Its
# `cdylib` ships in an archive named for the *root* crate's version,
# so a drift here would publish `tinywallet-module-0.2.0-*.tar.gz`
# containing a library that reports 0.1.0 — with nothing to catch it.
bump crates/tinywallet-module/Cargo.toml
# Refreshes both workspace members in the lockfile. `cargo update -p`
# cannot do this: these are path dependencies, and the later
# `--locked` steps fail against a stale lock.
cargo update --workspace

- name: Commit version bump and tag
env:
Expand All @@ -117,7 +132,7 @@ jobs:
set -euo pipefail
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git add Cargo.toml Cargo.lock
git add Cargo.toml Cargo.lock crates/tinywallet-module/Cargo.toml
git commit -m "Release ${RELEASE_TAG}"
git tag -a "${RELEASE_TAG}" -m "Release ${RELEASE_TAG}"

Expand All @@ -136,3 +151,205 @@ jobs:
run: cargo publish --locked
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}

native-bundles:
name: Module bundle (${{ matrix.id }})
needs: publish
strategy:
fail-fast: false
matrix:
include:
- id: ubuntu-22.04-x86_64
os: ubuntu-22.04
target: x86_64-unknown-linux-gnu
- id: ubuntu-22.04-arm64
os: ubuntu-22.04-arm
target: aarch64-unknown-linux-gnu
- id: ubuntu-24.04-x86_64
os: ubuntu-24.04
target: x86_64-unknown-linux-gnu
- id: ubuntu-24.04-arm64
os: ubuntu-24.04-arm
target: aarch64-unknown-linux-gnu
- id: macos-15-x86_64
os: macos-15-intel
target: x86_64-apple-darwin
- id: macos-15-arm64
os: macos-15
target: aarch64-apple-darwin
- id: macos-26-x86_64
os: macos-26-intel
target: x86_64-apple-darwin
- id: macos-26-arm64
os: macos-26
target: aarch64-apple-darwin
- id: windows-2022-x86_64
os: windows-2022
target: x86_64-pc-windows-msvc
- id: windows-2025-x86_64
os: windows-2025
target: x86_64-pc-windows-msvc
- id: windows-11-arm64
os: windows-11-arm
target: aarch64-pc-windows-msvc
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v7
with:
ref: ${{ needs.publish.outputs.tag }}
persist-credentials: false
submodules: true

- uses: dtolnay/rust-toolchain@stable

- uses: Swatinem/rust-cache@v2

- name: Verify native Rust target
shell: bash
env:
EXPECTED_TARGET: ${{ matrix.target }}
run: |
set -euo pipefail
actual_target="$(rustc -vV | sed -n 's/^host: //p')"
[[ "$actual_target" == "$EXPECTED_TARGET" ]]

- name: Build installable module
run: cargo build --locked --release --package tinywallet-module

- name: Assemble Unix module package
if: ${{ runner.os != 'Windows' }}
id: unix_package
shell: bash
env:
BUNDLE_ID: ${{ matrix.id }}
VERSION: ${{ needs.publish.outputs.next_version }}
run: |
set -euo pipefail

library_name="tinywallet_module"
case "$RUNNER_OS" in
Linux) module="target/release/lib${library_name}.so" ;;
macOS) module="target/release/lib${library_name}.dylib" ;;
*) echo "unsupported Unix runner: ${RUNNER_OS}" >&2; exit 1 ;;
esac
package_name="tinywallet-module-${VERSION}-${BUNDLE_ID}"
package_root="dist/${package_name}"
mkdir -p "$package_root"
install -m 755 "$module" "$package_root/"
install -m 644 LICENSE README.md docs/specs/tinybus-module.md "$package_root/"
module_name="$(basename "$module")"
module_hash="$(sha256sum "$package_root/$module_name" | awk '{print $1}')"
printf '"%s" = "%s"\n' "$module_name" "$module_hash" \
> "$package_root/modules.toml"
tar -C "$package_root" -czf "dist/${package_name}.tar.gz" .
echo "archive=dist/${package_name}.tar.gz" >> "$GITHUB_OUTPUT"

- name: Assemble Windows module package
if: ${{ runner.os == 'Windows' }}
id: windows_package
shell: pwsh
env:
BUNDLE_ID: ${{ matrix.id }}
VERSION: ${{ needs.publish.outputs.next_version }}
run: |
$ErrorActionPreference = 'Stop'
$libraryName = 'tinywallet_module'
$module = "target/release/$libraryName.dll"
$packageName = "tinywallet-module-$env:VERSION-$env:BUNDLE_ID"
$packageRoot = "dist/$packageName"
New-Item -ItemType Directory -Force $packageRoot | Out-Null
Copy-Item -LiteralPath $module, 'LICENSE', 'README.md' -Destination $packageRoot
$hash = (Get-FileHash -LiteralPath $module -Algorithm SHA256).Hash.ToLowerInvariant()
$moduleName = Split-Path -Leaf $module
"`"$moduleName`" = `"$hash`"`n" |
Set-Content -Path "$packageRoot/modules.toml" -Encoding utf8NoBOM
Compress-Archive -Path "$packageRoot/*" -DestinationPath "dist/$packageName.zip"
"archive=dist/$packageName.zip" >> $env:GITHUB_OUTPUT

- name: Upload Unix module package
if: ${{ runner.os != 'Windows' }}
uses: actions/upload-artifact@v7
with:
name: tinywallet-module-${{ matrix.id }}
path: ${{ steps.unix_package.outputs.archive }}
if-no-files-found: error

- name: Upload Windows module package
if: ${{ runner.os == 'Windows' }}
uses: actions/upload-artifact@v7
with:
name: tinywallet-module-${{ matrix.id }}
path: ${{ steps.windows_package.outputs.archive }}
if-no-files-found: error

github-release:
name: Create GitHub release
needs:
- publish
- native-bundles
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
with:
ref: ${{ needs.publish.outputs.tag }}
persist-credentials: false
submodules: true

- name: Download workflow artifacts
uses: actions/download-artifact@v8
with:
pattern: tinywallet-module-*
path: release-assets
merge-multiple: true

- uses: dtolnay/rust-toolchain@stable

- name: Create release checksum manifest with TinyBus
shell: bash
run: |
set -euo pipefail
mapfile -t assets < <(
find release-assets -type f \
\( -name '*.tar.gz' -o -name '*.zip' \) \
| sort
)
if [[ ${#assets[@]} -ne 11 ]]; then
printf 'expected 11 module archives, found %s:\n' "${#assets[@]}" >&2
find release-assets -type f -print >&2 || true
exit 1
fi
checksum_args=()
for asset in "${assets[@]}"; do checksum_args+=(--path "$asset"); done
cargo run --manifest-path vendor/tinybus/Cargo.toml --locked \
--package tinybus --all-features --bin tinybus -- \
modules checksum "${checksum_args[@]}" --output release-assets/checksum.toml

- name: Create release and upload assets
env:
GH_TOKEN: ${{ github.token }}
RELEASE_TAG: ${{ needs.publish.outputs.tag }}
REPOSITORY: ${{ github.repository }}
run: |
set -euo pipefail
mapfile -t release_files < <(find release-assets -type f | sort)
gh release create "$RELEASE_TAG" "${release_files[@]}" \
--repo "$REPOSITORY" \
--verify-tag \
--title "$RELEASE_TAG" \
--generate-notes

- name: Verify the published module through TinyBus
shell: bash
env:
RELEASE_TAG: ${{ needs.publish.outputs.tag }}
REPOSITORY: ${{ github.repository }}
VERSION: ${{ needs.publish.outputs.next_version }}
run: |
set -euo pipefail
archive="tinywallet-module-${VERSION}-ubuntu-24.04-x86_64.tar.gz"
release_url="https://github.com/${REPOSITORY}/releases/tag/${RELEASE_TAG}"
sha256="$(sed -n "s/^\"${archive}\" = \"\([0-9a-f]\{64\}\)\"$/\1/p" release-assets/checksum.toml)"
test -n "$sha256"
cargo run --manifest-path vendor/tinybus/Cargo.toml --locked \
--package tinybus --all-features --example github_module_host -- \
"$release_url" "$archive" "$sha256"
Loading