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
@method
s, 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 @prop
s and @method
s like smart contracts which have the same rules introduced before. A smart contract library can be used within @method
s 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.
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.
Related Tools
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.