CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-openzeppelin--test-helpers

JavaScript testing helpers for Ethereum smart contract development with assertions, event verification, balance tracking, and time manipulation.

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

balance-tracking.mddocs/

Balance Tracking

Elegant balance change tracking for Ethereum accounts with support for fee calculation and multiple units. Perfect for testing payment flows and gas cost analysis.

Capabilities

Current Balance

Get the current balance of an Ethereum account in the specified unit.

/**
 * Get the current balance of an account
 * @param {string} account - Ethereum address to check
 * @param {string} unit - Unit for the balance ('wei', 'ether', etc.)
 * @returns {Promise<BN>} - Account balance as BigNumber
 */
async function balance.current(account, unit = 'wei');

Usage Examples:

const { balance, BN } = require('@openzeppelin/test-helpers');

// Get balance in wei (default)
const balanceWei = await balance.current(userAddress);
console.log(balanceWei.toString()); // "1000000000000000000"

// Get balance in ether
const balanceEther = await balance.current(userAddress, 'ether');
console.log(balanceEther.toString()); // "1"

// Compare balances
const expected = new BN('1000000000000000000');
expect(balanceWei).to.be.bignumber.equal(expected);

Balance Tracker

Create a balance tracker for monitoring balance changes over time with fee calculation support.

/**
 * Create a balance tracker for an account
 * @param {string} owner - Ethereum address to track
 * @param {string} unit - Unit for balance tracking ('wei', 'ether', etc.)
 * @returns {Promise<BalanceTracker>} - Balance tracker instance
 */
async function balance.tracker(owner, unit = 'wei');

interface BalanceTracker {
  /**
   * Get the current tracked balance
   * @param {string} unit - Optional unit override
   * @returns {Promise<BN>} - Current balance
   */
  get(unit?): Promise<BN>;
  
  /**
   * Get the balance change since last check
   * @param {string} unit - Optional unit override
   * @returns {Promise<BN>} - Balance delta (positive for increase, negative for decrease)
   */
  delta(unit?): Promise<BN>;
  
  /**
   * Get the balance change and fees paid since last check
   * @param {string} unit - Optional unit override
   * @returns {Promise<{delta: BN, fees: BN}>} - Balance delta and fees paid
   */
  deltaWithFees(unit?): Promise<{ delta: BN, fees: BN }>;
}

Usage Examples:

// Create balance tracker
const tracker = await balance.tracker(userAddress);

// Get initial balance
const initial = await tracker.get();
console.log('Initial balance:', initial.toString());

// Perform some transactions
await token.transfer(recipient, amount, { from: userAddress });
await myContract.someFunction({ from: userAddress });

// Check balance change
const delta = await tracker.delta();
console.log('Balance change:', delta.toString());

// Check balance change with fees
const { delta: balanceDelta, fees } = await tracker.deltaWithFees();
console.log('Balance delta:', balanceDelta.toString());
console.log('Fees paid:', fees.toString());

Advanced Balance Tracking

const { balance, ether, BN } = require('@openzeppelin/test-helpers');

contract('PaymentContract', function ([owner, user, recipient]) {
  it('should track payment and fees correctly', async function () {
    // Create tracker for user
    const userTracker = await balance.tracker(user, 'ether');
    
    // Send payment transaction
    await this.paymentContract.sendPayment(
      recipient,
      ether('0.5'),
      { from: user, value: ether('0.5') }
    );
    
    // Check balance change including gas fees
    const { delta, fees } = await userTracker.deltaWithFees('ether');
    
    // User should have spent 0.5 ether plus gas fees
    expect(delta).to.be.bignumber.equal(new BN('0').sub(new BN('0.5')));
    expect(fees).to.be.bignumber.greaterThan(new BN('0'));
    
    console.log(`Payment: -0.5 ether`);
    console.log(`Gas fees: -${fees.toString()} ether`);
    console.log(`Total spent: ${delta.abs().toString()} ether`);
  });
  
  it('should track multiple transactions', async function () {
    const tracker = await balance.tracker(user);
    
    // Multiple transactions
    await this.contract.function1({ from: user });
    const delta1 = await tracker.delta();
    
    await this.contract.function2({ from: user });
    const delta2 = await tracker.delta();
    
    await this.contract.function3({ from: user });  
    const delta3 = await tracker.delta();
    
    console.log('Transaction 1 cost:', delta1.toString());
    console.log('Transaction 2 cost:', delta2.toString());
    console.log('Transaction 3 cost:', delta3.toString());
  });
});

Unit Support

Balance tracking supports all web3.js units:

  • 'wei' (default)
  • 'kwei' / 'babbage' / 'femtoether'
  • 'mwei' / 'lovelace' / 'picoether'
  • 'gwei' / 'shannon' / 'nanoether' / 'nano'
  • 'szabo' / 'microether' / 'micro'
  • 'finney' / 'milliether' / 'milli'
  • 'ether'
  • 'kether' / 'grand'
  • 'mether'
  • 'gether'
  • 'tether'

Fee Calculation

The deltaWithFees method calculates gas fees by:

  1. Tracking block numbers between balance checks
  2. Examining all transactions in intermediate blocks
  3. Identifying transactions sent from the tracked account
  4. Calculating gasUsed * gasPrice for each transaction
  5. Summing total fees paid

Note: Fee calculation requires access to transaction receipts and may be slow for accounts with many transactions.

Error Handling

// Handle insufficient balance scenarios
try {
  const delta = await tracker.delta();
  if (delta.isNeg()) {
    console.log('Account spent:', delta.abs().toString(), 'wei');
  }
} catch (error) {
  console.error('Balance tracking failed:', error.message);
}

Install with Tessl CLI

npx tessl i tessl/npm-openzeppelin--test-helpers

docs

advanced-features.md

balance-tracking.md

constants-utilities.md

event-testing.md

index.md

revert-testing.md

time-manipulation.md

tile.json