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 🙏

© 2024 – Pkg Stats / Ryan Hefner

@hackbg/borshest

v1.0.0-rc.1

Published

Extensible, zero-dependency Borsh and Zcash encoding and decoding

Downloads

429

Readme

@hackbg/borshest 🌲6️⃣

Borsh (Binary Object Representation Serializer for Hashing) is a non-self-describing, binary serialization format....

... meant to be used in security-critical projects as it prioritizes consistency, safety, speed; and comes with a strict specification. (https://borsh.io/)[https://borsh.io/]

This library is based on Borsh-JS (by Near, Dual Apache-2.0/MIT License) and Borsher (by NameSky, MIT License). See below for how we differ from those two.

Quick start

npm i --save @hackbg/borshest

API cheat sheet

// Entry points:
import { decode, encode } from '@hackbg/borshest'

// Types:
import {
  unit,                                    // empty type
  bool, option,                            // boolean, optional
  unsigned, u8, u16, u32, u64, u128, u256, // unsigned integer
  signed, i8, i16, i32, i64, i128, i256,   // signed integer
  float, f32, f64,                         // floating point
  array, vector, set, map,                 // collections
  struct, variants,                         // structures (variant = enum)
} from '@hackbg/borshest'

// Helpers:
import {
  Struct,  // structs into class instances
  variant, // enum variant -> [name, data]
} from '@hackbg/borshest'

// Encoding and decoding:
const value:   bigint     = 12345678901234567890n
const encoded: Uint8Array = encode(u256, value)
const decoded: bigint     = decode(u256, encoded)

const schema = struct(
  ['field1',     u256],
  ['field2',     bool],
  ['field3',     variants(
    ['variant1', unit],
    ['variant2', string],
    ['variant3', struct(
      ['field1', array(20, u8)],
      ['field2', vector(string)],
      ['field3', type],
    )],
  )]
)

const value = { /*...*/ }

const encoded = encode(schema, value)

const decoded = decode(schema, encoded)

Differences from prior art

256-bit numbers

Borshest provides signed and unsigned integers up to 256-bit precision.

Extensibility

Instead of an intermediate schema representation; all fields are represented by literal objects of the following form:

type Field<T> = {
  encode: (buffer: EncodeBuffer, value: T): void
  decode: (buffer: DecodeBuffer): T
}
const encoded = encode(field, object)
const decoded = decode(field, binary)

This means you can easily implement custom fields if your implementation requires extending Borsh (though we'd advise against that.)

Thanks to this extensible architecture, Borshest also provides support for Zcash encoding, which is used alongside Borsh in the Namada API.

Struct and enum schema

Borsh expects consistent field order. The field order in JS objects is unspecified Borshest does not rely on key order for representations of structs and enums, which is undefined according to JS spec. That's why they are represented as sequences of [name, type] pairs instead of the more customary {name: type} records.

// Struct fields:
import { struct } from '@hackbg/borshest'
const schema = struct(
  ['field1', schema],
  ['field2', schema],
  ['field3', schema],
)

// Enum variants:
import { variants } from '@hackbg/borshest'
const schema = variants(
  ['variant1', schema],
  ['variant2', schema],
  ['variant3', schema],
)

No decorators

Unlike @dao-xyz/borsh, we do not use decorators, as they are an unstable feature. Instead, you can define classes of the following form:

import { Struct } from '@hackbg/borshest'
class MyStruct extends fromStruct(
  ['my_field',       string],
  ['my_other_field', u128]
) {
  myMethod () { /***/ }
}

In TypeScript, to specify types, you must use the declare modifier (otherwise the values will be overwritten with undefined during construction):

import { Struct } from '@hackbg/borshest
class MyStruct extends fromStruct(
  ['myField',      string],
  ['myOtherField', u128]
) {
  declare myField:      string
  declare myOtherField: bigint

  myMethod () { /***/ }
}

This does have the unfortunate side effect of having to write field names twice 🤷 On the other hand, it saves you from depending on the opaque transpilation machinery that provides decorator support, and hopefully speeds up your builds somewhat.