ZReal is a privacy-oriented, Zcash/ZSA-native real estate tokenization system.
The intended architecture is:
- Django: backend, admin, database, auth, property/document/tokenization logic, ZSA integration boundary, tests
- Next.js: product frontend for issuers and investors
Implemented today:
- user signup/login through django-allauth
- role selection: investor or issuer
- staff-only local setup/status checklist
- issuer-facing ZSA configuration validation
- issuer dashboards sourced from application records
- issuer property create/edit flows
- address-first property data autofill with reviewable provider provenance
- document upload and text extraction for issuer-owned properties
- tokenization operation detail/history pages
- investor browse page that shows only tokenized or active properties
- property map using stored latitude/longitude; public/investor views show tokenized or active properties, issuers also see their own drafts
- auditable ZSA tokenization attempts
- safe document-to-tokenization metadata using document hashes, document types, timestamps, and selected structured fields
- Stripe checkout integration when Stripe keys are configured
- JSON endpoints for the product frontend
- a Next.js product workspace in
frontend/
ZSA issuance only runs when you configure an external ZSA-capable tool. If required configuration is missing or invalid, tokenization is blocked before operation creation. If the configured tool runs and fails, ZReal records a failed operation with a safe error message.
py -3 -m pip install -r requirements.txtOptional but recommended:
copy .env.example .envLocal development defaults to SQLite if DATABASE_URL is not set.
Minimum local config:
SECRET_KEY=change-me
DEBUG=1
ALLOWED_HOSTS=localhost,127.0.0.1For real Zcash/ZSA issuance, configure:
ZCASH_NETWORK=testnet
ZCASH_RPC_URL=http://rpcuser:rpcpassword@127.0.0.1:18232
ZSA_ISSUANCE_BACKEND=zcash_tx_tool
ZCASH_TX_TOOL_PATH=C:\path\to\zcash_tx_tool.exe
ZCASH_ZSA_ISSUE_COMMAND={tool} create-zsa-issuance --from {issuer_zaddr} --asset-symbol {asset_symbol} --total-shares {total_shares} --network {network}
ZCASH_ZSA_STATUS_COMMAND={tool} status --operation-id {operation_id} --network {network}The issue/status commands must print a JSON object. Issuance output must include at least one of:
{
"status": "pending|broadcast|confirmed",
"operation_id": "...",
"txid": "...",
"asset_id": "..."
}Safe tokenization metadata is stored with the operation and passed to the command in ZREAL_ZSA_METADATA_JSON. The command template may also reference {metadata_json} if your tool expects metadata as an argument. ZReal includes document hashes and selected structured fields, not full legal document text.
Stripe checkout is optional. Configure it only if you want platform billing for issuer SaaS, legal review, or administrative service fees. Stripe is not used for investor property purchases, token settlement, holder ownership, or distributions:
STRIPE_SECRET_KEY=sk_test_...
STRIPE_ISSUER_PRICE_ID=price_...
DJSTRIPE_WEBHOOK_SECRET=whsec_...
REQUIRE_ACTIVE_SUBSCRIPTION_FOR_ZSA=0Property data enrichment defaults to fixture mode for local development and CI:
PROPERTY_DATA_PROVIDER=mock
PROPERTY_DATA_ENABLE_LIVE_CALLS=0
PROPERTY_DATA_API_KEY=
PROPERTY_DATA_REGRID_API_KEY=
PROPERTY_DATA_OPENCAGE_API_KEY=
PROPERTY_DATA_GOOGLE_API_KEY=
REGRID_API_KEY=
OPENCAGE_API_KEY=
GOOGLE_GEOCODING_API_KEY=Supported provider modes are mock, fixture, census, regrid, opencage, and google. mock/fixture return local fixture data for tests and development checks. census can resolve live addresses only when PROPERTY_DATA_ENABLE_LIVE_CALLS=1. Regrid, OpenCage, and Google are keyed provider interfaces until live integration and licensing are approved; the shorter REGRID_API_KEY, OPENCAGE_API_KEY, and GOOGLE_GEOCODING_API_KEY aliases are also accepted.
During property creation, an issuer can resolve an address first and submit the selected candidate with the new property. ZReal stores that candidate as unconfirmed enrichment provenance, not as trusted readiness evidence. The issuer must review and confirm autofilled data before it can stop blocking tokenization readiness.
Backend:
py -3 manage.py migrate
py -3 manage.py runserver 127.0.0.1:8000Open:
http://127.0.0.1:8000/
Frontend:
cd frontend
npm install
npm run devOpen:
http://127.0.0.1:3000/
Backend:
py -3 manage.py check
py -3 manage.py testFrontend:
cd frontend
npm run typecheck
npm run buildLocal frontend development uses Django session authentication.
- Start Django at
http://127.0.0.1:8000. - Start Next.js at
http://127.0.0.1:3000. - Sign in through the styled Django allauth page at
http://127.0.0.1:8000/accounts/login/. - Signup, logout, password reset, and email confirmation are still handled by allauth, but use ZReal dark auth templates.
- Redirects from the frontend can use
?next=...; after login, allauth respects thatnextvalue. - Open
http://127.0.0.1:3000/accountafter login to confirm the Next.js frontend can read the Django session. - The frontend API client calls Django with
credentials: "include". - Unsafe frontend requests call
GET /api/csrf/first and sendX-CSRFToken.
The backend permits local frontend origins through CORS_ALLOWED_ORIGINS and CSRF_TRUSTED_ORIGINS.
Production must configure:
- real
SECRET_KEY - real
ALLOWED_HOSTS - real frontend origin in
CORS_ALLOWED_ORIGINS - real frontend origin in
CSRF_TRUSTED_ORIGINS - secure cookies/HTTPS settings
Frontend-facing API endpoints are mounted under /api/:
GET /api/health/GET /api/csrf/GET /api/me/GET/PATCH /api/role/GET /api/dashboard/issuer/GET /api/dashboard/investor/GET /api/setup/status/staff onlyGET /api/properties/GET /api/properties/browse/POST /api/properties/resolve-address/POST /api/properties/new/GET /api/properties/<id>/PATCH/PUT /api/properties/<id>/edit/POST /api/properties/<id>/enrich/GET /api/properties/<id>/enrichment/POST /api/properties/<id>/confirm-enrichment/GET /api/properties/<id>/documents/POST /api/properties/<id>/documents/upload/POST /api/properties/<id>/reviews/request/GET /api/reviews/staff onlyPOST /api/reviews/<id>/decision/staff onlyGET /api/zsa/config/POST /api/properties/<id>/tokenize/GET /api/tokenization/operations/<id>/POST /api/tokenization/operations/<id>/refresh/
The product endpoints return persisted application data. Empty states are represented as empty arrays or null values.
Property readiness responses include enrichment evidence and the current tokenization review state. A staff approval is valid only for the exact fingerprinted property fields, confirmed enrichment, and completed document hashes that were submitted.
- User signs in.
- User chooses the issuer role.
- Issuer creates a property.
- Issuer uploads legal/property documents.
- ZReal stores the document and its SHA-256 hash, then extracts local structured metadata.
- Issuer submits the completed property package for tokenization review.
- Staff approves, rejects, or requests changes. The decision and package fingerprint are audited.
- Issuer checks ZSA readiness on the dashboard or staff setup/configuration views.
- If review approval or configuration is missing, ZReal blocks issuance before operation creation.
- If approval and configuration are current, issuer enters a shielded issuer address and submits
Issue ZSA. - ZReal creates a
TokenizationOperationand an append-only audit event. - ZReal attaches safe metadata: property ID, asset symbol, total shares, document types, document SHA-256 hashes, timestamps, and selected non-text extracted fields.
- ZReal calls the configured ZSA issuance command.
- ZReal stores real returned
operation_id,txid,asset_id, status, and errors. - Pending operations can be refreshed from the dashboard or operation detail page.
No private keys should be stored in ZReal. The external ZSA-capable tool is responsible for signing and broadcasting.
- Install backend dependencies:
py -3 -m pip install -r requirements.txt. - Run migrations:
py -3 manage.py migrate. - Start Django:
py -3 manage.py runserver 127.0.0.1:8000. - Install frontend dependencies:
cd frontend && npm install. - Start Next.js:
npm run dev. - Open
http://127.0.0.1:8000/accounts/signup/and confirm it uses the ZReal dark auth UI. - Create an account with your own email and password.
- Sign out and sign back in at
http://127.0.0.1:8000/accounts/login/?next=/profile/role/to confirm thenextredirect is preserved. - Open
http://127.0.0.1:3000/account. - Confirm the frontend shows the authenticated profile.
- Choose the issuer role in the frontend.
- Open
http://127.0.0.1:3000/properties/new. - Enter a property address, run
Autofill property details, review the normalized address/source/confidence, then create the draft. - Open the created property detail page.
- Edit the property from the frontend, run saved-property enrichment if needed, confirm autofill, and confirm the saved values reload.
- Upload a real legal/property document from the property detail page.
- Confirm the frontend shows document hash, processing status, and safe metadata only.
- Request tokenization review from the property detail page.
- Sign in as staff, open
http://127.0.0.1:3000/reviews, and approve or return the package with a real reason. - Confirm the issuer property page shows the persisted decision and audit trail.
- Inspect ZSA readiness on the property detail page.
- Attempt tokenization with missing ZSA config and confirm the clear blocked/error state.
- Configure the ZSA environment variables listed above if you have issuance tooling.
- Submit tokenization with a real issuer shielded address.
- Open the tokenization operation detail page.
- Refresh operation status and confirm the page shows operation IDs, txids, asset IDs, timestamps, and safe errors.
- Create or log into an investor account and open
http://127.0.0.1:3000/properties. - Confirm no draft properties are shown. If no real tokenized properties exist, the page should say:
No tokenized properties are available yet.
For the staff-only local setup checklist, create or use a staff/superuser account and open:
http://127.0.0.1:8000/setup/status/
- Django app boot and routing
- SQLite local development
- auth and role selection
- issuer property management
- provider-agnostic property data enrichment foundation with fixture mode
- ownership-protected document upload
- PDF/image text extraction path
- local setup/status checklist
- ZSA configuration validation endpoint
- dashboard metrics from persisted records
- frontend API layer
- Next.js product workspace
- investor tokenized-property browsing
- property map
- tokenization audit model
- fingerprinted staff tokenization review workflow
- append-only critical-action audit events
- tokenization operation detail/status refresh pages
- external ZSA tool integration boundary
- tests for document upload, tokenization success/failure/status refresh, permissions, investor holdings, and Stripe missing configuration
- a real native ZSA backend/tool must be supplied and configured
- Zcash-native investor purchase reservation and payment verification
- production holder ledger backed by verified Zcash-native settlement
- Zcash-compatible rental/dividend distribution model
- live parcel/geocoder provider integrations beyond fixture mode
- production hardening for KYC/AML and securities compliance
- viewing keys are not currently stored; add encrypted custody/read-only access if that feature is needed
See COMPLETION_PLAN.md for the ordered plan to complete ZReal as a Zcash/ZSA-native product.
- Regrid live parcel API integration
- ATTOM/ICE/Cotality enrichment provider
- official county/state ArcGIS connector layer
- PostGIS parcel boundary storage
- flood/elevation/climate risk enrichment
- zoning/land-use module
- MLS/RESO listing overlay
- provider confidence scoring dashboard
- provider license/compliance registry
- background enrichment jobs
- map-based parcel confirmation