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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,9 @@ target/
**/.flutter-plugins-dependencies
build/
rust/target/

# FVM Version Cache
.fvm/

# MkDocs generated
site/
10 changes: 5 additions & 5 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
[submodule "packages/boltz"]
path = packages/boltz
url = git@github.com:SatoshiPortal/boltz-dart.git
url = https://github.com/SatoshiPortal/boltz-dart.git
[submodule "packages/lwk"]
path = packages/lwk
url = git@github.com:SatoshiPortal/lwk-dart.git
url = https://github.com/SatoshiPortal/lwk-dart.git
[submodule "packages/bbqr"]
path = packages/bbqr
url = git@github.com:SatoshiPortal/bbqr-dart.git
url = https://github.com/SatoshiPortal/bbqr-dart.git
[submodule "packages/ark-wallet"]
path = packages/ark-wallet
url = git@github.com:SatoshiPortal/ark-wallet-dart.git
url = https://github.com/SatoshiPortal/ark-wallet-dart.git
[submodule "packages/bitbox"]
path = packages/bitbox
url = git@github.com:SatoshiPortal/bitbox-dart.git
url = https://github.com/SatoshiPortal/bitbox-dart.git
137 changes: 137 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
# Bull SDK

Unified flutter_rust_bridge bindings for Bitcoin and Liquid wallet operations. Merges Ark, BBQr, Boltz, LWK, and Bitbox into a single native library.

## Setup Commands

```bash
# Initialize git submodules (required — packages are submodules)
git submodule update --init --recursive

# Install Flutter dependencies (FVM manages Flutter version)
fvm flutter pub get

# Install Rust dependencies
cargo fetch
```

## Build Commands

```bash
# Build the unified native library (Rust + Dart bindings)
cd packages/bull_sdk
flutter_rust_bridge_codegen generate
bash fix_frb_generated.sh
cargo check -p rust_lib_bull_sdk
```

## Test Commands

```bash
# Run integration tests (requires device/emulator)
cd packages/bull_sdk
flutter test integration_test/

# Run satoshifier unit tests
cd packages/satoshifier
flutter test test/

# Run satoshifier integration tests
cd packages/satoshifier/example
flutter test integration_test/

# Lint
cd packages/bull_sdk
flutter analyze

# Documentation (MkDocs)
mkdocs serve # Dev server at localhost:8001
mkdocs build # Build static site to site/
```

## Project Structure

```
bull-sdk/
├── Cargo.toml # Cargo workspace (Rust)
├── pubspec.yaml # Dart workspace root
├── packages/
│ ├── bull_sdk/ # Unified FRB package (single native library)
│ │ ├── flutter_rust_bridge.yaml # FRB codegen config — scans all sub-crate APIs
│ │ ├── fix_frb_generated.sh # Post-codegen patches (MANDATORY)
│ │ ├── rust/ # Bridge crate (rust_lib_bull_sdk)
│ │ ├── lib/ # Dart exports: ark.dart, bbqr.dart, boltz.dart, lwk.dart, bitbox.dart
│ │ ├── integration_test/ # Integration tests
│ │ └── rust_builder/ # Native build tooling (cargokit)
│ ├── ark-wallet/ # git submodule → SatoshiPortal/ark-wallet-dart
│ ├── bbqr/ # git submodule → SatoshiPortal/bbqr-dart
│ ├── boltz/ # git submodule → SatoshiPortal/boltz-dart
│ ├── lwk/ # git submodule → SatoshiPortal/lwk-dart
│ ├── bitbox/ # git submodule → SatoshiPortal/bitbox-dart
│ ├── boltz-stream/ # Pure Dart — BoltzWebSocket (depends on bull_sdk)
│ ├── satoshifier/ # git submodule → SatoshiPortal/dart-satoshifier
│ └── bitbox-transport/ # Transport layer for Bitbox hardware
```

## Architecture

`bull_sdk` is a single flutter_rust_bridge package that generates unified Dart bindings by scanning the Rust API of each sub-crate as external dependencies:

```
┌─────────────────────────────────────────────┐
│ bull_sdk (Dart) │
│ lib/ark.dart lib/boltz.dart lib/lwk.dart│
├─────────────────────────────────────────────┤
│ frb_generated.rs (unified) │
│ Single FFI dispatcher for all FFI │
├─────────────────────────────────────────────┤
│ ark_wallet │ bbqr │ boltz │ lwk │ bitbox │
│ (Rust external crates via Cargo deps) │
└─────────────────────────────────────────────┘
```

- **One native library** — all Rust code compiles into a single `.so`/`.dylib`
- **Sub-crate `frb_generated` is cfg-gated** — when used as a dependency of `bull_sdk`, each sub-crate's `frb_generated.rs` is disabled via `#[cfg(not(feature = "bull_sdk"))]`
- **Mirror types** — Rust enums with data (like `TxFee`, `ArkTransaction`) use `#[frb(mirror)]` to generate proper sealed Dart classes

## Key Configuration

| Item | Value | Notes |
|------|-------|-------|
| Rust toolchain | `1.95.0` | Pinned in `rust-toolchain.toml` |
| Flutter version | `3.44.2` | Pinned via FVM in `.fvmrc` |
| Dart SDK | `>=3.1.0` | bull_sdk; `>=3.12.2` for satoshifier/boltz-stream |
| flutter_rust_bridge | `2.12.0` | Exact version pinned in pubspec and Cargo.toml |
| Cargo profile release | `opt-level = "z"`, `lto = true`, `panic = "abort"` | Aggressive size optimization |

## Skills Reference

| Skill | Trigger | Covers |
|-------|---------|--------|
| [frb-codegen](skills/frb-codegen/SKILL.md) | FRB codegen, regenerate bindings, fix_frb_generated | Full FRB codegen + post-processing workflow |

## Docs Reference

| Page | URL | Content |
|------|-----|---------|
| Home | `localhost:8001` | Overview, modules, quick start |
| API Reference | `localhost:8001/api-reference/` | Boltz, LWK, Ark, BBQr, Bitbox |
| Architecture | `localhost:8001/architecture/` | Design decisions, dependency graph |
| Troubleshooting | `localhost:8001/development/troubleshooting/` | Common errors and fixes |
| robots.txt | `localhost:8001/robots.txt` | Agent-aware crawl directives |
| llms.txt | `localhost:8001/llms.txt` | Service description for LLMs |

## Gotchas

- **Submodules must be initialized** — `git submodule update --init --recursive` is required before anything builds. Without it, Rust deps and Dart packages are missing.
- **Submodule URLs use SSH** — `.gitmodules` uses `git@github.com:` URLs. In containers or CI without SSH keys, convert to HTTPS: `sed -i 's|git@github.com:|https://github.com/|' .gitmodules && git submodule sync && git submodule update --init --recursive`
- **Always run `fix_frb_generated.sh` after FRB codegen** — FRB cannot automatically handle external crate error types or mirrored enum conversions. Without this step, the build will fail with type mismatch errors.
- **Sub-crate `frb_generated` conflicts** — Each submodule has its own `frb_generated.rs`. When used as a `bull_sdk` dependency, the `bull_sdk` feature gate disables them. Never commit sub-crate FRB output into bull_sdk.
- **Mirror types are manual** — Data-variant Rust enums scanned as external crate types become opaque. You must create mirror types in `packages/bull_sdk/rust/src/api/simple.rs` and implement `From` conversions.
- **`fix_frb_generated.sh` uses macOS `sed`** — The script uses `sed -i ''` which is macOS-specific. On Linux, use `sed -i` (no empty string argument). Patch before running.
- **Cargo workspace excludes submodules** — The root `Cargo.toml` workspace only includes `packages/bull_sdk/rust`. Submodule Rust code is excluded from the workspace to avoid duplicate symbol errors.

## Git Conventions

- Commit format: conventional commits (`type: description`)
- Submodule branches tracked in `.gitmodules` — changes to submodule refs require coordinated updates
65 changes: 49 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
# bull_sdk
# Bull SDK

Unified flutter_rust_bridge bindings for Bitcoin and Liquid wallet operations.

> **AI Agent?** This repo includes [`AGENTS.md`](AGENTS.md) with setup commands, architecture, gotchas, and everything you need to work here. Read it first.

## Why

Over the past years, we contributed to the open source community by creating flutter_rust_bridge bindings for several Bitcoin/Liquid libraries:
Expand Down Expand Up @@ -40,24 +42,43 @@ This produces **one native library** containing all the Rust code, with **one FR

```
bull-sdk/
├── Cargo.toml # Cargo workspace
├── AGENTS.md # AI agent instructions
├── Cargo.toml # Cargo workspace
├── packages/
│ ├── bull_sdk/ # Unified FRB package (single native library)
│ ├── bull_sdk/ # Unified FRB package (single native library)
│ │ ├── flutter_rust_bridge.yaml
│ │ ├── fix_frb_generated.sh # Post-processing script
│ │ ├── rust/ # Bridge crate
│ │ ├── fix_frb_generated.sh # Post-processing script
│ │ ├── rust/ # Bridge crate
│ │ └── lib/
│ │ ├── bull_sdk.dart # BullSdk.init()
│ │ ├── ark.dart # Ark wallet types
│ │ ├── bbqr.dart # BBQr types
│ │ ├── boltz.dart # Boltz swap types
│ │ └── lwk.dart # Liquid Wallet Kit types
│ ├── ark-wallet/ # git submodule → SatoshiPortal/ark-wallet-dart
│ ├── bbqr/ # git submodule → SatoshiPortal/bbqr-dart
│ ├── boltz/ # git submodule → SatoshiPortal/boltz-dart
│ ├── lwk/ # git submodule → SatoshiPortal/lwk-dart
│ ├── boltz-stream/ # Pure Dart — BoltzWebSocket (depends on bull_sdk)
│ └── satoshifier/ # git submodule → SatoshiPortal/dart-satoshifier
│ │ ├── bull_sdk.dart # BullSdk.init()
│ │ ├── ark.dart # Ark wallet types
│ │ ├── bbqr.dart # BBQr types
│ │ ├── boltz.dart # Boltz swap types
│ │ └── lwk.dart # Liquid Wallet Kit types
│ ├── ark-wallet/ # git submodule → SatoshiPortal/ark-wallet-dart
│ ├── bbqr/ # git submodule → SatoshiPortal/bbqr-dart
│ ├── boltz/ # git submodule → SatoshiPortal/boltz-dart
│ ├── lwk/ # git submodule → SatoshiPortal/lwk-dart
│ ├── boltz-stream/ # Pure Dart — BoltzWebSocket (depends on bull_sdk)
│ └── satoshifier/ # git submodule → SatoshiPortal/dart-satoshifier
├── skills/
│ ├── agent-init/ # Reusable repo onboarding skill
│ └── frb-codegen/ # FRB codegen workflow + troubleshooting
└── docs/ # MkDocs site (EN/ES/IT/PT)
```

## Quick start

```bash
# 1. Initialize submodules
git submodule update --init --recursive

# 2. Install dependencies
fvm flutter pub get && cargo fetch

# 3. Build
cd packages/bull_sdk
cargo check -p rust_lib_bull_sdk
```

## Regenerating bindings
Expand All @@ -71,6 +92,18 @@ cargo check -p rust_lib_bull_sdk

Always run `fix_frb_generated.sh` after codegen — it patches error type wrapping and mirror type conversions that FRB cannot handle automatically for external crate types.

## Documentation

Full docs at **https://lassetrwa-ship-it.github.io/bull_sdk/**

- [Installation](https://lassetrwa-ship-it.github.io/bull_sdk/getting-started/installation/)
- [Quick Start](https://lassetrwa-ship-it.github.io/bull_sdk/getting-started/quickstart/)
- [Architecture](https://lassetrwa-ship-it.github.io/bull_sdk/architecture/)
- [API Reference](https://lassetrwa-ship-it.github.io/bull_sdk/api-reference/)
- [Troubleshooting](https://lassetrwa-ship-it.github.io/bull_sdk/development/troubleshooting/)

Available in: [English](/) | [Español](/es/) | [Italiano](/it/) | [Português](/pt/)

## Usage

```dart
Expand Down
129 changes: 129 additions & 0 deletions docs/api-reference/ark.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
# Ark — Ark Protocol

Ark protocol wallet: offchain payments, boarding, and settlements.

**Import:** `package:bull_sdk/ark.dart`

---

## ArkWallet

Core class for Ark protocol operations.

### Initialization

```dart
final wallet = await ark.ArkWallet.init(
secretKey: secretKey, // List<int> (32 bytes)
network: 'mainnet', // or 'testnet'
esplora: 'https://esplora.blockstream.info',
server: 'https://arkserver.example.com',
boltz: 'https://boltz.exchange',
);
```

### Addresses

```dart
// Offchain Ark address
final offchainAddr = wallet.offchainAddress();

// Onchain boarding address
final onchainAddr = wallet.onchainAddress();

// Boarding address (same as onchain, for boarding UTXOs)
final boardingAddr = wallet.boardingAddress();
```

### Sending

```dart
// Send offchain (Ark-to-Ark, instant)
final txid = await wallet.sendOffChain(
address: 'ark1q...',
sats: BigInt.from(100000),
);

// Send onchain (standard Bitcoin/Liquid transaction)
final txid = await wallet.sendOnChain(
address: 'bc1q...',
sats: BigInt.from(100000),
);
```

### Settlements

```dart
// Settle pending offchain transactions
await wallet.settle(selectRecoverableVtxos: true);

// Settle boarding transactions (onchain → offchain)
final status = await wallet.settleBoardingTransactions(
selectRecoverableVtxos: true,
);

// Check boarding status
final boardingStatus = await wallet.getBoardingStatus();
final canSettle = await wallet.canSettleBoarding();
```

### Balance and History

```dart
final balance = await wallet.balance();
// Returns ArkBalance

final history = await wallet.transactionHistory();
// Returns List<ArkTransaction>
```

---

## ArkTransaction

Union type representing different transaction states:

```dart
enum ArkTransaction {
Boarding {
String txid;
int sats;
int? confirmedAt;
},
Commitment {
String txid;
int sats;
int createdAt;
},
Redeem {
String txid;
int sats;
bool isSettled;
int createdAt;
},
}
```

| Variant | Meaning |
|---------|---------|
| `Boarding` | Onchain UTXO awaiting settlement to offchain |
| `Commitment` | Offchain commitment created |
| `Redeem` | Offchain redemption (settled or pending) |

---

## Server Info

```dart
final info = wallet.serverInfo();
// Returns ServerInfo with server details
```

---

## Gotchas

- **Secret key**: Must be exactly 32 bytes. Store securely — it controls the wallet.
- **Boarding delay**: Boarding transactions require confirmation before they can be settled. Check `canSettleBoarding()` before attempting settlement.
- **Recoverable VTXOs**: When `selectRecoverableVtxos: true`, the wallet selects UTXOs that can be recovered if the server goes offline.
- **Network strings**: Ark uses string network identifiers (`'mainnet'`/`'testnet'`), not enum values like LWK.
Loading