Skip to content

Commit 1fa1312

Browse files
authored
🥑 Add mock contract typing (#818)
1 parent 702c6ab commit 1fa1312

File tree

2 files changed

+18
-9
lines changed

2 files changed

+18
-9
lines changed

‎.changeset/silly-pets-do.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@ethereum-waffle/mock-contract": patch
3+
---
4+
5+
Mock contract typing

‎waffle-mock-contract/src/index.ts

+13-9
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {Contract, ContractFactory, Signer, utils} from 'ethers';
1+
import {BaseContract, Contract, ContractFactory, Signer, utils} from 'ethers';
22
import type {JsonFragment} from '@ethersproject/abi';
33

44
import DoppelgangerContract from './Doppelganger.json';
@@ -13,9 +13,9 @@ interface StubInterface {
1313
withArgs(...args: any[]): StubInterface;
1414
}
1515

16-
export interface MockContract extends Contract {
16+
export interface MockContract<T extends BaseContract = BaseContract> extends Contract {
1717
mock: {
18-
[key: string]: StubInterface;
18+
[key in ((keyof T['functions'] | 'receive'))]: StubInterface;
1919
};
2020
call (contract: Contract, functionName: string, ...params: any[]): Promise<any>;
2121
staticcall (contract: Contract, functionName: string, ...params: any[]): Promise<any>;
@@ -155,7 +155,7 @@ async function deploy(signer: Signer, options?: DeployOptions) {
155155
return factory.deploy();
156156
}
157157

158-
function createMock(abi: ABI, mockContractInstance: Contract) {
158+
function createMock<T extends BaseContract>(abi: ABI, mockContractInstance: Contract): MockContract<T>['mock'] {
159159
const {functions} = new utils.Interface(abi);
160160
const encoder = new utils.AbiCoder();
161161

@@ -166,9 +166,9 @@ function createMock(abi: ABI, mockContractInstance: Contract) {
166166
[func.name]: stubbed,
167167
[func.format()]: stubbed
168168
};
169-
}, {} as MockContract['mock']);
169+
}, {} as MockContract<T>['mock']);
170170

171-
mockedAbi.receive = {
171+
(mockedAbi as any).receive = {
172172
returns: () => { throw new Error('Receive function return is not implemented.'); },
173173
withArgs: () => { throw new Error('Receive function return is not implemented.'); },
174174
reverts: () => mockContractInstance.__waffle__receiveReverts('Mock Revert'),
@@ -178,11 +178,15 @@ function createMock(abi: ABI, mockContractInstance: Contract) {
178178
return mockedAbi;
179179
}
180180

181-
export async function deployMockContract(signer: Signer, abi: ABI, options?: DeployOptions): Promise<MockContract> {
181+
export async function deployMockContract<T extends BaseContract = BaseContract>(
182+
signer: Signer,
183+
abi: ABI,
184+
options?: DeployOptions
185+
): Promise<MockContract<T>> {
182186
const mockContractInstance = await deploy(signer, options);
183187

184-
const mock = createMock(abi, mockContractInstance);
185-
const mockedContract = new Contract(mockContractInstance.address, abi, signer) as MockContract;
188+
const mock = createMock<T>(abi, mockContractInstance);
189+
const mockedContract = new Contract(mockContractInstance.address, abi, signer) as MockContract<T>;
186190
mockedContract.mock = mock;
187191

188192
const encoder = new utils.AbiCoder();

0 commit comments

Comments
 (0)