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

clvm

v3.0.0

Published

Javascript implementation of chia lisp

Downloads

142

Readme

clvm

Javascript implementation of CLVM (Chia Lisp VM)

Install

npm install clvm
# or
yarn add clvm

Test

clvm-js passes all the test equivalent to Python's original clvm.
You can compare test files for Javascript and Python
To run the test, execute the following command.

git clone https://github.com/Chia-Mine/clvm-js
cd clvm-js

npm install
npm run test
# or
yarn
yarn test

If you find something not compatible with Python's clvm, please report it to GitHub issues.

Compatibility

This code is compatible with:

Example

// in nodejs context
async function main(){
  const clvm = require("clvm");

  // `await clvm.initializeClvmWasm()` is now always necessary.
  // This loads clvm_wasm_bg.wasm.
  // If you have a strong reason to use features of bls-signatures,
  // you need to do `await clvm.initialize()` instead.
  // `clvm.initialize()` loads both blsjs.wasm and clvm_wasm_bg.wasm.
  await clvm.initializeClvmWasm();
  
  const {SExp, KEYWORD_TO_ATOM, h, t, run_chia_program, Flag} = clvm;
  const plus = h(KEYWORD_TO_ATOM["+"]); // byte representation of '+' operator
  const q = h(KEYWORD_TO_ATOM["q"]); // byte representation of 'q' operator
  const program = SExp.to([plus, 1, t(q, 175)]).as_bin().raw(); // (+ . (1 . (q . 175)))
  const env = SExp.to(25).as_bin().raw();
  const max_cost = BigInt(10000000);
  const [cost, lazyNode] = run_chia_program(program, env, max_cost, Flag.allow_backrefs());
  const result = new SExp(lazyNode);
  let isEqual = result.equal_to(SExp.to(25 + 175));
  console.log(`isEqual: ${isEqual}`); // 'isEqual: true'
  isEqual = result.as_int() === (25 + 175);
  console.log(`isEqual: ${isEqual}`); // 'isEqual: true'
}

main().catch(e => console.error(e));

More example with clvm_wasm

See this test case for clvm_wasm

Use in browser

If you'd like to run some javascript code which depends on clvm on browser,
you need to put clvm_wasm_bg.wasm and optionally blsjs.wasm to the same directory as the code who loads clvm.
Because most of BLS operations are now performed inside clvm_wasm_bg.wasm, in most cases you don't need blsjs.wasm.

If you use React with CRA(create-react-app), copy blsjs.wasm and clvm_wasm_bg.wasm into <react-project-root>/public/static/js/ folder. It automatically copies wasm file next to main js file.

If you use React with vite, copy blsjs.wasm and clvm_wasm_bg.wasm into <react-project-root>/public/assets/ folder.

IMPORTANT NOTE
When your code is loaded as a module, such as with <script type='module'/> (common in React with Vite), there is a path restriction for loading the WebAssembly (WASM) module.
See Known Issues. Also see code comment here

Note1
Don't forget to wait clvm.initializeClvmWasm().
clvm.initializeClvmWasm() only loads clvm_wasm_bg.wasm.
If you have a strong reason to use features of bls-signatures inside clvm-js, you need to wait clvm.initialize() instead, since clvm.initialize() loads both blsjs.wasm and clvm_wasm_bg.wasm.
Note2
Redistributing your project with bundled blsjs.wasm and/or clvm_wasm_bg.wasm must be compliant with Apache2.0 License provided by Chia-Network
Note3 You may need blsjs.wasm if you want to run run_program, which has been deprecated as of [email protected].

Browser compatibility

clvm-js uses BigInt. So if runtime environment does not support BigInt, clvm-js doesn't work as well.
If you transpile code using babel or something which uses babel (like create-react-app), you need to tell the transpiler to optimize code only for the target browsers.
Just copy and paste below to your package.json and you can avoid a lot of runtime incompatibility issues.

"browserslist": [
  "edge >= 79",
  "firefox >= 68",
  "chrome >= 67",
  "safari > 14",
  "opera >= 54",
  "ios_saf >= 14.4",
  "android >= 67",
  "op_mob >= 48",
  "and_chr >= 67",
  "and_ff >= 68",
  "samsung >= 9.2",
  "node >= 10.4.0",
  "electron >= 4.0.0"
]

Differences with Python's clvm

Although I try hard to make it look like Python's clvm, there are things users should be aware of.
I put the code which absorbs language incompatibility into src/__type_compaibility__.ts, so if you're interested take a look at it.

There are no build-in Tuple type in Javascript

When you want to create a tuple, you need to write like this:

const {t} = require("clvm"); 
const aTuple = t(1, 2);

// Tuple is Array-Like object
aTuple[0] === 1; // true
aTuple[1] === 2; // true

// Tuple content cannot be changed
aTuple[0] = 99;
aTuple[0] === 99; // false
aTuple[0] === 1; // true

// Tuple accepts only 2 elements.
const tuple2 = t(1, 2, 3);
tuple2; // (1, 2)

// You can check if a variable is a tuple
const {isTuple, isList} = require("clvm");
isTuple([1, 2]); // false
isTuple(t(1, 2)); // true
isList([1, 2]); // true
isList(t(1, 2)); // false

Just add t in front of tuple parenthesis (1, 2) and you get a tuple.

There are no build-in bytes type in JavaScript

This is the most notable difference with Python.
I used to be a JavaScript developer for several years, and sometimes I heard Python is slow and JavaScript is fast.
But working on the project, I truly surprised that Python can handle byte data really well in ways:

  • Python's bytes is immutable and can be used as a dict key.
  • Python's bytes is fast and easy to write.
    b'aaa' + b'bbb' == b'aaabbb', b'a' * 3 == b'aaa'
  • Python's bytes comparison is FAST.
    If you are interested, compare the performance of test_very_long_blobs in tests/serialize_test.[ts|py]
    See more details here
const {b} = require("clvm");
// Turns string to UTF-8 byte array.
b("abc"); // will be { Uint8Array(3) [97,98,99] }
b("あ"); // will be { Uint8Array(3) [227,129,130] }

// If you want to do Byte comparison, use equal_to method.
b("abc").equal_to(b("abc")); // true
b("abc") === b("abc"); // false. Because it compares reference of Bytes instance.

// Initialize Bytes instance with hex string
const {h} = require("clvm");
h("0x616263"); // will be { Uint8Array(3) [97,98,99] }
h("616263"); // You can omit '0x' prefix
h("0x616263").equal_to(b("abc")); // true

// +: Bytes concat
b("a").concat(b("b")); // === b("ab")
// *: Bytes repeat
b("a").repeat(3); // === b("aaa")

// Bytes initialization
const {Bytes} = require("clvm");
uint8 = new Uint8Array([97, 98, 99]);
b1 = Bytes.from(uint8);
b1.equal_to(b("abc")); // true
// Initializing by Bytes.from copies value and cut reference apart.
uint8[0] = 0;
b1.at(0); // 97
// Initializing by new Bytes() just stores value and keep reference, for better performance
uint8 = new Uint8Array([97, 98, 99]);
b2 = new Bytes(uint8);
b2.equal_to(b("abc")); // true
uint8[0] = 0;
b2.at(0); // 0

// Check byte instance
const {isBytes} = require("clvm");
isBytes(b('aaa')); // true
isBytes(h('0xfe')); // true
isBytes(new Bytes()); // true

Python's str(x) is x.toString() in Javascript

If you want to stringify SExp or Bytes, just call x.toString() method.

const {b, SExp, str} = require("clvm");
b("あ").toString(); // "b'\\xe3\\x81\\x82'"
SExp.to([1, [2, 3]]).toString(); // 'ff01ffff02ff038080'
str(SExp.to([1, [2, 3]])); // You can use str() function as well as Python by the way.

Calculation of division/modulo against negative number is different

|Python|JavaScript| |------|----------| |-8 // 5 == -2|-8n / 5n === -1n| |-8 % 5 == 2|-8n % 5n === -3n|

clvm license

clvm-js is based on clvm with the Apache license 2.0

clvm_wasm license

clvm_wasm is used and redistributed under the Apache license 2.0

bls-signatures license

bls-signatures is used and redistributed under the Apache license 2.0

jscrypto license

jscrypto is used under the MIT license