Skip to content
On this page

Installation & Quick Start

Installation

Locklift is typically utilized through a local installation in your project. This ensures reproducibility and prevents future version conflicts.

If you're starting a new project, you can simplify the process by running:

bash
mkdir myProject
cd myProject
npx locklift init

This will create your project directory, install Locklift, and initialize your project.

If your project already exists, you can install Locklift using:

bash
npm install --save-dev locklift

Quick Start

We will explore the basics of creating a Locklift project with a sample contract, tests of that contract, and a script to deploy it.

To create the sample project, run npx locklift init in your project folder:

bash
# initialize in the current directory
npx locklift init -f
# or specify a new one
npx locklift init --path amazing-locklift-project

TIP

If you run npx locklift init -f after npm init, it will overwrite the existing files, including package.json.

This process might not be ideal as it's still a bit raw. If you want to avoid this, you can run npx locklift init without the prior installation of Locklift. npx will automatically fetch Locklift and create a sample project.

This is a handy workaround that doesn't contradict the steps mentioned above.

Building the Contract

Next, if you take a look in the contracts/ folder, you'll see Sample.tsol:

solidity
pragma ever-solidity >= 0.61.2;
pragma AbiHeader expire;
pragma AbiHeader pubkey;


contract Sample {
    uint16 static _nonce;

    uint state;

    event StateChange(uint _state);

    constructor(uint _state) public {
        tvm.accept();

        setState(_state);
    }

    function setState(uint _state) public {
        tvm.accept();
        state = _state;

        emit StateChange(_state);
    }

    function getDetails()
        external
        view
    returns (
        uint _state
    ) {
        return state;
    }
}

Let's build the contract using the command below:

bash
npx locklift build

This command will use the specified TON Solidity compiler and TVM linker to build all contracts in the contracts/ directory. The built files will be placed in build/.

[INFO]  Found 1 sources
[INFO]  factorySource generated
[INFO]  Built

Testing the Contract

Testing the contract verifies its functions under specified conditions. We'll be utilizing Mocha for this purpose. Here's the command to execute the tests:

bash
npx locklift test

This command will automatically run the Mocha tests located in the test directory. The locklift object will be automatically configured and integrated, eliminating the need for manual import. It's noteworthy to mention that the tests will be executed in Locklift's default Locklift Network, facilitating isolated and accurate testing environments without affecting live networks.

Test Sample contract
  Contracts
    ✅ Load contract factory
    ✅ Deploy contract (1511ms)
    ✅ Interact with contract (611ms)

3 passing (2s)

In your test/ folder, you will find a test file like the following one:

typescript
import { expect } from 'chai';
import { Contract, Signer } from 'locklift';
import { FactorySource } from '../build/factorySource';

let sample: Contract<FactorySource['Sample']>;
let signer: Signer;

describe('Test Sample contract', async function () {
  before(async () => {
    signer = (await locklift.keystore.getSigner('0'))!;
  });
  describe('Contracts', async function () {
    it('Load contract factory', async function () {
      const sampleData = await locklift.factory.getContractArtifacts(
        'Sample'
      );

      expect(sampleData.code).not.to.equal(
        undefined,
        'Code should be available'
      );
      expect(sampleData.abi).not.to.equal(
        undefined,
        'ABI should be available'
      );
      expect(sampleData.tvc).not.to.equal(
        undefined,
        'tvc should be available'
      );
    });

    it('Deploy contract', async function () {
      const INIT_STATE = 0;
      const { contract } = await locklift.factory.deployContract({
        contract: 'Sample',
        publicKey: signer.publicKey,
        initParams: {
          _nonce: locklift.utils.getRandomNonce(),
        },
        constructorParams: {
          _state: INIT_STATE,
        },
        value: locklift.utils.toNano(2),
      });
      sample = contract;

      expect(
        await locklift.provider
          .getBalance(sample.address)
          .then(balance => Number(balance))
      ).to.be.above(0);
    });

    it('Interact with contract', async function () {
      const NEW_STATE = 1;

      await sample.methods
        .setState({ _state: NEW_STATE })
        .sendExternal({ publicKey: signer.publicKey });

      const response = await sample.methods.getDetails({}).call();

      expect(Number(response._state)).to.be.equal(
        NEW_STATE,
        'Wrong state'
      );
    });
  });
});

This sample test file comprises three major stages:

  1. Loading the contract factory: This phase validates the existence of the contract code, ABI (Application Binary Interface), and the tvc (TVM binary code).

  2. Deploying the contract: Here, the contract is deployed with an initial state and funded with 2 coins converted to nanocoins. The test then asserts that the balance of the contract's address is more than 0, ensuring successful deployment.

  3. Interacting with the contract: In this phase, the state of the contract is altered, and the test verifies if the state change was successful.

These tests offer a practical way to ensure the contract behaves as expected before deploying it to the live network.

Deploying the Contract

Once we have built and tested our contract, we can deploy it using a Node JS script. The command to do this is:

bash
npx locklift run --network mainnet --script scripts/1-deploy-sample.ts

TIP

Before launching into a live network, consider testing your deployment in the Locklift network which is used by Locklift by default. This allows for a secure and convenient way to ensure everything is working correctly before the actual deployment.

bash
npx locklift run --script scripts/1-deploy-sample.ts

This command will run the specified script with an already configured locklift module. In the example above, we are deploying the Sample.tsol contract.

typescript
async function main() {
  const signer = (await locklift.keystore.getSigner('0'))!;
  const { contract: sample, tx } =
    await locklift.factory.deployContract({
      contract: 'Sample',
      publicKey: signer.publicKey,
      initParams: {
        _nonce: locklift.utils.getRandomNonce(),
      },
      constructorParams: {
        _state: 0,
      },
      value: locklift.utils.toNano(3),
    });

  console.log(`Sample deployed at: ${sample.address.toString()}`);
}

main()
  .then(() => process.exit(0))
  .catch(e => {
    console.log(e);
    process.exit(1);
  });
Sample deployed at: 0:a56a1882231c9d901a1576ec2187575b01d1e33dd71108525b205784a41ae6d0

TIP

In essence, the deployment process is divided into two parts - funding from the giver, and then the actual deployment of the code. We will delve deeper into this process further in the Deploying Contracts.