Laminar Field Manual

The complete operational guide for treasurers processing batch disbursements using Laminar. This manual covers the core workflow, data formats, validation rules, and troubleshooting procedures.

Overview

Laminar is the operational command console for the Zcash economy. It is a local-first, air-gapped terminal for high-volume Zcash batch operations.

Laminar separates Transaction Construction (the Brain) from Key Storage (the Muscle). Treasurers construct batches on a desktop application and hand off signing to an offline mobile wallet device without private keys ever touching an internet-connected machine.

Key Properties

Non-Custodial

Never accesses, stores, or transmits private keys or seed phrases

Stateless

No server-side state. All data persists locally in encrypted IndexedDB

Air-Gapped

Transaction construction requires no network access. QR handoff bridges the gap

Deterministic

Same input CSV always produces identical output. No randomness in construction

Auditable

JSON receipts provide machine-readable proof of constructed transactions

Open Source

MIT / Apache 2.0 dual-license. Full source available for audit and verification

Core Concepts

Understanding the architecture and philosophy behind Laminar's design.

The Spreadsheet Gap

Zcash organizations currently manage treasury disbursements using a fragile, manual workflow: payroll data in spreadsheets, manual copy-paste of each address into a mobile wallet, transactions signed one-by-one, and no standardized audit trail.

Laminar closes this gap by accepting batch input and generating scannable QR codes that mobile wallets can process, reducing a 2-4 hour process to under 5 minutes for 50+ recipients.

Brain vs. Muscle

Brain (Laminar Terminal)

Handles computation, validation, ZIP-321 construction, and QR generation. Runs on internet-connected desktop. Has no signing authority.

Muscle (Mobile Wallet)

Stores private keys, signs transactions, broadcasts to network. Zashi or YWallet. Keys never leave the device.

Payment Intents

Laminar constructs Payment Intents, not transactions. A Payment Intent contains all information needed to create a transaction (recipients, amounts, memos) but has no signing authority. The mobile wallet receives the intent and executes it using locally-stored keys.

Critical Invariants

Architectural constraints that are enforced at all times. Violation of any invariant is a critical defect.

Non-Negotiable

These invariants are architectural constraints enforced at all times. Violation of any invariant is a critical defect.

  • INV-01 Laminar NEVER stores, generates, or requests spending keys or seed phrases.
  • INV-02 Laminar NEVER signs transactions. It constructs Payment Intents only.
  • INV-03 Laminar NEVER broadcasts transactions. The mobile wallet handles network communication.
  • INV-04 ALL monetary arithmetic uses integer zatoshis (bigint). Floating-point is PROHIBITED.
  • INV-05 All cross-boundary data MUST be validated against versioned schemas.
  • INV-06 Sensitive IndexedDB fields (memos, labels) MUST be encrypted with session key.
  • INV-07 Memo encoding: UTF-8 bytes to standard base64. Maximum 512 bytes.
  • INV-08 Handoff results MUST conform to HandoffResult schema.
  • INV-09 No telemetry. No analytics. No external network requests.
  • INV-10 If ANY row fails validation, the ENTIRE batch is rejected. No partial processing.

Workflow

The standard batch disbursement workflow consists of seven steps, from CSV preparation to receipt generation.

  1. Prepare CSV

    Create a CSV file with recipient addresses, amounts, and optional memos. Use UTF-8 encoding. See CSV Format for schema details.

  2. Import Batch

    Drag the CSV file into Laminar Terminal or use the file picker. Select the network (Mainnet or Testnet) before import.

  3. Review & Validate

    Laminar validates every row: address format, network match, amount bounds, memo length. Review the batch summary showing total ZEC and recipient count. If any row fails, the entire batch is rejected.

  4. Generate QR

    Click "Proceed" to construct ZIP-321 payment requests. Laminar generates static QR (small batches) or animated UR sequence (large batches) automatically.

  5. Scan with Wallet

    Open Zashi or YWallet on your mobile device. Use the scan function to capture the QR code. For animated sequences, hold steady until all frames are captured.

  6. Sign & Broadcast

    Review the transaction details on your mobile wallet. Confirm to sign with your locally-stored keys. The wallet broadcasts to the Zcash network.

  7. Save Receipt

    Return to Laminar and click "Generate Receipt". Save the JSON receipt bundle for your records. This provides an audit trail of the constructed batch.

CSV Format

Laminar accepts CSV files with flexible column naming. The first row must contain headers. Files must use UTF-8 encoding.

Column Specification

Header Aliases Required Description
address recipient, to Yes Zcash address (Unified, Sapling, or Transparent)
amount value, zec Yes* Amount in ZEC (decimal notation)
amount_zatoshis zatoshis, zats Yes* Amount in zatoshis (integer)
memo message, note No Encrypted memo (max 512 bytes UTF-8)
label name, recipient_name No Display label (not sent on-chain)

*Either amount OR amount_zatoshis is required. If both are present, amount_zatoshis takes precedence.

Example CSV

address,amount,memo,label
u1abc123...,10.5,"January payment",Alice
u1def456...,25.0,"January payment",Bob
u1ghi789...,15.75,,Carol

Encoding Requirements

  • File encoding: UTF-8 (with or without BOM)
  • Line endings: LF or CRLF
  • Delimiter: Comma (,)
  • Quote character: Double quote (")
  • Escape: Doubled double quotes ("")
Formula Injection Protection

CSV fields beginning with =, +, -, @, \t, or \r are detected and rejected to prevent formula injection attacks.

JSON Format

For programmatic batch generation, Laminar accepts JSON files conforming to the Laminar Batch Schema.

Input Schema

{
  "version": "1.0",
  "network": "mainnet",
  "recipients": [
    {
      "address": "u1...",
      "amount_zatoshis": 100000000,
      "memo": "January payment",
      "label": "Alice"
    }
  ]
}

Receipt Output Schema

{
  "laminar_version": "1.0.0",
  "timestamp": "2025-01-28T12:00:00Z",
  "batch_id": "a1b2c3d4",
  "network": "mainnet",
  "total_zatoshis": 5000000000,
  "total_zec": "50.0",
  "recipient_count": 25,
  "zip321_payload_hash": "sha256:...",
  "segments": 1
}

Validation Rules

All data is validated before batch construction. If any row fails, the entire batch is rejected.

Address Validation

  • Format: Valid Zcash encoding (Bech32m for Unified, Bech32 for Sapling, Base58Check for Transparent)
  • Network: Must match configured network. Cross-network rejected.
  • Types: Unified, Sapling, and Transparent addresses accepted

Amount Validation

  • Minimum: 1 zatoshi (0.00000001 ZEC)
  • Maximum: 21,000,000 ZEC (total supply cap)
  • Dust: Warning below 10,000 zats (0.0001 ZEC)
  • Precision: Up to 8 decimal places

Memo Validation

  • Maximum: 512 bytes UTF-8 encoded
  • Encoding: Valid UTF-8 required
  • Empty: Allowed

Batch Validation

  • Max recipients: 500 per batch
  • Overflow: Sum must not exceed u64 max
  • Duplicates: Warning only (may be intentional)

QR Generation

Laminar automatically selects between static QR and animated UR sequences based on payload size.

Static QR (ZIP-321)

For payloads under 2,510 bytes (with safety margin), Laminar generates a single static QR code containing a ZIP-321 payment request URI.

Animated UR Sequences

For larger payloads, Laminar uses Uniform Resources (UR) encoding to create animated QR sequences that transmit data across multiple frames.

ZIP-321 URI Format

zcash:<address>?amount=<zec>&memo=<base64>
    &address.1=<addr>&amount.1=<zec>&memo.1=<base64>

UR Animation Parameters

150

Fragment Size

Bytes per frame (100-200 range)

10 FPS

Frame Rate

100ms per frame display

bc-ur

Encoding

Blockchain Commons UR standard

Scanning Tips

Hold your phone steady during animated QR scanning. Ensure adequate lighting and avoid glare on the screen. The progress indicator shows capture status.

Payload Limits

Understanding size constraints for each handoff mode.

Size Limits by Mode

2,510

Static QR

Bytes effective (2,953 raw, 15% margin)

29 KB

Animated UR

Effective limit (32 KB raw, 10% margin)

7.2 KB

Deep Link

Effective limit (8 KB raw, 10% margin)

Recipient Capacity

Mode Typical Capacity Notes
Static QR (ZIP-321) 8-12 recipients Depends on memo length
Animated UR 50+ recipients ~15-20 frames at 100ms
Auto Batch Split Unlimited Sequential segments

Wallet Compatibility

Tested wallet versions and supported features. Results tracked by version.

Wallet Version Static QR Animated UR Deep Link Notes
Zashi iOS 1.2+ Yes Yes Yes Primary target
Zashi Android 1.2+ Yes Yes Yes Primary target
YWallet iOS 1.5+ Yes No Yes Use batch splitting
YWallet Android 1.5+ Yes No Yes Use batch splitting

Error Codes

All errors use standardized codes. No string literals in error handling.

Code Name Description
1001 INVALID_ADDRESS Address does not match any valid Zcash encoding
1002 INVALID_AMOUNT Amount format is invalid or cannot be parsed
1003 AMOUNT_OUT_OF_RANGE Amount is zero, negative, or exceeds maximum
1004 MEMO_TOO_LONG Memo exceeds 512 bytes when UTF-8 encoded
1008 CSV_PARSE_ERROR CSV file is malformed or uses unsupported encoding
1009 CSV_FORMULA_INJECTION Field begins with formula character (=, +, -, @)
1010 NETWORK_MISMATCH Address network does not match configured network
1012 MISSING_REQUIRED_COLUMN Required column (address or amount) not found
1013 BATCH_TOTAL_OVERFLOW Sum of all amounts exceeds u64 maximum
3001 DB_UNAVAILABLE IndexedDB not available or access denied
3003 ENCRYPTION_FAILED Failed to encrypt data for storage
5003 PAYLOAD_TOO_LARGE Payload exceeds maximum size for selected mode
5008 UR_ENCODING_FAILED Failed to encode payload as Uniform Resource
9999 UNKNOWN Unknown or unclassified error

Constants Reference

Critical constants used throughout the system. Reference implementations must use exact values.

Monetary

ZATOSHI_PER_ZEC = 100,000,000
ZATOSHI_MIN     = 1
ZATOSHI_MAX     = 2.1e15
DUST_THRESHOLD  = 10,000

Payload Limits

QR_STATIC    = 2510
QR_ANIMATED  = 29000
DEEPLINK     = 7200

Encoding

MEMO_MAX       = 512
MAX_RECIPIENTS = 500
UR_FRAGMENT    = 150
UR_FRAME_MS    = 100

Glossary

Key terms and definitions used throughout Laminar documentation.

Term Definition
Air Gap Physical or logical separation between systems to prevent data transfer except through controlled channels (QR codes).
Handoff The process of transferring a Payment Intent from Laminar to a mobile wallet via QR code.
Iron Core Codename for Laminar's foundational Rust library containing all business logic.
Operator The person using Laminar to construct batch transactions (treasurer, finance admin).
Payment Intent A constructed but unsigned transaction request. Contains all information needed to sign but no signing authority.
Recipient A single entry in a batch: address, amount, and optional memo.
Tactical Spike Phase 1 of Laminar development, focused on proving the core workflow with minimal features.
Transaction Intent See Payment Intent. Protocol-native terminology.
UR Uniform Resources. Encoding standard for transmitting data via animated QR code sequences.
Vault Local encrypted storage for drafts and address book. Not custody.
Zatoshi The smallest unit of ZEC. 1 ZEC = 100,000,000 zatoshis.
ZIP-321 Zcash Improvement Proposal defining the standard format for payment request URIs.