question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Feature to add a Contracts object to typechain

See original GitHub issue

So it’s a bit of a pain to use the lib as is with hardhat.

First I need to get the SystemFactory, then cast it, then deploy the contract from it. In order to avoid that I developed something that makes it easier.

And instead of doing that:

systemF = (await ethers.getContractFactory('System')) as System__factory;
system = await systemF.deploy();

You can directly do:

import Contracts from "./ContractsHelper"

system = await Contracts.System.deploy();

With full types.

Here is how I did it:

let contractStore: { [key: string]: ContractFactory } = {};

const deployContract = async <ParamsTypes extends typeof ContractFactory.prototype.deploy, T extends Promise<Contract>>(
    contractName: string,
    argsNumber: number,
    args: Parameters<ParamsTypes>
): Promise<T> => {
    let signer: SignerWithAddress = (await ethers.getSigners())[0];

    // If full arguments then last arg is override
    if (argsNumber == args.length) {
        let overrides = args.pop();
        if (overrides != {} && overrides.from) {
            signer = await ethers.getSigner(overrides.from);
        }
    }

    let signerAddress = await signer.getAddress();
    if (contractStore[contractName + signerAddress] === undefined) {
        contractStore[contractName + signerAddress] = await ethers.getContractFactory(contractName, signer);
    }

    return args === undefined || args.length === 0
        ? await contractStore[contractName + signerAddress].deploy()
        : await contractStore[contractName + signerAddress].deploy(...args);
};

const attachContract = async <T extends Promise<Contract>>(
    contractName: string,
    address: string,
    signer?: SignerWithAddress
): Promise<T> => {
    return await ethers.getContractAt(contractName, address, signer);
};

const deployOrAttach = <T extends Contract, ParamsTypes extends typeof ContractFactory.prototype.deploy>(
    contractName: string,
    argsNumber: number
) => {
    return {
        deploy: async (...parameters: Parameters<ParamsTypes>): Promise<T> => {
            return await deployContract<ParamsTypes, Promise<T>>(contractName, argsNumber, parameters);
        },
        attach: async (address: string, signer?: SignerWithAddress): Promise<T> => {
            return await attachContract<Promise<T>>(contractName, address, signer);
        }
    };
};

export default {
    myContract: deployOrAttach<Contract, typeof ContractFactory.prototype.deploy>(
        'myContract',
        ContractFactory.prototype.deploy.length
    ),
}

Allowing anyone to do:

import Contracts from "./ContractsHelper";

// Normal deploy with default signer
contract = Contracts.myContract.deploy();

// Normal deploy with custom signer
contract = Contracts.myContract.deploy({ from: accounts[1].address });

Indeed, everything is typed.

I think that could be inserted as a part of the typechain build. What’s your thoughts ? It would make things easier imo

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:20 (13 by maintainers)

github_iconTop GitHub Comments

3reactions
alcuadradocommented, Apr 13, 2021

Ok, I found a way of doing it! This is gonna be so cool!

Here’s an example:

// file: mod.ts -- A mock up of our ethers helpers module

export abstract class Base {}

export class Child extends Base {
  public f() {
    return 1;
  }
}

export interface E {
  getContract(a: string): Base;
}

export function createE(): E {
  return {
    getContract(c: string) {
      if (c === "Child") {
        return new Child();
      }

      throw new Error("Not found " + c);
    },
  };
}
// file: overloads.ts -- this would be a typechain generated module
import { Child } from "./mod";

declare module "./mod" {
  interface E {
    getContract(a: "Child"): Child;
  }
}
// file: a.ts -- This is a file that uses it.
import { createE } from "./mod";

const e = createE();
const c = e.getContract("Child");
console.log(c.f()); // typed as Child

const d = e.getContract("A"); // typed as Base, but in reality it throws.
2reactions
krzkaczorcommented, Apr 29, 2021

Yes, this should be out today. ethers.getContractFactory(name) returns concrete factory type 🥳 If you want to test it (which I would really appreciate):

Please checkout: https://github.com/ethereum-ts/TypeChain/pull/363

Build it:

yarn 
yarn build

and then link packages locally

cd packages/typechain
yarn link

do the same for hardhat and ethers-v5 packages.

Finally, in the project that you want to test: yarn link typechain (and do the same for hardhat and ethers-v5) and you will use your local packages.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Feature to add a Contracts object to typechain #370 - GitHub
First I need to get the SystemFactory, then cast it, then deploy the contract from it. In order to avoid that I developed...
Read more >
@typechain/hardhat - npm
Automatically generate TypeScript bindings for smartcontracts while using Hardhat. Installation. If you use Ethers/Waffle do: npm install --save ...
Read more >
hardhat-typechain | Yarn - Package Manager
Add Typechain tasks to your hardhat project! What. TypeChain gives you Typescript bindings for your smart contracts. Now, your tests and frontend code...
Read more >
How to deploy your first smart contract on Ethereum with ...
Typechain GitHub Repository. Let's do it. yarn add --dev typechain @typechain/hardhat @typechain/ethers-v5. Add these imports to your Hardhat ...
Read more >
Strong Types With Typescript - useDApp
When using typescript, you can generate types for the contracts you use and take advantage of type checking in your code. Typechain usage​....
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found