Skip to main content

How to Publish a Contract to NPM

What is a Smart Contract Library?

A smart contract library can provide methods which can be reused in many contracts. Developers can use existing libraries to reduce the cost of developing their own contracts.

A smart contract library is different from a smart contract in these ways:

  • A smart contract library can not have any public/entry @methods, which means a library can not be deployed or called directly through a tx. They can only be called within a smart contract or another library.

  • A smart contract library can not have any stateful properties, i.e. @prop(true) properties. But a property declared as @prop() is fine.

Write a Smart Contract Library

Using sCrypt we can create a smart contract library class like this:

class MyLib extends SmartContractLib {

@prop()
readonly buf: ByteString;

constructor(buf: ByteString) {
super(...arguments);
this.buf = buf;
}

@method()
append(content: ByteString) {
this.buf += content;
}

@method()
static add(x: bigint, y: bigint): bigint {
return x + y;
}

}

A smart contract library can be declared as a class that extends SmartContractLib. It may also have @props and @methods like smart contracts which have the same rules introduced before. A smart contract library can be used within @methods like this:

class MyContract extends SmartContract {
@method()
public unlock(x: ByteString) {
let myLib = new MyLib(hexToByteString('0123'));
myLib.append(x);
assert(MyLib.add(1n, 2n) === 3n, 'incorrect sum');
}
}

Test a Smart Contract Library

You can test your smart contract library as a normal class, for example, writing some unit tests:

describe('Test SmartContractLib `MyLib`', () => {
it('should pass unit test successfully.', () => {
expect(MyLib.add(1n, 2n)).to.eq(3n)
})
})

Also you can write a smart contract using the library, then have some tests for the contract, like:

class TestLib extends SmartContract {
@method
public unlock(x: bigint) {
assert(MyLib.add(1n, 2n) == x, 'incorrect sum')
}
}

describe('Test SmartContractLib `Lib`', () => {
before(async() => {
await TestLib.loadArtifact()
})

it('should pass integration test successfully.', () => {
let testLib = new TestLib()
let result = testLib.verify(self => self.unlock(3n))
expect(result.success, result.error).to.be.true
}
})

Create and Publish a Library Project Using sCrypt CLI

The following command will create a demo sCrypt library along with tests and scaffolding:

npx scrypt-cli project --lib <your-lib-name>

Note the lib option is turned on.

You can publish the library on NPM by running the following command in the project's root directory:

npm publish

This will build the project and publish it on NPM. After the library is published, users can simply import it in any other project just like regular NPM packages.

note

Named imports are not supported yet. You should only import like the following.

import { MyLib } from “my_package”

Advanced

For the import system working properly, you should always publish the auto-generated sCrypt contracts (including scrypt.index.json file) along with the javascript outputs. The structure of the package could be like this:

node_modules
|__ my_package
|__ dist
|__ myLib.js
|__ myLib.d.ts
|__ artifacts
|__ myLib.scrypt
|__ scrypt.index.json

The scrypt.index.json file will be generated at TypeScript compile time in the same directory of your tsconfig.json which should be placed in the root folder. It shall not be moved or modified manually. The folder for auto-generated .scrypt files (artifacts in the upper file tree) can be changed by configuring the outDir option in tsconfig.json, like:

"compilerOptions": {
"plugins": [
{
"transform": "scrypt-ts/dist/transformation/transformer",
"transformProgram": "true",
"outDir": "my_scrypts_dir"
}
]
}

You should always publish the auto-generated sCrypt files along with the package.

scrypt-ts-lib

It’s a collection of smart contract libraries provided by us. You can find some useful tools here. Also you are welcome to contribute.