|
| 1 | +# ADR 0018: Coinset parse and pagination submodule decomposition |
| 2 | + |
| 3 | +## Status |
| 4 | + |
| 5 | +Accepted (2026-06-29) |
| 6 | + |
| 7 | +## Context |
| 8 | + |
| 9 | +`coinset/parse.rs` (~440 lines) mixed JSON payload parsing, typed coin-record helpers, |
| 10 | +RPC success checks, pagination field extraction, and generic utilities (`chunk_values`, |
| 11 | +`to_coinset_hex`). `pagination.rs` mixed cursor parsing with async page orchestration. |
| 12 | +Callers imported from a single `parse` module name that no longer matched its contents. |
| 13 | + |
| 14 | +## Decision |
| 15 | + |
| 16 | +### Coinset layout (`greenfloor-engine/src/coinset/`) |
| 17 | + |
| 18 | +| Module | Responsibility | |
| 19 | +| ---------------------- | ---------------------------------------------------------------------------------------------------------- | |
| 20 | +| `parse/mod.rs` | Barrel re-exports for JSON → protocol parsing only | |
| 21 | +| `parse/payload.rs` | `coin_records_from_payload`, `record_from_payload` | |
| 22 | +| `parse/record.rs` | `coin_id_from_record`, `coin_from_record`, `coin_spend_from_solution_payload` | |
| 23 | +| `parse/tests.rs` | Parse unit tests | |
| 24 | +| `rpc_result.rs` | `ensure_coinset_success` (typed SDK responses), `ensure_coinset_rpc_success` (JSON payloads) | |
| 25 | +| `pagination/mod.rs` | Async cursor page orchestration (`fetch_all_coinset_pages`, endpoint wrappers) | |
| 26 | +| `pagination/cursor.rs` | `CoinsetRecordsPagination`, `pagination_from_*`, `ensure_complete_page`, `coin_records_page_from_response` | |
| 27 | +| `pagination/tests.rs` | Pagination unit tests | |
| 28 | +| `json_util.rs` | Coinset JSON scan helpers: `to_coinset_hex`, `u64_from_value` | |
| 29 | +| `batch.rs` | Generic `chunk_values` batching for scan/lineage queries | |
| 30 | + |
| 31 | +**Ownership split:** |
| 32 | + |
| 33 | +- **`rpc_result`** owns Coinset RPC success/failure mapping for typed and JSON responses. |
| 34 | +- **`parse`** owns JSON coin-record and spend decoding only. |
| 35 | +- **`pagination`** owns cursor pagination types, page parsing, and multi-page fetch loops. |
| 36 | +- **`json_util`** is the canonical in-crate `0x`-prefixed hex helper for Coinset IO (`wallet_io`, scan paths). |
| 37 | + |
| 38 | +Unspent typed `CoinRecord` filtering (`!record.spent`) is inlined at call sites in `xch`, |
| 39 | +`coin_select`, and `cats/list` — a one-line filter does not warrant a shared module. |
| 40 | + |
| 41 | +**Public API:** `greenfloor_engine::coinset::*` re-exports are unchanged (`chunk_values`, |
| 42 | +`to_coinset_hex`, `u64_from_value`, `ensure_coinset_rpc_success`, parse fns). |
| 43 | + |
| 44 | +**Behavior note:** `coin_spend_from_solution_payload` uses `hex_to_bytes` (normalize + strip |
| 45 | +non-hex) instead of raw `hex::decode(trim_start_matches("0x"))`; tests document the broader |
| 46 | +acceptance of prefixed/mixed-case hex. |
| 47 | + |
| 48 | +## Consequences |
| 49 | + |
| 50 | +- Import `ensure_coinset_success` from `coinset::rpc_result` (crate-internal), not `parse`. |
| 51 | +- Import pagination helpers from `coinset::pagination`, not `parse`. |
| 52 | +- Prefer `json_util::to_coinset_hex` over local `format!("0x{}", hex::encode(...))` in `coinset/`. |
| 53 | +- Historical references to monolithic `parse.rs` / `pagination.rs` are superseded by this ADR. |
| 54 | + |
| 55 | +## References |
| 56 | + |
| 57 | +- [0007](0007-rust-signer-and-coinset-io.md) — Rust Coinset IO baseline |
| 58 | +- [0017](0017-offer-submodule-decompositions.md) — prior submodule decomposition pattern |
0 commit comments