# rwa-kyc-hook
Token-2022 **Transfer Hook** program for RWA primary issuance on x402. **v2** is multi-issuer SaaS: one program deployment serves many issuers via UUID `issuer_id` in PDA seeds.
## Workspace
| `api` | Account layouts, PDAs, SDK, errors/events |
| `program` | Platform + issuer ops + hook `Execute` |
| `cli` | Operator CLI (`--program-id`, `--issuer-id`, ops/payer keypairs) |
## Build
```bash
cargo test
cargo clippy --workspace --all-targets -- -D warnings
cargo build -p rwa-kyc-hook-cli --release
./build-sbf.sh # Linux — target/deploy/rwa_kyc_hook.so
```
### Publish CLI to crates.io (v2)
Crates.io currently has **`rwa-kyc-hook-api` 0.0.1** (v1, single-tenant). The workspace is **0.2.0** (v2 multi-issuer). Publish in order:
```bash
cargo publish -p rwa-kyc-hook-api # api first (cli depends on it)
cargo publish -p rwa-kyc-hook-cli # installs as `rwa-kyc-hook` binary
```
The on-chain `program` crate is `publish = false` (SBF artifact only).
## Quick start (v2)
```bash
export RWA_KYC_HOOK_PROGRAM_ID=<deployed-program-id>
export RWA_KYC_HOOK_ISSUER_ID=550e8400e29b41d4a716446655440000
export OPS_KEYPAIR=~/.config/solana/ops.json
export PAYER_KEYPAIR=~/.config/solana/id.json # optional
./scripts/initialize.sh devnet
# register issuer via CLI (see DEPLOYMENT_GUIDE)
./scripts/register-mint.sh <mint> both series-a
./scripts/init-hook-metadatas.sh <mint>
./scripts/create-kyc-record.sh global <wallet>
./scripts/update-kyc-verified.sh global <wallet> true
```
See [docs/TECHNICAL_SPEC.md](docs/TECHNICAL_SPEC.md), [docs/DEPLOYMENT_GUIDE.md](docs/DEPLOYMENT_GUIDE.md), [docs/SYNC_RUNBOOK.md](docs/SYNC_RUNBOOK.md).
## Cluster-agnostic design
- PDAs use runtime `program_id` from the entrypoint.
- `declare_id!` in `api` is a Steel placeholder only.
## Integration
- **Portal:** [rwa-issuer-portal](https://github.com/miralandlabs/rwa-issuer-portal) — KYC system of record
- **Ops sync:** [rwa-kyc-sync](https://github.com/miralandlabs/rwa-kyc-sync) — portal feed → CLI → on-chain
- **Seller:** x402-buy-rwa-token — catalog `issuer_id`, `transfer_hook_program`
- **Oracle:** oracle-rwa-transfer — hook program pin
- **Binding:** Postgres `issuers.id` → on-chain `issuer_id`; sync worker → `Update*KycVerified`