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

nestjs-ethers

v2.2.0

Published

The ethers.js library for NestJS

Downloads

2,583

Readme

NestJS-Ethers

npm CircleCI Coverage Status vulnerabilities CodeQL supported platforms

Ethereum utilities for NestJS based on Ethers.js

Install

npm i nestjs-ethers

Register module

Zero configuration

Just import EthersModule to your module:

import { EthersModule } from 'nestjs-ethers';

@Module({
  imports: [EthersModule.forRoot()],
  ...
})
class MyModule {}

NOTE: By default EthersModule will try to connect using getDefaultProvider. It's the safest, easiest way to begin developing on Ethereum. It creates a FallbackProvider connected to as many backend services as possible.

Configuration params

nestjs-ethers can be configured with this options:

interface EthersModuleOptions {
  /**
   * Optional parameter for connection, can be a Network object
   * or the name of a common network as a string (e.g. "homestead")
   * If no network is provided, homestead (i.e. mainnet) is used.
   * The network may also be a URL to connect to,
   * such as http://localhost:8545 or wss://example.com.
   * @see {@link https://docs.ethers.io/v5/api/providers/types/#providers-Networkish}
   */
  network?: Network | string;

  /**
   * Optional parameter for Alchemy API Token
   * @see {@link https://alchemyapi.io}
   */
  alchemy?: string;

  /**
   * Optional parameter for Etherscan API Token
   * @see {@link https://etherscan.io}
   */
  etherscan?: string;
  
  /**
   * Optional parameter for Bscscan API Token
   * @see {@link https://bscscan.com/}
   */
  bscscan?: string;

  /**
   * Optional parameter for use Cloudflare Provider
   * @see {@link https://cloudflare-eth.com}
   */
  cloudflare?: boolean;

  /**
   * Optional parameter for Infura Project ID
   * or InfuraProviderOptions(applicationId, applicationSecretKey)
   * @see {@link https://infura.io}
   */
  infura?: InfuraProviderOptions | string;

  /**
   * Optional parameter for Pocket Network Application ID
   * or PocketProviderOptions(projectId, projectSecret)
   * @see {@link https://pokt.network}
   */
  pocket?: PocketProviderOptions | string;
  
  /**
   * Optional parameter for Moralis API Token
   * or MoralisProviderOptions(apiKey, region)
   * @see {@link https://moralis.io/}
   */
  moralis?: MoralisProviderOptions | string;
  
  /**
   * Optional parameter for Ankr API Token
   * or AnkrProviderOptions(apiKey, projectSecret)
   * @see {@link https://www.ankr.com/}
   */
  ankr?: AnkrProviderOptions | string;
  
  /**
   * Optional parameter for a custom StaticJsonRpcProvider
   * You can connect using an URL, ConnectionInfo or an array of both.
   * @see {@link https://docs.ethers.io/v5/api/providers/jsonrpc-provider/#StaticJsonRpcProvider}
   * @ses {@link https://docs.ethers.io/v5/api/utils/web/#ConnectionInfo}
   */
  custom?: ConnectionInfo | string | (ConnectionInfo | string)[]

  /**
   * Optional parameter the number of backends that must agree
   * (default: 2 for mainnet, 1 for testnets)
   */
  quorum?: number;

  /**
   * Optional parameter if this option is false, EthersModule won't wait until
   * the providers are ready. If this option is true, EthersModule  will wait 
   * until the network has heen established for all the providers.
   * @see {@link https://docs.ethers.io/v5/api/providers/provider/#Provider-ready}
   */
  waitUntilIsConnected?: boolean;

  /**
   * Optional parameter if this option is false, EthersModule will try to connect
   * with the credentials provided in options. If you define more than one provider,
   * EthersModule will use the FallbackProvider to send multiple requests simultaneously.
   */
  useDefaultProvider?: boolean;

  /**
   * Optional parameter if this option is true, EthersModule will disable 
   * the console.log in the ethers.js library.
   */
  disableEthersLogger?: boolean
  
  /**
   * Optional parameter to associate a token name to EthersProvider,
   * the token is used to request an instance of a class by the same name.
   * This can be useful when you want multiple intances of EthersProvider.
   */
  token?: string;
}

Synchronous configuration

Use EthersModule.forRoot method with Options interface:

import { EthersModule, RINKEBY_NETWORK } from 'nestjs-ethers';

@Module({
  imports: [
    EthersModule.forRoot({
      network: RINKEBY_NETWORK,
      alchemy: '845ce4ed0120d68eb5740c9160f08f98',
      etherscan: 'e8cce313c1cfbd085f68be509451f1bab8',
      cloudflare: true,
      infura: {
        projectId: 'd71b3d93c2fcfa7cab4924e63298575a',
        projectSecret: 'ed6baa9f7a09877998a24394a12bf3dc',
      },
      pocket: {
        applicationId: '9b0afc55221c429104d04ef9',
        applicationSecretKey: 'b5e6d6a55426712a42a93f39555973fc',
      },
      quorum: 1,
      useDefaultProvider: true,
    })
  ],
  ...
})
class MyModule {}

Asynchronous configuration

With EthersModule.forRootAsync you can, for example, import your ConfigModule and inject ConfigService to use it in useFactory method.

useFactory should return object with Options interface or undefined

Here's an example:

import { EthersModule, RINKEBY_NETWORK } from 'nestjs-ethers';

@Injectable()
class ConfigService {
  public readonly infura = {
    projectId: 'd71b3d93c2fcfa7cab4924e63298575a',
    projectSecret: 'ed6baa9f7a09877998a24394a12bf3dc',
  };
}

@Module({
  providers: [ConfigService],
  exports: [ConfigService]
})
class ConfigModule {}

@Module({
  imports: [
    EthersModule.forRootAsync({
      imports: [ConfigModule],
      inject: [ConfigService],
      useFactory: async (config: ConfigService) => {
        await somePromise();
        return {
          network: RINKEBY_NETWORK,
          infura: config.infura,
          useDefaultProvider: false,
        };
      }
    })
  ],
  ...
})
class TestModule {}

Or you can just pass ConfigService to providers, if you don't have any ConfigModule:

import { EthersModule, RINKEBY_NETWORK } from 'nestjs-ethers';

@Injectable()
class ConfigService {
  public readonly pocket: {
    applicationId: '9b0afc55221c429104d04ef9',
    applicationSecretKey: 'b5e6d6a55426712a42a93f39555973fc',
  };
}

@Module({
  imports: [
    EthersModule.forRootAsync({
      providers: [ConfigService],
      inject: [ConfigService],
      useFactory: (config: ConfigService) => {
        return {
          network: RINKEBY_NETWORK,
          pocket: config.pocket,
          useDefaultProvider: false,
        };
      }
    })
  ],
  controllers: [TestController]
})
class TestModule {}

You can also pass multiple ethersjs configs, if you want to use the FallbackProvider to send multiple requests simultaneously:

import { EthersModule, RINKEBY_NETWORK } from 'nestjs-ethers';

@Injectable()
class ConfigService {
  public readonly infura = {
    projectId: 'd71b3d93c2fcfa7cab4924e63298575a',
    projectSecret: 'ed6baa9f7a09877998a24394a12bf3dc',
  };
  public readonly pocket: {
    applicationId: '9b0afc55221c429104d04ef9',
    applicationSecretKey: 'b5e6d6a55426712a42a93f39555973fc',
  };
}

@Module({
  providers: [ConfigService],
  exports: [ConfigService]
})
class ConfigModule {}

@Module({
  imports: [
    EthersModule.forRootAsync({
      imports: [ConfigModule],
      inject: [ConfigService],
      useFactory: async (config: ConfigService) => {
        await somePromise();
        return {
          network: RINKEBY_NETWORK,
          infura: config.infura,
          pocket: config.pocket,
          useDefaultProvider: false,
        };
      }
    })
  ],
  ...
})
class TestModule {}

BaseProvider

BaseProvider implements standard Ether.js Provider. So if you are familiar with it, you are ready to go.

import { InjectEthersProvider, BaseProvider } from 'nestjs-ethers';

@Injectable()
export class TestService {
  constructor(
    @InjectEthersProvider()
    private readonly ethersProvider: BaseProvider,
  ) {}
  async someMethod(): Promise<Network> {
    return this.ethersProvider.getNetwork();
  }
}

Binance Smart Chain Provider

if you are familiar with BscscanProvider, you are ready to go.

import {
  EthersModule,
  InjectEthersProvider,
  BscscanProvider,
  BINANCE_NETWORK
} from 'nestjs-ethers';

@Module({
  imports: [
    EthersModule.forRoot({
      network: BINANCE_NETWORK,
      bscscan: '845ce4ed0120d68eb5740c9160f08f98',
      useDefaultProvider: false,
    })
  ],
  ...
})
class MyModule {}

@Controller('/')
class TestController {
  constructor(
    @InjectEthersProvider()
    private readonly bscProvider: BscscanProvider,
  ) {}
  @Get()
  async get() {
    const gasPrice: BigNumber = await this.bscProvider.getGasPrice()

    return { gasPrice: gasPrice.toString() }
  }
}

Binance Smart Chain Default Provider

This will create a FallbackProvider, backed by all popular Third-Party BSC services (currently only BscscanProvider).

NOTE: if bscscan is null or undefined. The BSC default provider will use the community API Key.

import {
  EthersModule,
  InjectEthersProvider,
  FallbackProvider,
  BINANCE_NETWORK
} from 'nestjs-ethers';

@Module({
  imports: [
    EthersModule.forRoot({
      network: BINANCE_NETWORK,
      useDefaultProvider: true,
    })
  ],
  ...
})
class MyModule {}

@Controller('/')
class TestController {
  constructor(
    @InjectEthersProvider()
    private readonly bscProvider: FallbackProvider,
  ) {}
  @Get()
  async get() {
    const gasPrice: BigNumber = await this.bscProvider.getGasPrice()

    return { gasPrice: gasPrice.toString() }
  }
}

Custom StaticJsonRpcProvider

if you are familiar with StaticJsonRpcProvider, you are ready to go. The custom provider is very helpful when you want to use a RPC that is not defined in ethers. This is the case for Binance Smart Chain public RPCs.

import {
  EthersModule,
  InjectEthersProvider,
  StaticJsonRpcProvider,
  BNB_TESTNET_NETWORK
} from 'nestjs-ethers';

@Module({
  imports: [
    EthersModule.forRoot({
      network: BNB_TESTNET_NETWORK,
      custom: 'https://data-seed-prebsc-1-s1.binance.org:8545',
      useDefaultProvider: false,
    })
  ],
  ...
})
class MyModule {}

@Controller('/')
class TestController {
  constructor(
    @InjectEthersProvider()
    private readonly customProvider: StaticJsonRpcProvider,
  ) {}
  @Get()
  async get() {
    const gasPrice: BigNumber = await this.customProvider.getGasPrice()

    return { gasPrice: gasPrice.toString() }
  }
}

You can also pass multiple custom providers, if you want to use the FallbackProvider to send multiple requests simultaneously:

import {
  EthersModule,
  InjectEthersProvider,
  FallbackProvider,
  BNB_TESTNET_NETWORK
} from 'nestjs-ethers';

@Module({
  imports: [
    EthersModule.forRoot({
      network: BNB_TESTNET_NETWORK,
      custom: [
        'https://data-seed-prebsc-1-s1.binance.org:8545',
        'https://data-seed-prebsc-1-s3.binance.org:8545',
        'https://data-seed-prebsc-2-s2.binance.org:8545'
      ],
      useDefaultProvider: false,
    })
  ],
  ...
})
class MyModule {}

@Controller('/')
class TestController {
  constructor(
    @InjectEthersProvider()
    private readonly customProvider: FallbackProvider,
  ) {}
  @Get()
  async get() {
    const gasPrice: BigNumber = await this.customProvider.getGasPrice()

    return { gasPrice: gasPrice.toString() }
  }
}

EthersSigner

EthersSigner implements methods to create a Wallet or VoidSigner. A Signer in ethers is an abstraction of an Ethereum Account, which can be used to sign messages and transactions and send signed transactions to the Ethereum Network. This service will also inject the BaseProvider into the wallet.

Create a Wallet from a private key:

import { EthersSigner, InjectSignerProvider, Wallet } from 'nestjs-ethers';

@Injectable()
export class TestService {
  constructor(
    @InjectSignerProvider()
    private readonly ethersSigner: EthersSigner,
  ) {}
  async someMethod(): Promise<string> {
    const wallet: Wallet = this.ethersSigner.createWallet(
      '0x4c94faa2c558a998d10ee8b2b9b8eb1fbcb8a6ac5fd085c6f95535604fc1bffb'
    );

    return wallet.getAddress();
  }
}

Create a random Wallet:

import { EthersSigner, InjectSignerProvider, Wallet } from 'nestjs-ethers';

@Injectable()
export class TestService {
  constructor(
    @InjectSignerProvider()
    private readonly ethersSigner: EthersSigner,
  ) {}
  async someMethod(): Promise<string> {
    const wallet: Wallet = this.ethersSigner.createRandomWallet();

    return wallet.getAddress();
  }
}

Create a Wallet from an encrypted JSON:

import { EthersSigner, InjectSignerProvider, Wallet } from 'nestjs-ethers';

@Injectable()
export class TestService {
  constructor(
    @InjectSignerProvider()
    private readonly ethersSigner: EthersSigner,
  ) {}
  async someMethod(): Promise<string> {
    const wallet: Wallet = this.ethersSigner.createWalletFromEncryptedJson(
      {
        address: '012363d61bdc53d0290a0f25e9c89f8257550fb8',
        id: '5ba8719b-faf9-49ec-8bca-21522e3d56dc',
        version: 3,
        Crypto: {
          cipher: 'aes-128-ctr',
          cipherparams: { iv: 'bc0473d60284d2d6994bb6793e916d06' },
          ciphertext:
            'e73ed0b0c53bcaea4516a15faba3f6d76dbe71b9b46a460ed7e04a68e0867dd7',
          kdf: 'scrypt',
          kdfparams: {
            salt: '97f0b6e17c392f76a726ceea02bac98f17265f1aa5cf8f9ad1c2b56025bc4714',
            n: 131072,
            dklen: 32,
            p: 1,
            r: 8,
          },
          mac: 'ff4f2db7e7588f8dd41374d7b98dfd7746b554c0099a6c0765be7b1c7913e1f3',
        },
        'x-ethers': {
          client: 'ethers.js',
          gethFilename: 'UTC--2018-01-27T01-52-22.0Z--012363d61bdc53d0290a0f25e9c89f8257550fb8',
          mnemonicCounter: '70224accc00e35328a010a19fef51121',
          mnemonicCiphertext: 'cf835e13e4f90b190052263dbd24b020',
          version: '0.1',
        },
      },
      'password'
    );

    return wallet.getAddress();
  }
}

Create a Wallet from a mnemonic:

import { EthersSigner, InjectSignerProvider, Wallet } from 'nestjs-ethers';

@Injectable()
export class TestService {
  constructor(
    @InjectSignerProvider()
    private readonly ethersSigner: EthersSigner,
  ) {}
  async someMethod(): Promise<string> {
    const wallet: Wallet = this.ethersSigner.createWalletfromMnemonic(
      'service basket parent alcohol fault similar survey twelve hockey cloud walk panel'
    );

    return wallet.getAddress();
  }
}

Create a [VoidSigner](https://docs.ethers.io/v5/api/signer/ from an address:

import { EthersSigner, InjectSignerProvider, VoidSigner } from 'nestjs-ethers';

@Injectable()
export class TestService {
  constructor(
    @InjectSignerProvider()
    private readonly ethersSigner: EthersSigner,
  ) {}
  async someMethod(): Promise<string> {
    const wallet: VoidSigner = this.ethersSigner.createVoidSigner(
      '0x012363d61bdc53d0290a0f25e9c89f8257550fb8'
    );

    return wallet.getAddress();
  }
}

EthersContract

EthersContract implements a method for the creation of a Contract instance. This service will also inject the a BaseProvider into the contract.

Create a SmartContract attached to an address:

import { EthersContract, InjectContractProvider, Contract, Network } from 'nestjs-ethers';
import * as ABI from './utils/ABI.json';

@Injectable()
class TestService {
  constructor(
    @InjectContractProvider()
    private readonly ethersContract: EthersContract,
  ) {}
  async someMethod(): Promise<Network> {
    const contract: Contract = this.ethersContract.create(
      '0x012363d61bdc53d0290a0f25e9c89f8257550fb8',
      ABI,
    );

    return contract.provider.getNetwork();
  }
}

Create a Contract with a Wallet:

import {
  EthersContract,
  EthersSigner,
  InjectContractProvider,
  InjectSignerProvider,
  Contract,
  Network,
  Wallet
} from 'nestjs-ethers';
import * as ABI from './utils/ABI.json';

@Injectable()
class TestService {
  constructor(
    @InjectContractProvider()
    private readonly ethersContract: EthersContract,
    @InjectSignerProvider()
    private readonly ethersSigner: EthersSigner,
  ) {}
  async someMethod(): Promise<Network> {
    const wallet: Wallet = this.ethersSigner.createWallet(
      '0x4c94faa2c558a998d10ee8b2b9b8eb1fbcb8a6ac5fd085c6f95535604fc1bffb'
    );
    const contract: Contract = this.ethersContract.create(
      '0x012363d61bdc53d0290a0f25e9c89f8257550fb8',
      ABI,
      wallet,
    );

    return contract.signer.provider.getNetwork();
  }
}

Multichain mode

You can use the token property to use multiple instances of Ethers. This can be helpful when you want to connect with more than one EVN compatible chain like BSC, Polygon or Fantom.

If you know what you're doing, you can enable it like so:

Synchronous

import { Module, Controller, Get } from '@nestjs/common'
import {
  EthersModule,
  InjectEthersProvider,
  InjectEthersProvider,
  InjectEthersProvider,
  PocketProvider,
  AlchemyProvider,
  StaticJsonRpcProvider,
  BigNumber,
  RINKEBY_NETWORK,
  MUMBAI_NETWORK,
  BNB_TESTNET_NETWORK,
} from 'nestjs-ethers';

@Controller('/')
class TestController {
  constructor(
    @InjectEthersProvider('eth')
    private readonly pocketProvider: PocketProvider,
    @InjectEthersProvider('poly')
    private readonly alchemyProvider: AlchemyProvider,
    @InjectEthersProvider('bsc')
    private readonly customProvider: StaticJsonRpcProvider,
  ) {}
  @Get()
  async get() {
    const pocketGasPrice: BigNumber = await this.pocketProvider.getGasPrice()
    const alchemyGasPrice: BigNumber = await this.alchemyProvider.getGasPrice()
    const bscGasPrice: BigNumber = await this.customProvider.getGasPrice()

    return {
      pocketGasPrice: pocketGasPrice.toString(),
      alchemyGasPrice: alchemyGasPrice.toString(),
      bscGasPrice: bscGasPrice.toString(),
    }
  }
}

@Module({
  imports: [
    EthersModule.forRoot({
      token: 'eth',
      network: RINKEBY_NETWORK,
      pocket: {
        applicationId: '9b0afc55221c429104d04ef9',
        applicationSecretKey: 'b5e6d6a55426712a42a93f39555973fc',
      },
      useDefaultProvider: false,
    }),
    EthersModule.forRoot({
      token: 'poly',
      network: MUMBAI_NETWORK,
      alchemy: '845ce4ed0120d68eb5740c9160f08f98',
      useDefaultProvider: false,
    }),
    EthersModule.forRoot({
      token: 'bsc',
      network: BNB_TESTNET_NETWORK,
      custom: 'https://data-seed-prebsc-1-s1.binance.org:8545',
      useDefaultProvider: false,
    }),
  ],
  controllers: [TestController],
})
class TestModule {}

Asynchronous configuration

import { Module, Controller, Get } from '@nestjs/common'
import {
  EthersModule,
  InjectEthersProvider,
  InjectEthersProvider,
  InjectEthersProvider,
  PocketProvider,
  AlchemyProvider,
  StaticJsonRpcProvider,
  BigNumber,
  RINKEBY_NETWORK,
  MUMBAI_NETWORK,
  BNB_TESTNET_NETWORK,
} from 'nestjs-ethers';

@Controller('/')
class TestController {
  constructor(
    @InjectEthersProvider('eth')
    private readonly pocketProvider: PocketProvider,
    @InjectEthersProvider('poly')
    private readonly alchemyProvider: AlchemyProvider,
    @InjectEthersProvider('bsc')
    private readonly customProvider: StaticJsonRpcProvider,
  ) {}
  @Get()
  async get() {
    const pocketGasPrice: BigNumber = await this.pocketProvider.getGasPrice()
    const alchemyGasPrice: BigNumber = await this.alchemyProvider.getGasPrice()
    const bscGasPrice: BigNumber = await this.customProvider.getGasPrice()

    return {
      pocketGasPrice: pocketGasPrice.toString(),
      alchemyGasPrice: alchemyGasPrice.toString(),
      bscGasPrice: bscGasPrice.toString(),
    }
  }
}

@Injectable()
class ConfigService {
  public readonly applicationId: '9b0afc55221c429104d04ef9'
  public readonly applicationSecretKey: 'b5e6d6a55426712a42a93f39555973fc'
  public readonly alchemy: '845ce4ed0120d68eb5740c9160f08f98'
  public readonly custom: 'https://data-seed-prebsc-1-s1.binance.org:8545'
}

@Module({
  providers: [ConfigService],
  exports: [ConfigService],
})
class ConfigModule {}

@Module({
  imports: [
    EthersModule.forRootAsync({
      imports: [ConfigModule],
      inject: [ConfigService],
      token: 'eth',
      useFactory: (config: ConfigService) => {
        return {
          network: RINKEBY_NETWORK,
          pocket: {
            applicationId: config.applicationId,
            applicationSecretKey: config.applicationSecretKey,
          },
          useDefaultProvider: false,
        }
      },
    }),
    EthersModule.forRootAsync({
      imports: [ConfigModule],
      inject: [ConfigService],
      token: 'poly',
      useFactory: (config: ConfigService) => {
        return {
          network: MUMBAI_NETWORK,
          alchemy: config.alchemy,
          useDefaultProvider: false,
        }
      },
    }),
    EthersModule.forRootAsync({
      imports: [ConfigModule],
      inject: [ConfigService],
      token: 'bsc',
      useFactory: (config: ConfigService) => {
        return {
          network: BNB_TESTNET_NETWORK,
          custom: config.custom,
          useDefaultProvider: false,
        }
      },
    }),
  ],
  controllers: [TestController],
})
class TestModule {}

Testing a class that uses InjectEthersProvider

This package exposes a getEthersToken(token?: string) function that returns a prepared injection token based on the provided context. Using this token, you can easily provide a mock implementation of the BaseProvider using any of the standard custom provider techniques, including useClass, useValue, and useFactory.

  const module: TestingModule = await Test.createTestingModule({
    providers: [
      MyService,
      {
        provide: getEthersToken(MyService.name),
        useValue: mockProvider,
      },
    ],
  }).compile();

Testing a class that uses InjectContractProvider

This package exposes a getContractToken(token?: string) function that returns a prepared injection token based on the contract provided context. Using this token, you can easily provide a mock implementation of the ethers.Contract using any of the standard custom provider techniques, including useClass, useValue, and useFactory.

  const module: TestingModule = await Test.createTestingModule({
    providers: [
      MyService,
      {
        provide: getContractToken(MyService.name),
        useValue: mockContractProvider,
      },
    ],
  }).compile();

Testing a class that uses InjectSignerProvider

This package exposes a getSignerToken(token?: string) function that returns a prepared injection token based on the signer provided context. Using this token, you can easily provide a mock implementation of the ethers.Signer using any of the standard custom provider techniques, including useClass, useValue, and useFactory.

  const module: TestingModule = await Test.createTestingModule({
    providers: [
      MyService,
      {
        provide: getSignerToken(MyService.name),
        useValue: mockSignerProvider,
      },
    ],
  }).compile();

Migration

v1

  • SmartContract was renamed to Contract
  • EthersBaseProvider was renamed to BaseProvider
  • SmartContractInterface was renamed to ContractInterface
  • WalletSigner was renamed to Wallet
  • SmartContractFactory was renamed to ContractFactory
  • RandomWalletSignerOptions was renamed to RandomWalletOptions

A new more convenient way to inject the EthersSigner and EthersContract providers into a service or controller was add it.

EthersSigner

// v0
import { EthersSigner, WalletSigner } from 'nestjs-ethers';

@Injectable()
export class TestService {
  constructor(private readonly ethersSigner: EthersSigner) {}
  async someMethod(): Promise<string> {
    const wallet: WalletSigner = this.ethersSigner.createWallet(
      '0x4c94faa2c558a998d10ee8b2b9b8eb1fbcb8a6ac5fd085c6f95535604fc1bffb'
    );

    return wallet.getAddress();
  }
}

// v1
import { EthersSigner, InjectSignerProvider, Wallet } from 'nestjs-ethers';

@Injectable()
export class TestService {
  constructor(
    @InjectSignerProvider()
    private readonly ethersSigner: EthersSigner,
  ) {}
  async someMethod(): Promise<string> {
    const wallet: Wallet = this.ethersSigner
    .createWallet(
      '0x4c94faa2c558a998d10ee8b2b9b8eb1fbcb8a6ac5fd085c6f95535604fc1bffb'
    );

    return wallet.getAddress();
  }
}

EthersContract

// v0
import { EthersContract, SmartContract } from 'nestjs-ethers';
import * as ABI from './utils/ABI.json';

@Injectable()
class TestService {
  constructor(private readonly ethersContract: EthersContract) {}
  async someMethod(): Promise<string> {
    const contract: SmartContract = this.ethersContract.create(
      '0x012363d61bdc53d0290a0f25e9c89f8257550fb8',
      ABI,
    );

    return contract.provider.getNetwork();
  }
}

// v1
import { EthersContract, InjectContractProvider, Contract, Network } from 'nestjs-ethers';
import * as ABI from './utils/ABI.json';

@Injectable()
class TestService {
  constructor(
    @InjectContractProvider()
    private readonly contract: EthersContract,
  ) {}
  async someMethod(): Promise<Network> {
    const contract: Contract = this.ethersContract.create(
      '0x012363d61bdc53d0290a0f25e9c89f8257550fb8',
      ABI,
    );

    return contract.provider.getNetwork();
  }
}

Change Log

See Changelog for more information.

Contributing

Contributions welcome! See Contributing.

Collaborators

License

Licensed under the Apache 2.0 - see the LICENSE file for details.