@exowarexyz/simplex
v2026.9.0
Published
Index artifacts emitted by Simplex.
Readme
@exowarexyz/simplex
TypeScript helpers for uploading Commonware Simplex artifacts into Exoware
Store. The package mirrors the Rust exoware-simplex key layout:
- header bytes by digest
- full
{ header, body }block data by digest - notarized
{ proof, header }bytes by Simplex epoch and view - finalized
{ proof, header }bytes by Simplex epoch and view - finalized
{ proof, header }bytes by block height
The TypeScript client uploads raw encoded bytes. Certificate reads verify bytes
before returning when the client is constructed with a verifier. Use the *Raw
read methods when you explicitly want unverified bytes.
import { Client, StoreWriteBatch } from '@exowarexyz/sdk';
import { SimplexClient } from '@exowarexyz/simplex';
const store = new Client('http://localhost:10000').store();
const simplex = new SimplexClient(store);
const batch = new StoreWriteBatch();
simplex.stageUpload(simplex.prepareBlock({
digest: '0x...',
header: '0x...',
body: '0x...',
}), batch);
simplex.stageUpload(simplex.prepareFinalization({
epoch: 0n,
view: 42n,
height: 42n,
finalized: '0x...',
}), batch);
await batch.commit(store);Use prepareHeader, prepareBlock, prepareNotarization, and
prepareFinalization to stage multiple Simplex rows into one
StoreWriteBatch. Raw uploads must provide the encoded certificate's epoch
and view. The client does not decode certificate bytes, so a wrong value
mis-keys the round row.
Use getHeader or subscribeHeaders when only header bytes are needed. Use
getBlock or subscribeBlocks when the caller needs the full
{ header, body } block data.
Verification
Pass a SimplexCertificateVerifier to verify opaque certificate records before
getNotarizationByRound, getFinalizationByRound, getFinalizationByHeight,
latestFinalization, or subscribeCertificates returns them:
import { SimplexClient, type SimplexCertificateVerifier } from '@exowarexyz/simplex';
const verifier: SimplexCertificateVerifier = {
verifyNotarization: async (bytes, context) => verifyMyNotarization(bytes, context.epoch, context.view),
verifyFinalization: async (bytes, context) => verifyMyFinalization(bytes, context),
};
const simplex = new SimplexClient('http://localhost:10000', { verifier });
const latest = await simplex.latestFinalization();For upstream Commonware Simplex certificate types, build the optional WASM
module and use @exowarexyz/simplex/wasm:
npm --prefix simplex/ts run build:wasmimport { createWasmSimplexVerifier } from '@exowarexyz/simplex/wasm';
import { SimplexClient, hexToBytes } from '@exowarexyz/simplex';
const verifier = await createWasmSimplexVerifier({
scheme: 'bls12381-threshold-vrf-min-sig',
payload: 'sha256',
identity: 'ed25519',
namespace: new TextEncoder().encode('_MY_SIMPLEX_NAMESPACE'),
verificationMaterial: hexToBytes('...'),
verifyHeader: ({ payload, header }) => verifyHeaderPayload(payload, header),
});
const simplex = new SimplexClient('http://localhost:10000', { verifier });Supported schemes are ed25519, secp256r1,
bls12381-multisig-min-pk, bls12381-multisig-min-sig,
bls12381-threshold-standard-min-pk,
bls12381-threshold-standard-min-sig, bls12381-threshold-vrf-min-pk, and
bls12381-threshold-vrf-min-sig. Supported payloads are sha256, blake3,
transcript-summary, and coding-commitment. Supported identity key types are
ed25519 and secp256r1. Verification material is encoded key material: an
Ed25519 participant set, a Secp256r1/BLS multisig identity-to-signing-key map,
or a threshold identity depending on the scheme.
The WASM verifier treats certificates as opaque proof-plus-header records and
verifies the configured certificate key material. Pass verifyHeader to
validate the application-specific relationship between the certificate payload
and header. Bodies are not embedded in streamed certificate records. Fetch full
{ header, body } block data separately with getBlock or subscribeBlocks
when needed. The client does not hardcode SHA or trust a server body-presence
flag. The caller-selected verifier defines the required payload/header
relationship before the TS client returns a fetched or streamed certificate.
Header and block integrity can also live in caller-owned WASM. Implement the ABI you need:
#[wasm_bindgen]
pub fn verify_header(payload: Vec<u8>, header: Vec<u8>) -> bool {
// Verify payload/header according to the application's header format.
}
#[wasm_bindgen]
pub fn verify_block(payload: Vec<u8>, header: Vec<u8>, body: Vec<u8>) -> bool {
// Verify payload/header/body according to the application's header format.
}Then adapt the module in TS:
import { createWasmSimplexVerifier } from '@exowarexyz/simplex/wasm';
import {
createWasmSimplexHeaderVerifier,
} from '@exowarexyz/simplex';
const verifier = await createWasmSimplexVerifier({
scheme,
payload,
identity,
namespace,
verificationMaterial,
verifyHeader: createWasmSimplexHeaderVerifier(myBlockVerifierWasm),
});The built-in verifier returns the signed epoch and checks any requested epoch
and view before application header verification. Custom verifiers receive the
same context and own those checks, including height/header binding.
