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

echpochmak

v0.3.5

Published

Echpochmak is a toolchain for developing Decentralized Applications based on TON

Downloads

21

Readme

npm Contributors Forks Stargazers Issues MIT License

About The Project

Echpochmak, is a framework based on TONOS Client Library for TON DApp development

It provides some high-level interfaces to interact with your TON smart-contracts, allowing you to write integration and e2e tests.

Content Table

Getting Started

  1. Install Echpochmak
npm install -g echpochmak

Test Examples

You can see examples of tests here

Usage

To run all tests:

echpochmak-cli test -p ./path/to/tests/folder

Synopsis

test [options]

Options

| Option | Description | Default | | ------------------- | --------------------- | ------- | | -p, --path | Path to test folder | | | -b, --bail | Enable bail | false | | -v, --verbose | Wite debug info | false | | -t, --timeout | Timeout time for test | 0 | | --version (boolean) | Show version | | | --help (boolean) | Show help information | |

If you need help, use

echpochmak-cli --help

Write test

Tests are written using Mocha

Restart tondev command

beforeEach(async () => {
  await restart(); //Recreate and start containers
});

Or set port (if you use don't default port in tondev-cli)

restart command does not set a port for the container, but only uses it for long polling

beforeEach(async () => {
  await restart(8080); //Default 80
});

The manager is in the global scope

const manager = new Manager();

Create new Manager object

beforeEach(async () => {
    manager = new Manager();

Create client

default ['net.ton.dev']

Signature

async createClient(servers: string[] = ['net.ton.dev'])

await manager.createClient(['http://localhost:8080/graphql']);

Generate keys

let keys = await manager.createKeysAndReturn();

Load contract

Signature

public async loadContract( contractPath: string, abiPath: string, options: loadOptions )

await manager.loadContract(
  './tests/contract/15_MessageReceiver.tvc', // tvc
  './tests/contract/15_MessageReceiver.abi.json' // abi
);
await manager.loadContract(
  './tests/contract/15_MessageReceiver.tvc', // tvc
  './tests/contract/15_MessageReceiver.abi.json' // abi
);
// Custom name
await manager.loadContract(
  './tests/contract/15_MessageSender.tvc',
  './tests/contract/15_MessageSender.abi.json',
  { contractName: 'sender ' } // Name
);
// Custom keys
await manager.loadContract(
  './tests/contract/15_MessageSender.tvc',
  './tests/contract/15_MessageSender.abi.json',
  { keys: anyKeys } // keys
);

Get future/current address

let address = manager.contracts['15_MessageReceiver'].address;

loadOption signature

export interface loadOptions {
  keys?: any;
  contractName?: string;
}

Referring to the contract

manager.contracts['Contract_name']; // Taken from the name of the tvc file without extension

Deploy contract

Signature

async deployContract(constructorParams = {}, giveGram = true, keys?)

await manager.contracts['15_MessageReceiver'].deployContract();
await manager.contracts['15_MessageSender'].deployContract();

Deploy with parameters

await manager.contracts['9_PiggyBank'].deployContract({
  own: manager.contracts['9_PiggyBank_Owner'].address,
  lim: 1000000,
});

"Complicated" deploy

This method allows you to provide: constructor parameters, constructor headers and init parameters of your deployable smart contract

await manager.contracts['someName'].complicatedDeploy(
  constructorParams,
  constructorHeader,
  initParams,
)
await manager.contracts['9_PiggyBank'].complicatedDeploy(
  {
    own: manager.contracts['9_PiggyBank_Owner'].address,
    lim: 1000000,
  },
  {
    pubkey: keypair.public,
    expire: new Date()
  },
  {
    randomNonce: '0x' + crypto.createHash('sha256').update(crypto.randomBytes(32)).digest('hex')
  }
);

### Or use custom keys

```js
await manager.contracts['9_PiggyBank'].deployContract({}, keys);

Add contract from address

Signature

async addContractFromAddress( address: string, abiPath: string, contractName: string, keyPair? )

await manager.addContractFromAddress(
  'address',
  'abiPath',
  'contractName',
  keyPair // HERE, the keys are indicated, if nothing is specified, those inside the contract object are used
);

Run contract

Signature

async runContract(functionName, input, keyPair?)

await manager.contracts['15_MessageSender'].runContract('sendMessage', {
  anotherContract: manager.contracts['15_MessageReceiver'].address,
});

Run contract(no sign)

await manager.contracts['15_MessageSender'].runContract(
  'sendMessage',
  {
    anotherContract: manager.contracts['15_MessageReceiver'].address,
  },
  null // HERE, the keys are indicated, if nothing is specified, those inside the contract object are used (see below);
);

RunLocal contract

Signature async runLocal(functionName, input, keyPair?)

await manager.contracts['15_MessageSender'].runLocal('getData', {});

Run contract with message

Signature

public async runWithMessage(functionName, input, keyPair?)

const msg = await manager.contracts['15_MessageSender'].runWithMessage(
  'sendMessage',
  {
    anotherContract: manager.contracts['15_MessageReceiver'].address,
  }
);

console.log(`Tokens were sent. Transaction id is ${msg.transaction.id}`);
console.log(`Run fees are  ${JSON.stringify(msg.fees, null, 2)}`);

Use Giver

Signature

async giveToAddress(address, amount?: number)

manager.giveToAddress(manager.contracts['15_MessageReceiver'].address); // give 1000000000000000 gram

Contract fields

manager.contracts['15_MessageSender'].address; // Contract address
manager.contracts['15_MessageSender'].contractPath; // Contract path
manager.contracts['15_MessageSender'].isDeployed; // boolean
manager.contracts['15_MessageSender'].contractPackage; //{ abi,imageBase64 }

Helpers

Use helpers from Manager object

manager.helpers.<helper>;

deployCheck

Signature public static async deployCheck(address, client)

await manager.helpers.deployCheck(contractAddress, manager.client);

getAccountBalance

Signature public static async getAccountBalance(address, client)

await manager.helpers.getAccountBalance(contractAddress, manager.client);

hasOnBounced

Signature public static async hasOnBounced(address, timestamp: number, client)

timestamp - The time when the transaction preceding OnBounced was made, guarantees the assistant will wait for the last message OnBounced

await manager.helpers.hasOnBounced(contractAddress, manager.client);

lastTransaction

Signature public static async lastMessage( address, client, fields = 'src, dst, bounce, bounced, value' )

let tx = await manager.helpers.lastTransaction(contractAddress, manager.client);

lastMessage

Signature public static async lastMessage( address, client, fields = 'src, dst, bounce, bounced, value' )

let msg = await manager.helpers.lastMessage(contractAddress, manager.client);

balanceHasChanged

Signature public static async balanceHasChanged( address, client, oldValue, type: hasChangedValue )

await manager.helpers.balanceHasChanged(
  contractAddress,
  manager.client,
  100000,
  hasChangedValue.big
);

hasChangedValue enum

export enum hasChangedValue {
  big,
  small,
}

getRunFees

Signature

static async getRunFees( contract: Contract, functionName, input, client, keyPair )

const fees = await manager.helpers.getRunFees(
  manager.contracts['15_MessageSender'],
  'send',
  manager.client,
  keys
);

getDeployFees

Signature

static async getDeployFees( contract: Contract, constructorParams, newAccount: boolean, client, keyPair )

const fees = await manager.helpers.getDeployFees(
  manager.contracts['15_MessageSender'],
  {},
  true,
  manager.client,
  keys
);

Asserts

assertError

Signature

assertError = async (asyncFn: any, code: number, message?)

Example

await assertError(
  async () => {
    await manager.contracts['9_PiggyBank'].runContract('getData', {});
  },
  3025,
  'getData'
);

Wallet Contract

A simple wallet contract, you may find it useful when testing fallback functions

Create Wallet object()

Signature

async createWallet(keys?)

let wallet = await manager.createWallet();

or set keys

let wallet = await manager.createWallet(keys);

Deploy wallet

await wallet.deploy();

SendTransaction

Signature

async sendTransaction(dest: string, value: number, bounce: boolean)

await wallet.sendTransaction(
  (dest: string),
  (value: number),
  (bounce: boolean)
);

Wallet fields

wallet.address; // wallet address
wallet.contractPath; // wallet path
wallet.isDeployed; // boolean
wallet.contractPackage; //{ abi,imageBase64 }

Custom Contract Object

Create class

CustomObject.example.js

const BaseContract = require('echpochmak').BaseContract; // Import BaseContract class

class BankContract extends BaseContract {
  async getData() {
    // new
    return await this.runLocal('getData', {}); // Using 'contract' object fields
  }
}

module.exports = BankContract;

Use in tests

Import contract object

const BankContract = require('./CustomObject.example');

Create object (Constructor used from BaseContract class)

const customBankObject = await new BankContract(
  './tests/contract/9_PiggyBank.tvc',
  './tests/contract/9_PiggyBank.abi.json',
  manager.client,
  await manager.createKeysAndReturn()
);

Add object in manager

manager.addCustomContract(customBankObject, 'customBank');

Use custom fields

const res = await manager.contracts['customBank'].getData();

BaseContract class

/* eslint-disable @typescript-eslint/no-explicit-any */
import { readFileSync } from 'fs';
import { resolve } from 'path';
import { deploy } from '../Deploy/Deploy';

export abstract class BaseContract {
public contractPackage: any;
public contractPath: string;
public isDeployed = false;
public address: any;
protected client: any;
protected keys: any;

constructor(
contractPath: string,
abiPath: string,
client,
keys: any,
noPath = false
) {
// read contract .tvc file
let imageBase64 = '';
if (!noPath) {
const buff = readFileSync(resolve(contractPath));
// convert tvc code into base64
imageBase64 = buff.toString('base64');
}

  // eslint-disable-next-line @typescript-eslint/no-var-requires
  const abi = require(resolve(abiPath));
  this.contractPackage = { abi, imageBase64 };
  this.client = client;
  this.keys = keys;
  this.isDeployed = false;

}

public async deployContract(constructorParams = {}, giveGram = true, keys?) {
this.address = await deploy(
this.client,
this.contractPackage,
keys || this.keys,
constructorParams,
giveGram
);
this.isDeployed = true;
}

public async runWithMessage(functionName, input, keyPair?) {
if (!this.isDeployed) {
throw new Error('Contract not deployed');
}
if (!keyPair) {
keyPair = this.keys;
}
const runMessage = await this.client.contracts.createRunMessage({
address: this.address,
abi: this.contractPackage.abi,
functionName,
input,
keyPair,
});
const messageProcessingState = await this.client.contracts.sendMessage(
runMessage.message
);
const result = await this.client.contracts.waitForRunTransaction(
runMessage,
messageProcessingState
);
return result;
}

public async runLocal(functionName, input, keyPair?) {
if (!this.isDeployed) {
throw new Error('Contract not deployed');
}
if (!keyPair) {
keyPair = this.keys;
}
const response = await this.client.contracts.runLocal({
address: this.address,
abi: this.contractPackage.abi,
functionName,
input,
keyPair,
});
return response;
}

public async futureAddress() {
const futureAddress = (
await this.client.contracts.getDeployData({
abi: this.contractPackage.abi,
imageBase64: this.contractPackage.imageBase64,
publicKeyHex: this.keys.public,
})
).address;
return futureAddress;
}
public async runContract(functionName, input, keyPair?) {
if (!this.isDeployed) {
throw new Error('Contract not deployed');
}
if (!keyPair) {
keyPair = this.keys;
}
const response = await this.client.contracts.run({
address: this.address,
abi: this.contractPackage.abi,
functionName: functionName,
input: input,
keyPair: keyPair, //there is no pubkey key check in the contract so we can leave it empty
});
return response.output;
}
}

Contributing

Contributions are what make the open source community such an amazing place to be learn, inspire, and create. Any contributions you make are greatly appreciated.

  1. Fork the Project
  2. Create your Feature Branch (git checkout -b feature/AmazingFeature)
  3. Commit your Changes (git commit -m 'Add some AmazingFeature')
  4. Push to the Branch (git push origin feature/AmazingFeature)
  5. Open a Pull Request

License

Distributed under the Apache 2.0 License. See LICENSE for more information.

Contact