Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/btc-vision/unit-test-framework
OP_Net official unit-test framework for contracts.
https://github.com/btc-vision/unit-test-framework
Last synced: 28 days ago
JSON representation
OP_Net official unit-test framework for contracts.
- Host: GitHub
- URL: https://github.com/btc-vision/unit-test-framework
- Owner: btc-vision
- License: mit
- Created: 2024-11-15T00:03:24.000Z (about 2 months ago)
- Default Branch: main
- Last Pushed: 2024-12-02T23:35:08.000Z (about 1 month ago)
- Last Synced: 2024-12-03T00:27:09.267Z (about 1 month ago)
- Language: TypeScript
- Size: 49.8 KB
- Stars: 1
- Watchers: 0
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# OP_NET Smart Contract Testing Framework
![Bitcoin](https://img.shields.io/badge/Bitcoin-000?style=for-the-badge&logo=bitcoin&logoColor=white)
![AssemblyScript](https://img.shields.io/badge/assembly%20script-%23000000.svg?style=for-the-badge&logo=assemblyscript&logoColor=white)
![Rust](https://img.shields.io/badge/rust-%23000000.svg?style=for-the-badge&logo=rust&logoColor=white)
![TypeScript](https://img.shields.io/badge/TypeScript-007ACC?style=for-the-badge&logo=typescript&logoColor=white)
![NodeJS](https://img.shields.io/badge/Node%20js-339933?style=for-the-badge&logo=nodedotjs&logoColor=white)
![NPM](https://img.shields.io/badge/npm-CB3837?style=for-the-badge&logo=npm&logoColor=white)
![Gulp](https://img.shields.io/badge/GULP-%23CF4647.svg?style=for-the-badge&logo=gulp&logoColor=white)
![ESLint](https://img.shields.io/badge/ESLint-4B3263?style=for-the-badge&logo=eslint&logoColor=white)[![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square)](https://github.com/prettier/prettier)
This repository provides a robust framework for developing and testing smart contracts on the OPNet blockchain. The
framework includes essential tools and guidelines for ensuring your contracts are functional, secure, and performant.## Introduction
The **OP_NET Smart Contract Testing Framework** is designed to facilitate the development and testing of smart
contracts. It includes utilities, test cases, and a structured environment to ensure that your contracts
work as intended under various conditions.## Requirements
Ensure the following are installed before using the framework:
- [Node.js](https://nodejs.org/)
- [npm](https://www.npmjs.com/) or [Yarn](https://yarnpkg.com/)
- [TypeScript](https://www.typescriptlang.org/)
- [Rust](https://www.rust-lang.org/)## Installation
Clone the repository and install the dependencies:
```bash
git clone https://github.com/@btc-vision/unit-test-framework.git
cd unit-test-framework
npm install
```## Compiling Contracts and Tests
Before running the tests, you need to compile your contracts and test files. Use the following command:
```bash
npm run build
```Or, alternatively:
```bash
gulp
```This will compile your TypeScript files into JavaScript, and the output will be located in the `build/` directory.
### Advanced Compilation
For more advanced documentation please click [here](docs/README.md).
### Example Test File
Here's an example of what your test file might look like:
```typescript
import { opnet, OPNetUnit } from '../opnet/unit/OPNetUnit.js';
import { Assert } from '../opnet/unit/Assert.js';
import { MyCustomContract } from '../contracts/MyCustomContract.ts';await opnet('MyCustomContract Tests', async (vm: OPNetUnit) => {
vm.beforeEach(async () => {
// Initialize your contract here...
});vm.afterEach(async () => {
// Clean up after each test...
});await vm.it('should correctly execute a function', async () => {
// Your test logic here...
Assert.expect(someValue).toEqual(expectedValue);
});
});
```## Example Contracts
Here's an example of a basic contract that users must implement to interact with their own contracts:
```typescript
import { CallResponse, ContractRuntime } from '../opnet/modules/ContractRuntime.js';
import { Address, BinaryReader, BinaryWriter } from '@btc-vision/transaction';export class MyCustomContract extends ContractRuntime {
// Implementation details...
}
```### Contract Implementation Example
Let's create a simple token contract that follows the OP_20 standard (similar to ERC20 in Ethereum). This contract will
allow minting, transferring, and checking the balance of tokens.**File: `/src/contracts/SimpleToken.ts`**
```typescript
import { ContractRuntime, CallResponse } from '../opnet/modules/ContractRuntime.js';
import { Address, BinaryReader, BinaryWriter } from '@btc-vision/transaction';
import { Blockchain } from '../blockchain/Blockchain.js';export class SimpleToken extends ContractRuntime {
private readonly mintSelector: number = Number(`0x${this.abiCoder.encodeSelector('mint')}`);
private readonly transferSelector: number = Number(`0x${this.abiCoder.encodeSelector('transfer')}`);
private readonly balanceOfSelector: number = Number(`0x${this.abiCoder.encodeSelector('balanceOf')}`);constructor(
address: Address,
public readonly decimals: number,
gasLimit: bigint = 300_000_000_000n,
) {
super(address, 'bcrt1pe0slk2klsxckhf90hvu8g0688rxt9qts6thuxk3u4ymxeejw53gs0xjlhn', gasLimit);
this.preserveState();
}public async mint(to: Address, amount: bigint): Promise {
const calldata = new BinaryWriter();
calldata.writeAddress(to);
calldata.writeU256(amount);const result = await this.readMethod(
this.mintSelector,
Buffer.from(calldata.getBuffer()),
this.deployer,
this.deployer,
);if (!result.response) {
this.dispose();
throw result.error;
}const reader = new BinaryReader(result.response);
if (!reader.readBoolean()) {
throw new Error('Mint failed');
}
}public async transfer(from: Address, to: Address, amount: bigint): Promise {
const calldata = new BinaryWriter();
calldata.writeAddress(to);
calldata.writeU256(amount);const result = await this.readMethod(
this.transferSelector,
Buffer.from(calldata.getBuffer()),
from,
from,
);if (!result.response) {
this.dispose();
throw result.error;
}const reader = new BinaryReader(result.response);
if (!reader.readBoolean()) {
throw new Error('Transfer failed');
}
}public async balanceOf(owner: Address): Promise {
const calldata = new BinaryWriter();
calldata.writeAddress(owner);const result = await this.readMethod(
this.balanceOfSelector,
Buffer.from(calldata.getBuffer()),
);if (!result.response) {
this.dispose();
throw result.error;
}const reader = new BinaryReader(result.response);
return reader.readU256();
}
}
```### Unit Test Example
Now let's create a unit test for the `SimpleToken` contract. We'll test minting tokens, transferring tokens, and
checking the balance.**File: `/src/tests/simpleTokenTest.ts`**
```typescript
import { opnet, OPNetUnit } from '../opnet/unit/OPNetUnit.js';
import { Assert } from '../opnet/unit/Assert.js';
import { Blockchain } from '../blockchain/Blockchain.js';
import { SimpleToken } from '../contracts/SimpleToken.js';
import { Address } from '@btc-vision/transaction';const decimals = 18;
const totalSupply = 1000000n * (10n ** BigInt(decimals));
const deployer: Address = Blockchain.generateRandomAddress();
const receiver: Address = Blockchain.generateRandomAddress();await opnet('SimpleToken Contract', async (vm: OPNetUnit) => {
let token: SimpleToken;vm.beforeEach(async () => {
Blockchain.dispose();
token = new SimpleToken(deployer, decimals);
Blockchain.register(token);await Blockchain.init();
});vm.afterEach(async () => {
token.dispose();
});await vm.it('should mint tokens correctly', async () => {
await token.mint(receiver, totalSupply);const balance = await token.balanceOf(receiver);
Assert.expect(balance).toEqual(totalSupply);
});await vm.it('should transfer tokens correctly', async () => {
await token.mint(deployer, totalSupply);const transferAmount = 100000n * (10n ** BigInt(decimals));
await token.transfer(deployer, receiver, transferAmount);const balanceDeployer = await token.balanceOf(deployer);
const balanceReceiver = await token.balanceOf(receiver);Assert.expect(balanceDeployer).toEqual(totalSupply - transferAmount);
Assert.expect(balanceReceiver).toEqual(transferAmount);
});await vm.it('should return correct balances', async () => {
await token.mint(receiver, totalSupply);const balance = await token.balanceOf(receiver);
Assert.expect(balance).toEqual(totalSupply);const balanceDeployer = await token.balanceOf(deployer);
Assert.expect(balanceDeployer).toEqual(0n);
});
});
```### Explanation
- **SimpleToken Contract**: This contract implements a simple token with minting, transferring, and balance checking
functions.
- **mint**: Mints tokens to a specified address.
- **transfer**: Transfers tokens from one address to another.
- **balanceOf**: Returns the balance of a specified address.- **simpleTokenTest.ts**: This test suite covers the main functionality of the `SimpleToken` contract.
- **beforeEach**: Initializes a new instance of the `SimpleToken` contract before each test case.
- **afterEach**: Disposes of the contract instance after each test case.
- **Test Cases**:
- **should mint tokens correctly**: Tests that tokens are correctly minted to a given address.
- **should transfer tokens correctly**: Tests that tokens are correctly transferred from one address to another.
- **should return correct balances**: Tests that the balance checking function returns the expected results.## Contributing
Contributions are welcome! To contribute:
1. Fork the repository.
2. Create a new branch (`git checkout -b feature/your-feature`).
3. Commit your changes (`git commit -am 'Add new feature'`).
4. Push to the branch (`git push origin feature/your-feature`).
5. Open a Pull Request.## License
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.