|
| 1 | +# Copilot Instructions for E-Bills Project |
| 2 | + |
| 3 | +## Project Overview |
| 4 | + |
| 5 | +**E-Bills** is a Rust-based project for the Bitcredit E-Bills system, primarily targeting **WebAssembly (WASM)** as the main execution environment. The project provides a core API for managing electronic bills with Bitcoin integration, Nostr-based transport, and SurrealDB persistence. |
| 6 | + |
| 7 | +## Project Structure |
| 8 | + |
| 9 | +This is a Rust workspace with the following crates: |
| 10 | + |
| 11 | +- **`bcr-ebill-core`** - Core data models, validation logic, and traits for bills, contacts, companies, and blockchain operations |
| 12 | +- **`bcr-ebill-persistence`** - Persistence traits and SurrealDB implementation (uses IndexedDB in WASM) |
| 13 | +- **`bcr-ebill-transport`** - Network transport API traits with Nostr protocol implementation |
| 14 | +- **`bcr-ebill-api`** - Main business logic and service layer integrating all components |
| 15 | +- **`bcr-ebill-wasm`** - **Primary entrypoint** - WASM bindings and JavaScript/TypeScript API surface |
| 16 | + |
| 17 | +### Key Dependencies |
| 18 | + |
| 19 | +- Bitcoin operations: `bitcoin`, `bip39`, `miniscript`, `secp256k1` |
| 20 | +- WASM integration: `wasm-bindgen`, `tsify`, `serde-wasm-bindgen` |
| 21 | +- Transport: `nostr`, `nostr-sdk` (for decentralized communication) |
| 22 | +- Database: `surrealdb` (IndexedDB for WASM, other backends for native) |
| 23 | +- Async runtime: `tokio` and `tokio_with_wasm` for cross-platform async support |
| 24 | +- Internal dependencies: `bcr-common`, `bcr-wallet-lib` (from BitcreditProtocol organization) |
| 25 | + |
| 26 | +## Architecture Principles |
| 27 | + |
| 28 | +### WASM-First Design |
| 29 | + |
| 30 | +1. **Target Environment**: The primary execution environment is WebAssembly running in browsers |
| 31 | +2. **Database**: Uses IndexedDB via SurrealDB in WASM builds (`indxdb://default` connection string) |
| 32 | +3. **Platform Abstraction**: Code must work in both single-threaded (WASM) and multi-threaded environments |
| 33 | + - Use `ServiceTraitBounds` trait for platform-specific trait bounds |
| 34 | + - `Send + Sync` on native, no bounds on `wasm32` |
| 35 | +4. **Async Runtime**: Use `tokio_with_wasm` for WASM compatibility, `tokio` for native |
| 36 | + |
| 37 | +### Core Architecture Layers |
| 38 | + |
| 39 | +``` |
| 40 | +┌─────────────────────────────────────┐ |
| 41 | +│ bcr-ebill-wasm (WASM API) │ ← TypeScript bindings, JS interface |
| 42 | +├─────────────────────────────────────┤ |
| 43 | +│ bcr-ebill-api (Business Logic) │ ← Services, orchestration |
| 44 | +├─────────────────────────────────────┤ |
| 45 | +│ bcr-ebill-transport (Nostr) │ ← Network communication |
| 46 | +│ bcr-ebill-persistence (DB) │ ← Data storage |
| 47 | +├─────────────────────────────────────┤ |
| 48 | +│ bcr-ebill-core (Domain Models) │ ← Core types, validation |
| 49 | +└─────────────────────────────────────┘ |
| 50 | +``` |
| 51 | + |
| 52 | +## Key Concepts |
| 53 | + |
| 54 | +### Bill Lifecycle |
| 55 | + |
| 56 | +E-Bills follow a complex state machine with multiple roles: |
| 57 | +- **Drawer**: Bill issuer |
| 58 | +- **Payer**: Bill drawee (who pays) |
| 59 | +- **Holder**: Current bill holder (payee or endorsee) |
| 60 | +- **Contingent**: Guarantee chain participant |
| 61 | +- **Recoursee**: Participant being recoursed against |
| 62 | +- **Buyer**: User to sell bill to |
| 63 | + |
| 64 | +### Bill States |
| 65 | + |
| 66 | +Bills have multi-dimensional states: |
| 67 | +1. **Acceptance State**: requested → accepted/rejected/expired |
| 68 | +2. **Payment State**: requested → paid/rejected/expired |
| 69 | +3. **Recourse States**: List of recourse transactions (latest first) |
| 70 | +4. **Sell States**: List of sale transactions (latest first) |
| 71 | +5. **Mint State**: Whether bill was minted |
| 72 | + |
| 73 | +See `docs/concepts.md` for detailed state machine documentation. |
| 74 | + |
| 75 | +### Blockchain Structure |
| 76 | + |
| 77 | +Bills use a blockchain-like structure with blocks representing actions. Each action creates a new block in the bill's chain. |
| 78 | + |
| 79 | +## Development Guidelines |
| 80 | + |
| 81 | +### Code Style |
| 82 | + |
| 83 | +1. **Formatting**: Use `cargo fmt` (configuration in `rustfmt.toml`) |
| 84 | +2. **Linting**: Use `cargo clippy` (configuration in `clippy.toml`) |
| 85 | + - `too-many-arguments-threshold=200` is configured |
| 86 | +3. **Validation**: Implement `Validate` trait for all domain types |
| 87 | +4. **Error Handling**: Use `thiserror` for error types, `anyhow` for contexts |
| 88 | + |
| 89 | +### Testing Strategy |
| 90 | + |
| 91 | +- **Core**: Thorough unit tests for validation and blockchain logic |
| 92 | +- **Persistence**: Unit tests for database operations |
| 93 | +- **Transport**: Unit tests for Nostr communication |
| 94 | +- **API**: Integration tests combining components |
| 95 | +- **WASM**: Basic wiring tests |
| 96 | + |
| 97 | +Run tests with: |
| 98 | +```bash |
| 99 | +cargo test # Without logs |
| 100 | +RUST_LOG=info cargo test -- --nocapture # With logs |
| 101 | +``` |
| 102 | + |
| 103 | +### WASM Development |
| 104 | + |
| 105 | +#### Building WASM |
| 106 | + |
| 107 | +```bash |
| 108 | +# Development build |
| 109 | +wasm-pack build --dev --target web --out-name index ./crates/bcr-ebill-wasm |
| 110 | + |
| 111 | +# Release build (optimized) |
| 112 | +wasm-pack build --target web ./crates/bcr-ebill-wasm |
| 113 | +``` |
| 114 | + |
| 115 | +Or use the justfile: |
| 116 | +```bash |
| 117 | +just wasm # Development build |
| 118 | +``` |
| 119 | + |
| 120 | +#### TypeScript Bindings |
| 121 | + |
| 122 | +Use `tsify` for automatic TypeScript generation from Rust types: |
| 123 | + |
| 124 | +**For structs/types:** |
| 125 | +```rust |
| 126 | +use tsify::Tsify; |
| 127 | + |
| 128 | +#[derive(Tsify, Serialize, Deserialize)] |
| 129 | +#[tsify(into_wasm_abi, from_wasm_abi)] |
| 130 | +pub struct MyType { |
| 131 | + field: String, |
| 132 | +} |
| 133 | +``` |
| 134 | + |
| 135 | +**For API functions:** |
| 136 | +```rust |
| 137 | +use wasm_bindgen::prelude::*; |
| 138 | + |
| 139 | +#[wasm_bindgen] |
| 140 | +impl MyApi { |
| 141 | + #[wasm_bindgen(unchecked_return_type = "MyReturnType")] |
| 142 | + pub async fn my_function( |
| 143 | + &self, |
| 144 | + #[wasm_bindgen(unchecked_param_type = "MyParamType")] payload: JsValue, |
| 145 | + ) -> Result<JsValue> { |
| 146 | + let param: MyParamType = serde_wasm_bindgen::from_value(payload)?; |
| 147 | + // ... logic |
| 148 | + let result = serde_wasm_bindgen::to_value(&response)?; |
| 149 | + Ok(result) |
| 150 | + } |
| 151 | +} |
| 152 | +``` |
| 153 | + |
| 154 | +**For numeric enums:** |
| 155 | +```rust |
| 156 | +#[wasm_bindgen] |
| 157 | +#[repr(u8)] |
| 158 | +#[derive(serde_repr::Serialize_repr, serde_repr::Deserialize_repr)] |
| 159 | +pub enum MyEnum { |
| 160 | + Variant1 = 0, |
| 161 | + Variant2 = 1, |
| 162 | +} |
| 163 | +``` |
| 164 | + |
| 165 | +**For string-based enums:** |
| 166 | +```rust |
| 167 | +#[derive(Tsify, Serialize, Deserialize)] |
| 168 | +#[tsify(into_wasm_abi, from_wasm_abi)] |
| 169 | +pub enum MyEnum { |
| 170 | + Variant1, |
| 171 | + Variant2, |
| 172 | +} |
| 173 | +``` |
| 174 | + |
| 175 | +#### Testing WASM Locally |
| 176 | + |
| 177 | +```bash |
| 178 | +# Build and serve |
| 179 | +just wasm |
| 180 | +just serve |
| 181 | + |
| 182 | +# Or manually |
| 183 | +wasm-pack build --dev --target web ./crates/bcr-ebill-wasm |
| 184 | +http-server -g -c-1 -p 8081 ./crates/bcr-ebill-wasm/ |
| 185 | +``` |
| 186 | + |
| 187 | +Access at http://localhost:8081/ and use browser DevTools (Storage tab) to inspect IndexedDB. |
| 188 | + |
| 189 | +### Configuration |
| 190 | + |
| 191 | +WASM apps require initialization with config: |
| 192 | + |
| 193 | +```javascript |
| 194 | +let config = { |
| 195 | + bitcoin_network: "testnet", // mainnet, testnet, testnet4, regtest |
| 196 | + esplora_base_url: "https://esplora.minibill.tech", |
| 197 | + nostr_relays: ["wss://bcr-relay-dev.minibill.tech"], |
| 198 | + surreal_db_connection: "indxdb://default", // IndexedDB for WASM |
| 199 | + data_dir: ".", |
| 200 | + job_runner_initial_delay_seconds: 1, |
| 201 | + job_runner_check_interval_seconds: 600, |
| 202 | +}; |
| 203 | + |
| 204 | +await wasm.default(); |
| 205 | +await wasm.initialize_api(config); |
| 206 | +``` |
| 207 | + |
| 208 | +## Common Tasks |
| 209 | + |
| 210 | +### Adding a New Feature |
| 211 | + |
| 212 | +1. **Domain Model** (`bcr-ebill-core`): Add types with `Validate` trait |
| 213 | +2. **Persistence** (`bcr-ebill-persistence`): Add repository traits and implementations |
| 214 | +3. **Transport** (`bcr-ebill-transport`): Add network operations if needed |
| 215 | +4. **Business Logic** (`bcr-ebill-api`): Add service methods |
| 216 | +5. **WASM API** (`bcr-ebill-wasm`): Expose via WASM bindings with TypeScript types |
| 217 | +6. **Tests**: Add unit tests at each layer, integration tests in API |
| 218 | +7. **Documentation**: Update relevant docs in `docs/` |
| 219 | + |
| 220 | +### Working with Bills |
| 221 | + |
| 222 | +Bills are central to this system. Key files: |
| 223 | +- `crates/bcr-ebill-core/src/bill/` - Bill types and validation |
| 224 | +- `crates/bcr-ebill-core/src/blockchain/bill/` - Bill blockchain structure |
| 225 | +- `crates/bcr-ebill-api/src/service/` - Bill business logic |
| 226 | + |
| 227 | +### Bitcoin Integration |
| 228 | + |
| 229 | +The project uses Bitcoin for payments. Key considerations: |
| 230 | +- Support for multiple networks (mainnet, testnet, testnet4, regtest) |
| 231 | +- Esplora integration for blockchain queries |
| 232 | +- Miniscript for complex spending conditions |
| 233 | +- Payment tracking via mempool and confirmations |
| 234 | + |
| 235 | +### Nostr Transport |
| 236 | + |
| 237 | +Communication uses the Nostr protocol: |
| 238 | +- Decentralized relay-based messaging |
| 239 | +- NIP-04 and NIP-59 support |
| 240 | +- Configured via relay URLs in config |
| 241 | + |
| 242 | +## Build and CI |
| 243 | + |
| 244 | +### Quality Checks |
| 245 | + |
| 246 | +Use the `check` recipe in justfile: |
| 247 | +```bash |
| 248 | +just check |
| 249 | +``` |
| 250 | + |
| 251 | +This runs: |
| 252 | +1. WASM build |
| 253 | +2. Format check (`cargo fmt -- --check`) |
| 254 | +3. Compilation check (`cargo check`) |
| 255 | +4. All tests (`cargo test --all`) |
| 256 | +5. Clippy lints (`cargo clippy --all-targets --all-features -- -D warnings`) |
| 257 | +6. Dependency audit (`cargo deny check`) |
| 258 | + |
| 259 | +### CI Pipeline |
| 260 | + |
| 261 | +GitHub Actions workflow (`.github/workflows/`) runs on all branches: |
| 262 | +- Format, build, test, lint checks |
| 263 | +- Uses GitHub App token for private repo access (bcr-common, bcr-wallet-lib) |
| 264 | +- Disk space optimization for limited runners |
| 265 | + |
| 266 | +## Important Patterns |
| 267 | + |
| 268 | +### Platform-Specific Code |
| 269 | + |
| 270 | +```rust |
| 271 | +#[cfg(not(target_arch = "wasm32"))] |
| 272 | +pub trait ServiceTraitBounds: Send + Sync {} |
| 273 | + |
| 274 | +#[cfg(target_arch = "wasm32")] |
| 275 | +pub trait ServiceTraitBounds {} |
| 276 | +``` |
| 277 | + |
| 278 | +### Validation Pattern |
| 279 | + |
| 280 | +```rust |
| 281 | +impl Validate for MyType { |
| 282 | + fn validate(&self) -> Result<(), ValidationError> { |
| 283 | + // Validation logic |
| 284 | + Ok(()) |
| 285 | + } |
| 286 | +} |
| 287 | +``` |
| 288 | + |
| 289 | +### Error Handling in WASM |
| 290 | + |
| 291 | +```rust |
| 292 | +#[derive(Tsify, Serialize)] |
| 293 | +#[tsify(into_wasm_abi)] |
| 294 | +struct JsErrorData { |
| 295 | + error: &'static str, |
| 296 | + message: String, |
| 297 | + code: u16, |
| 298 | +} |
| 299 | +``` |
| 300 | + |
| 301 | +JavaScript side uses try/catch: |
| 302 | +```javascript |
| 303 | +try { |
| 304 | + let result = await api.someMethod(params); |
| 305 | +} catch (error) { |
| 306 | + // error has: { error, message, code } |
| 307 | +} |
| 308 | +``` |
| 309 | + |
| 310 | +## Documentation |
| 311 | + |
| 312 | +- `README.md` - Project overview |
| 313 | +- `CONTRIBUTING.md` - Links to contribution guidelines |
| 314 | +- `docs/index.md` - Documentation index |
| 315 | +- `docs/wasm.md` - WASM build and usage guide |
| 316 | +- `docs/wasm_configuration.md` - Configuration reference |
| 317 | +- `docs/concepts.md` - Bill lifecycle and state machine |
| 318 | +- `docs/testing.md` - Testing strategy |
| 319 | +- `docs/versioning.md` - Versioning guide |
| 320 | +- `docs/wasm_releasing.md` - Release process |
| 321 | + |
| 322 | +## External Resources |
| 323 | + |
| 324 | +- NPM Package: `@bitcredit/bcr-ebill-wasm` |
| 325 | +- GitHub Organization: BitcreditProtocol |
| 326 | +- Contributing Guidelines: [Google Doc](https://docs.google.com/document/d/18468Jb_PT4Sn1YoiwsEIZmWXUb2opxEQzFyGGnwH5VQ) |
| 327 | + |
| 328 | +## Notes for AI Assistants |
| 329 | + |
| 330 | +1. **WASM is Primary**: Always consider WASM compatibility. Check for `wasm32` target when suggesting async or platform-specific code |
| 331 | +2. **Type Safety**: Leverage Rust's type system and `Validate` trait for correctness |
| 332 | +3. **TypeScript Bindings**: When modifying WASM API, ensure proper TypeScript type generation using `tsify` or `wasm_bindgen` annotations |
| 333 | +4. **Testing**: Add tests at the appropriate layer (unit tests in core/persistence/transport, integration in API) |
| 334 | +5. **Documentation**: Bill lifecycle is complex - refer to `docs/concepts.md` for state machine details |
| 335 | +6. **Dependencies**: Some deps are from BitcreditProtocol private repos requiring GitHub App authentication |
| 336 | +7. **Serialization**: Use `borsh` for internal serialization, `serde_json` for WASM boundaries |
| 337 | +8. **Edition**: Project uses Rust 2024 edition |
0 commit comments