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

simplex_example

v0.1.0

Published

WebAssembly bindings for the SMPLX basic OLIV example builders.

Readme

Basic Simplex Example

This is an example project to get started with Simplex. The project assumes that the framework has already been successfully installed via simplexup.

Overview

The repository structure is the following:

root
├── simf — Simplicity smart contracts source directory
├── src — The project's Rust code (witness and transaction builders)
│   └── artifacts — Simplicity artifacts generated by Simplex (gitignored)
├── tests — Simplex tests directory
├── Cargo.toml — The project's Rust configuration
└── Simplex.toml — The project's Simplex configuration

Build

In order to see Simplex in action, first run the build command to generate Simplicity artifacts:

simplex build

You will see that Simplex has generated a new artifacts directory in the src directory. Think of these artifacts as "rust typization" helpers for individual simplicity smart contracts in the project.

Please note that this new module gets declared in the lib.rs file.

Test

Once the artifacts are generated, let's run Simplex test "basic_test" inside basic_test.rs:

simplex test basic_test --nocapture

You will see the test passing.

Under the hood, Simplex spins up a local Electrs + Elements regtest, establishes the connection, prefunds the signer specified in the simplex.toml, and runs the test marked via macros #[simplex::test].

Check out confidential_test.rs to learn how to issue and spend confidential UTXOs!

Oracle Asset Release / Reissuance Covenant

oracle_asset_release.simf is a small oracle-authorized mint covenant. It is not a release of an already-issued asset. The covenant holds the reissuance token, and a valid mint transaction spends that covenant UTXO and performs a Liquid reissuance.

The oracle payload is:

sha256(
  domain |
  asset_id |
  asset_amount |
  recipient_script_hash |
  eth_txid |
  ticket_txid |
  ticket_vout
)

The contract checks:

  • at least 3 of the configured 5 oracle signatures verify against that payload
  • the covenant/reissuance-token input is input 0
  • the signed ticket UTXO is input 1
  • the transaction has exactly 2 inputs
  • input 1 prevout equals ticket_txid:ticket_vout
  • the input 0 reissuance mints the signed asset_id
  • the input 0 reissuance amount equals signed asset_amount
  • output 0 sends signed asset_id and signed asset_amount to signed recipient_script_hash
  • output 1 returns the reissuance token to the same covenant script

Local Regtest Flow

Run the working end-to-end test:

simplex test oracle_asset_release_test --nocapture

The test does two transactions:

  1. Initial issuance transaction:

    • issues asset_id amount 1
    • issues reissuance token amount 1
    • sends the issued asset to the signer wallet
    • sends the reissuance token to the covenant script as a confidential output
    • creates a small Liquid policy-asset ticket UTXO for fees/replay binding
  2. Mint/reissuance transaction:

    • spends the covenant-held reissuance token as input 0
    • spends the signed ticket UTXO as input 1
    • reissues the oracle-signed asset_amount
    • sends the minted asset to the signed recipient
    • returns the reissuance token to the covenant

External Oracle Testnet Address

The external oracle pubkeys are defined in src/oracle_asset_release.rs.

Generate the Liquid testnet covenant address using the hardcoded protocol covenant SLIP77 master blinding key:

cargo run --bin oracle_asset_release_address

The hardcoded protocol covenant SLIP77 master blinding key is:

7b6d26da3eaa45718eb5e4af4c7cc29b8f9d78ddf43c59b3355472ce8fd24d95

For the current oracle pubkeys and contract script, the generated testnet deposit address is:

tlq1pqfpqlc2xzs09tfpwxx4mvd3a63kcc5hxyzyjf9qvuzlxx5euj6a9vxe34zwjzfrush26qj82w5kumszfx8wuutq4jq2n49kjdd7ucn8axyxfz0h0px7j

The derived covenant blinding pubkey is:

02420fe146141e55a42e31abb6363dd46d8c52e6208924940ce0be63533c96ba56

The address generator still accepts explicit overrides for comparison or experiments:

cargo run --bin oracle_asset_release_address -- \
  --slip77-master-blinding-key <other_slip77_master_blinding_key_hex>
cargo run --bin oracle_asset_release_address -- \
  --blinding-pubkey <compressed_blinding_pubkey_hex>

You can also run the Simplex smoke test:

simplex test --target oracle_asset_release_external_oracles_test \
  external_oracle_testnet_deposit_address_is_derivable \
  --nocapture

Blinding Key Requirement

Keep the reissuance-token covenant UTXO confidential for this SDK path.

Liquid reissuance needs issuance_blinding_nonce. The current Simplex SDK derives that value from the confidential input secrets:

partial_input.secrets.asset_bf

An explicit reissuance-token UTXO has no secrets, so FinalTransaction::add_program_issuance_input(...) cannot populate the nonce and will fail with:

Reissuance input must be confidential

That is transaction-building data required for this SDK reissuance path. It is not a covenant security check and should not be removed.

The protocol covenant SLIP77 master blinding key must be available to whoever builds the mint transaction, because that builder must derive the covenant script's blinding private key, unblind the covenant-held reissuance-token UTXO, and create the reissuance input. For a ct(slip77(...),...) wallet, the slip77(...) value is the master blinding key, not a compressed public key.

The #blinded=... fragment in a Blockstream Explorer URL is not the deposit address blinding public key. It is output unblinding data for explorer display, grouped as:

amount,asset_id,amount_blinder,asset_blinder

Those values can prove or reveal an output's amount and asset to a third party. They are not enough to create the confidential covenant address, and they are not the builder's blinding private key.

Which Keys Are Used

There are three separate key roles:

  • Issuer key: funds/signs the initial issuance transaction. This key is not needed by the covenant and is not needed by oracles. After the reissuance token is locked in the covenant, mint authority is controlled by the covenant plus oracle signatures.
  • Protocol covenant SLIP77 master blinding key: derives the covenant script's blinding key. The mint transaction builder needs this private key material to unblind the covenant-held reissuance-token UTXO and derive the reissuance nonce required by the SDK.
  • Oracle keys: sign only the oracle payload. They do not sign the Liquid transaction and they do not need the issuer key or blinding key.

NPM WebAssembly Package

The browser bindings for the OLIV transaction builders are published from this example as the npm package simplex_example. Consumers should depend on the npm package instead of a local ../smplx/examples/basic/pkg path.

From the repository root, build the package locally:

rustup target add wasm32-unknown-unknown
cargo install wasm-pack
brew install llvm # macOS only, if clang cannot target wasm32
CC_wasm32_unknown_unknown=/opt/homebrew/opt/llvm/bin/clang ./scripts/build-basic-wasm-package

On Linux CI the workflow installs clang, lld, and wasm-pack, then runs the same script with CC_wasm32_unknown_unknown=clang.

Inspect the package before publishing:

npm pack --dry-run ./examples/basic/pkg

Publish manually after logging in to npm:

npm publish ./examples/basic/pkg --access public --provenance

GitHub Actions publishes from .github/workflows/npm-basic-wasm.yml on version tags, or from workflow_dispatch when publish is set to true. Configure npm trusted publishing for the package, or add an npm automation token as the repository secret NPM_TOKEN.

Testnet End-to-End Flow

  1. Generate the covenant deposit address.

    cargo run --bin oracle_asset_release_address

    Capture:

    protocol_covenant_slip77_master_blinding_key
    deposit_address
    blinding_pubkey
    script_pubkey
    script_hash
  2. Create the initial issuance transaction.

    This transaction creates the asset and the reissuance token. The reissuance token must be sent directly to the covenant address in this same transaction. After this confirms, the issuer no longer holds the reissuance token; the covenant output does.

    Match the regtest shape:

    output 0: issued asset, amount 1, issuer-controlled address
    output 1: Liquid policy asset ticket UTXO, builder-controlled address
    output 2: reissuance token, amount 1, confidential covenant deposit_address

    If your wallet reorders outputs, use the actual vouts from the confirmed transaction. The covenant token outpoint is the output that holds reissuance_token_id amount 1. The ticket outpoint is the Liquid policy asset output that will be spent as input 1 in the mint transaction.

    Capture from the issuance builder or wallet:

    issuance_txid
    asset_id
    reissuance_token_id
    asset_entropy
    covenant_token_outpoint = issuance_txid:<vout holding reissuance_token_id>
    ticket_outpoint = issuance_txid:<vout holding the Liquid policy asset ticket>

    In the regtest example, these are printed by oracle_asset_release_test.rs as asset_id, reissuance_token_id, asset_entropy, and issuance txid.

  3. Select the ticket UTXO.

    Use the ticket UTXO created in step 2. It is included in the mint transaction as input 1. It pays fees and prevents oracle-signature replay.

    Capture:

    ticket_txid
    ticket_vout
  4. Build the oracle payload.

    Inputs:

    domain = 0
    asset_id
    asset_amount
    recipient_script_hash = sha256(recipient_script_pubkey)
    eth_txid
    ticket_txid
    ticket_vout

    Payload:

    sha256(domain | asset_id | asset_amount | recipient_script_hash | eth_txid | ticket_txid | ticket_vout)
  5. Collect oracle signatures.

    Any 3 of the 5 configured oracle private keys sign the payload hash. The oracles do not sign the Liquid transaction. They only sign the payload.

  6. Build the mint/reissuance transaction.

    The builder uses the hardcoded protocol_covenant_slip77_master_blinding_key to derive the covenant script's blinding private key and unblind the covenant token output before building this transaction.

    Transaction shape:

    input 0: covenant_token_outpoint
             spends the confidential UTXO holding reissuance_token_id amount 1
             carries the Liquid reissuance fields for asset_entropy and asset_amount
    input 1: ticket_txid:ticket_vout
             spends the signed ticket UTXO
    output 0: asset_id, asset_amount, recipient_script_pubkey
    output 1: reissuance_token_id, 1, covenant script

    In the Rust SDK this is built with FinalTransaction::add_program_issuance_input(...) and IssuanceInput::new_reissuance(asset_amount, asset_entropy). That call does not add another transaction input. It populates the Liquid reissuance fields on input 0, which is also the Simplicity covenant spend.

    The witness contains:

    maybe_sigs
    domain
    asset_id
    asset_amount
    recipient_script_hash
    eth_txid
    ticket_txid
    ticket_vout
  7. Broadcast the mint transaction.

    Expected result after confirmation:

    output 0 gives recipient_script_pubkey asset_amount of asset_id
    output 1 returns reissuance_token_id amount 1 to the covenant script
    input 1 spends ticket_txid:ticket_vout

    The same oracle signatures cannot be reused with a different ticket, because the signed payload commits to ticket_txid:ticket_vout and the contract requires that exact outpoint at input 1. After the ticket is spent once, that signed mint payload is no longer usable.

Regtest

If you wish to keep the blockchain's state between tests, run a local regtest separately:

simplex regtest

This command sets up the standalone nodes that can be connected to via simplex configuration.

Update the simplex.toml file with the necessary URLs and credentials, then run the test again. You will see that the state gets preserved.

Disclaimer

GLHF!