npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@openzeppelin/ui-builder-adapter-midnight

v1.8.0

Published

Midnight Adapter for UI Builder

Downloads

225

Readme

Midnight Network Adapter

A browser-based adapter for executing Midnight smart contracts in the OpenZeppelin Contracts UI Builder. This adapter enables users to upload Midnight contract artifacts, interact with contracts through the Lace wallet, and execute zero-knowledge proof transactions entirely in the browser.

Features

  • Pure Client-Side Execution - No backend server required
  • ZIP Upload Workflow - Simple contract artifact loading
  • Zero-Knowledge Proof Coordination - Orchestrates proof generation via external proof server
  • Lace Wallet Integration - Native Midnight wallet support
  • Production Ready - Static deployment identical to EVM/Stellar adapters

Quick Start

1. Upload Contract Artifacts

Export your Midnight contract as a ZIP file containing:

  • Contract definition (.d.ts or .d.cts)
  • Compiled contract module (.cjs or .js)
  • Witness code (witnesses.js)
  • ZK artifacts (.prover, .verifier, .bzkir)
cd your-midnight-contract
compact build
zip -r contract.zip dist/

2. Load in UI Builder

  1. Navigate to Midnight network in the UI Builder
  2. Click "Upload Contract"
  3. Select your contract.zip file
  4. Contract functions will automatically populate

3. Execute Transactions

  1. Connect Lace wallet
  2. Select a contract function
  3. Enter parameters
  4. Click "Execute" - proof generation and signing handled automatically

Runtime-Only Organizer Secret (Organizer-Only Circuits)

Some circuits require an organizer secret key. For security, the adapter treats this as a runtime-only credential:

  • Never requested or stored during artifact upload
  • Collected only at execution time (similar to a relayer API key)
  • Injected into the private state provider in-memory and never persisted

How it works in the UI:

  • The Builder auto-adds a form field of type runtimeSecret for functions that require an organizer key (based on adapter-provided decorations).
  • This field appears in the form like any other field (not in the execution settings panel). The label and helper text are adapter-defined (e.g., "Organizer Secret Key (hex)").
  • Values from runtimeSecret fields are never persisted; they are removed from contract arguments and passed to the adapter at submit time.
  • The adapter seeds a runtime-only overlay of the private state so the secret is available just-in-time for proof generation and is stripped on any persistence operations.

Architecture

This adapter implements a pure browser-based solution with lazy-loaded polyfills:

Browser Memory
├── ZIP Extraction (jszip)
├── ZK Artifacts (EmbeddedZkConfigProvider)
├── Contract Evaluation (dynamic code execution)
├── Browser Polyfills (lazy-loaded when adapter imports)
│   ├── Buffer Polyfill (runtime, via browser-init.ts)
│   └── CommonJS Polyfill (runtime, via browser-init.ts)
└── Transaction Execution (direct SDK integration)

Key Components:

  • EmbeddedZkConfigProvider: In-memory storage for prover/verifier keys
  • Contract Evaluator: Dynamic contract instantiation with shared WASM context
  • Browser Init: Lazy-loaded polyfills (Buffer + CommonJS) only when Midnight is selected
  • Monkey Patches: Minimal SDK patches for browser compatibility (see patches/)

Browser Compatibility Strategy

The adapter uses lazy-loaded runtime polyfills to minimize global namespace pollution:

Runtime Polyfills - Installed when adapter is first imported

  • Buffer polyfill for @dao-xyz/borsh (Midnight SDK serialization)
  • CommonJS globals for dynamic contract evaluation
  • Location: packages/adapter-midnight/src/browser-init.ts
  • Only loads when user selects Midnight ecosystem

Why This Works:

  • Polyfills install before any Midnight SDK code executes
  • No impact on other ecosystems (EVM, Solana, Stellar)
  • Vite's NodeGlobalsPolyfillPlugin provides additional Buffer support during dependency optimization

Exported Applications

When you export an application from the UI Builder, all contract artifacts are automatically bundled into the exported app. This enables:

  • ZK Proof Generation: All proof files included
  • Contract State Queries: TypeScript definitions preserved
  • Self-Contained Deployment: Deploy anywhere without external dependencies

What Gets Exported

The export process uses a lean bundling approach that keeps files small:

Bundled in the Export:

  1. Original ZIP file: Stored at public/midnight/contract.zip (keeps bundle small)
  2. Contract Address: Deployed contract address
  3. Private State ID: Contract's private state identifier

Parsed at Runtime (from ZIP):

  • Contract definition (TypeScript .d.ts interface)
  • Contract module (.cjs for contract interaction)
  • Witness code (witnesses.js for zero-knowledge proofs)
  • Verifier keys (.prover/.verifier for proof verification)
  • ZK artifacts (for browser-based proof generation)

This approach:

  • ✅ Keeps exported files small (no massive expanded artifacts)
  • ✅ Reuses the same ZIP parsing logic as the builder
  • ✅ Maintains a single source of truth for artifact handling
  • ✅ Makes exports future-proof to ZIP format changes

Exported App Structure

exports/your-app/
├── src/
│   ├── midnight/
│   │   └── artifacts.ts          # ← ZIP data + metadata
│   ├── main.tsx                   # ← Auto-loads and parses ZIP on startup
│   ├── App.tsx
│   └── components/
│       └── GeneratedForm.tsx
├── package.json                    # ← Includes all Midnight dependencies
└── vite.config.ts                  # ← Configured for WASM & module deduplication

The exported main.tsx automatically loads artifacts during adapter initialization:

const resolveAdapter = async (nc: NetworkConfig): Promise<ContractAdapter> => {
  const adapter = new MidnightAdapter(nc);
  // Load contract from URL-based ZIP (same parsing logic as builder)
  await adapter.loadContractWithMetadata(midnightArtifactsSource);
  return adapter;
};

The artifacts.ts file contains the ZIP metadata and URL:

export const midnightArtifactsSource = {
  contractAddress: '0x...',
  privateStateId: 'counter',
  contractArtifactsUrl: '/midnight/contract.zip',
};

Testing Exported Apps

Important: When testing exported Midnight apps, you must test them outside the UI Builder monorepo workspace.

# ❌ WRONG - Running in monorepo (patches won't apply)
cd /path/to/ui-builder/exports/my-app
pnpm install  # Patches from adapter are ignored in nested workspaces!
pnpm dev

# ✅ CORRECT - Copy to external directory first
cp -r exports/my-app ~/Desktop/my-app
cd ~/Desktop/my-app
pnpm install  # Now patches will be applied correctly
pnpm dev

Why? pnpm only applies patches from pnpm.patchedDependencies when installing published packages. In a monorepo, patches must be defined at the workspace root. The adapter's bundled patches are only activated when the adapter is installed from npm (not via workspace:*).

What happens if you test in the monorepo?

  • Midnight SDK patches won't be applied
  • You may see errors like "No private state found" or module resolution issues
  • Transaction execution will fail unexpectedly

For CI/CD or production deployments: This is not an issue. Published apps install the adapter from npm, which automatically applies all patches.

  1. Export from Builder: Use the "Export" button after loading a contract
  2. Install Dependencies: cd exports/your-app && npm install
  3. Run Locally: npm run dev
  4. Execute Transaction: Connect Lace wallet and submit a transaction
  5. Verify Offline: Artifacts load instantly without network requests

For more on the export architecture, see docs/ADAPTER_ARCHITECTURE.md § 11.6.

Documentation

This adapter includes comprehensive documentation covering all aspects of the Midnight integration:

📚 Core Documentation

  • TRANSACTION_IMPLEMENTATION.md - Complete implementation guide covering architecture, data flow, WASM context isolation, Buffer polyfills, ZK artifact distribution, SDK patches, and testing guidelines.

  • TYPE-COVERAGE.md - Comprehensive type system reference with full coverage analysis of all Midnight types, UI component mappings, validation status against production contracts, and edge case handling.

  • BROWSER_COMPATIBILITY.md - Browser compatibility strategy, polyfill implementation details, global namespace management, and debugging tips for browser-specific issues.

  • CHANGELOG.md - Version history, breaking changes, new features, and migration guides for adapter updates.

🔧 Component Documentation

  • Wallet Integration - Lace wallet connection, state management, and provider configuration.

📖 Quick Reference

| Topic | Document | Key Sections | | ---------------- | ----------------------------- | ---------------------------------- | | Getting Started | This README | Quick Start, Architecture, Export | | Transaction Flow | TRANSACTION_IMPLEMENTATION.md | §4-7: Providers, Execution, Proofs | | Type Mapping | TYPE-COVERAGE.md | Type Matrix, UI Components | | Browser Setup | BROWSER_COMPATIBILITY.md | Polyfills, CommonJS Support | | Wallet Setup | src/wallet/README.md | Connection, State, Errors |

Requirements

  • Browser: Modern browser with WebAssembly support
  • Wallet: Lace wallet browser extension
  • Contract: Midnight contract compiled with Compact compiler v0.9.0+

Note: This adapter automatically installs browser polyfills (Buffer, CommonJS) when loaded. No additional setup required.

Known Limitations

  1. Page Reload: Artifacts cleared on refresh (re-upload ZIP file)
  2. Memory Usage: ~500KB-1MB per circuit stored in browser
  3. Single Contract: One contract's artifacts at a time per session
  4. Proof Server: Requires external proof generation service

Dependencies

Core:

  • @midnight-ntwrk/compact-runtime - Contract runtime
  • @midnight-ntwrk/midnight-js-contracts - Contract utilities
  • @midnight-ntwrk/midnight-js-http-client-proof-provider - Proof server client
  • @midnight-ntwrk/midnight-js-level-private-state-provider - Private state storage
  • jszip - ZIP file extraction

Development

# Install dependencies
pnpm install

# Run development server
pnpm dev

# Build for production
pnpm build

File Structure

src/
├── index.ts                          # Entry point + polyfill loader
├── browser-init.ts                   # Runtime polyfills (Buffer + CommonJS)
├── adapter.ts                        # Main adapter implementation
├── networks/
│   └── testnet.ts                   # Network configurations
├── transaction/
│   ├── eoa.ts                       # Transaction execution strategy
│   ├── providers.ts                 # SDK provider configuration
│   ├── embedded-zk-config-provider.ts # In-memory ZK artifact storage
│   ├── contract-evaluator.ts       # Dynamic contract loading
│   └── witness-evaluator.ts        # Witness code evaluation
└── utils/
    ├── artifacts.ts                 # Artifact validation & registration
    ├── zip-extractor.ts             # ZIP parsing logic
    └── schema-parser.ts             # Contract interface parsing

Troubleshooting

Transaction Fails with Version Error

Cause: Prover keys compiled with incompatible Compact compiler version.

Solution: Recompile contract with current Compact compiler:

cd your-contract
pnpm install @midnight-ntwrk/compact-cli@latest
compact build

"Module not found" Error

Cause: Missing contract artifacts in ZIP file.

Solution: Ensure ZIP contains dist/ directory with all compiled outputs.

Proof Generation Timeout

Cause: Network issues or proof server overload.

Solution:

  • Check network connection
  • Verify proof server URL in wallet config
  • Try again after a few minutes

Contributing

When modifying this adapter:

  1. Test thoroughly - Midnight integration is complex
  2. Update docs - Keep TRANSACTION_IMPLEMENTATION.md current
  3. Maintain patches - Document any SDK monkey-patches
  4. Consider upstream - Submit fixes to Midnight SDK when possible

Resources

License

MIT