2.0.1 • Published 7 days ago

clvm v2.0.1

Weekly downloads
-
License
MIT
Repository
github
Last release
7 days ago

clvm

Javascript implementation of CLVM (Chia Lisp VM)

Install

npm install clvm
# or
yarn add clvm

Compatibility

This code is compatible with:

Example

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

  // 'clvm.initialization()' here is not required
  // if you're so sure it never calls 'pubkey_for_exp' or 'point_add' operation.
  // When one of those operations is called without prior 'clvm.initialize()'
  // it will raise an Error.
  // If it is unknown whether 'pubkey_for_exp' or 'point_add' will be called, 
  // then put 'await clvm.initialize()' for safety.
  // I know this 'await clvm.initialize()' makes code asynchronous
  // and really impacts on code architecture.
  // This is because 'clvm' relys on a wasm of 'bls-signatures',
  // which requires asynchronous loading.
  await clvm.initialize();
  
  const {SExp, OPERATOR_LOOKUP, KEYWORD_TO_ATOM} = clvm;
  const v1 = OPERATOR_LOOKUP(KEYWORD_TO_ATOM["+"], SExp.to([3,4,5]))[1];
  const v2 = SExp.to(12);
  const ok = v1.equal_to(v2);
  console.log(`ok: ${ok}`); // 'ok: true'
}

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

Use in browser

If you'd like to run some javascript code which depends on clvm on browser,
you need to put blsjs.wasm to the same directory as the code who loads clvm.

If you use React, put blsjs.wasm into public folder. It automatically places wasm file next to main js file.

Note1: Don't forget to wait clvm.initialize() if you are not sure whether pubkey_for_exp/point_add will be called.
Note2: If you're really sure that pubkey_for_exp/point_add will never be called, then you can opt out blsjs.wasm and await clvm.initialize(). If so, you can make your code fully synchronous.

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

PythonJavaScript
-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

bls-signatures license

bls-signatures is used under the Apache license 2.0

jscrypto license

jscrypto is used under the MIT license

3.0.0-beta.0

7 days ago

2.0.1

2 years ago

2.0.0

2 years ago

1.0.9

2 years ago

2.0.0-beta.1

2 years ago

2.0.0-beta.0

2 years ago

1.0.8

3 years ago

1.0.7

3 years ago

1.0.7-beta.2

3 years ago

1.0.7-beta.1

3 years ago

1.0.7-beta.0

3 years ago

1.0.6

3 years ago

1.0.5

3 years ago

1.0.4

3 years ago

1.0.3

3 years ago

1.0.2

3 years ago

1.0.1

3 years ago

1.0.0

3 years ago

0.0.19

3 years ago

0.0.18

3 years ago

0.0.17

3 years ago

0.0.16

3 years ago

0.0.15

3 years ago

0.0.14

3 years ago

0.0.13

3 years ago

0.0.12

3 years ago

0.0.11

3 years ago

0.0.10

3 years ago

0.0.9

3 years ago

0.0.8

3 years ago

0.0.7

3 years ago

0.0.5

3 years ago

0.0.4

3 years ago

0.0.6

3 years ago

0.0.3

3 years ago

0.0.2

3 years ago

0.0.1

3 years ago

0.0.0

3 years ago

0.0.0-beta.1

3 years ago

0.0.0-beta.0

3 years ago