@shinzonetwork/viewbundle
v1.0.1
Published
Go-compatible view bundler for ShinzoHub (bundle/unbundle register(bytes) payloads).
Readme
@shinzonetwork/viewbundle
Go-compatible view bundler for ShinzoHub.
This package produces the exact register(bytes) payload that the ShinzoHub ViewRegistry precompile expects, and can also decode it back into a runtime View.
It is designed to work in Node.js and the browser with the same wire format and limits as the Go implementation.
What it does
BundleView:
- takes
{ Query, Sdl, Transform.Lenses[] } - base64-decodes each lens WASM
- packs lenses into an ordered LensBlob
- zstd-compresses the LensBlob (when present)
- encodes the full wire payload in the Go
VWLformat
- takes
UnbundleView:
- decodes the wire payload
- safely decompresses the LensBlob (cap enforced)
- splits lens WASMs back out
- returns a runtime View (lens WASMs as base64 again)
DecodeHeader:
- reads only the header fields (Query, SDL, lens args) without unbundling lenses
Install
npm i @shinzonetwork/viewbundleQuick usage (Node.js)
import { Bundler } from "@shinzonetwork/viewbundle";
import { makeNodeZstd } from "@shinzonetwork/viewbundle/node";
const bundler = new Bundler(makeNodeZstd());
const view = {
Query: "Log { address topics data transactionHash blockNumber }",
Sdl: "type Example2 @materialized(if: false) { transactionHash: String }",
Transform: {
Lenses: [
{
Path: "<base64 wasm bytes>",
Arguments: JSON.stringify({
src: "address",
value: "0x1e3aA9fE4Ef01D3cB3189c129a49E3C03126C636",
}),
},
],
},
};
const wire = await bundler.BundleView(view);
// If you need to move wire through JSON safely, use base64.
const wireB64 = Buffer.from(wire).toString("base64");
// Later...
const wire2 = Uint8Array.from(Buffer.from(wireB64, "base64"));
const roundtrip = await bundler.UnbundleView(wire2);
console.log(roundtrip.Query);Quick usage (Browser)
import { Bundler } from "@shinzonetwork/viewbundle";
import { makeBrowserZstd } from "@shinzonetwork/viewbundle/browser";
const bundler = new Bundler(makeBrowserZstd());
const wire = await bundler.BundleView(view);
// If you need to move bytes through JSON, base64 it.
const wireB64 = btoa(String.fromCharCode(...wire));Tip: in browsers, prefer a proper base64 helper for large payloads to avoid stack limits.
API
new Bundler(zstdImpl, opts?)
type ZstdImpl = {
compress(raw: Uint8Array): Promise<Uint8Array> | Uint8Array;
decompress(comp: Uint8Array): Promise<Uint8Array> | Uint8Array;
};
new Bundler(zstdImpl, {
MaxDecompressedLensBlob?: number; // optional cap, defaults to Limits.MaxLensBlobBytes
});bundler.BundleView(view) -> Promise<Uint8Array>
Bundles a runtime View into wire bytes (the register(bytes) payload).
bundler.UnbundleView(wire) -> Promise<View>
Decodes wire bytes back into a runtime View.
bundler.DecodeHeader(wire) -> { Header, LensCodec, LensBlobLen }
Header-only decode helper for workflows where you only need Query/SDL/lens args.
Wire format (Go-compatible)
The bundle payload matches the Go encoder:
[magic "VWL"][version u8]
[queryLen u32 LE][query bytes]
[sdlLen u32 LE][sdl bytes]
[lensCount u16 LE]
repeat lensCount:
[id u32 LE] // must be positional 1..N
[argsLen u32 LE][args bytes]
[codec u8] 0=none 1=zstd
[blobLen u32 LE][blob bytes] // raw or compressedLens blob layout (ordered):
COUNT u16 LE
repeat COUNT:
WASM_LEN u32 LE
WASM_BYTESLimits
Defaults are tuned for a base64 transport target of 512 KiB.
Because base64 adds ~33% overhead, the raw wire cap is set to 384 KiB by default so that:
base64(wire)stays<= 512 KiB
Notes
- Do not convert wire bytes to
string(wire)and pass through JSON. That corrupts data. - If you need to send the payload through JSON, base64 encode the bytes.
- For blockchain submission via
eth_sendTransaction, you can passUint8Arraydirectly to ABI encoding in most SDKs (ethers, viem). Base64 is only for your own transport layers.
Exports
- Core:
@shinzonetwork/viewbundle
- Node zstd factory:
@shinzonetwork/viewbundle/node
- Browser zstd factory:
@shinzonetwork/viewbundle/browser
License
MIT
