Skip to content

Commit db98630

Browse files
Merge pull request #6442 from NomicFoundation/add-attach-support-in-hh-typechain
[Typechain] Investigate how to support the attach method
2 parents 640754b + 8f2403d commit db98630

File tree

3 files changed

+74
-9
lines changed

3 files changed

+74
-9
lines changed

.changeset/small-buckets-ring.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@nomicfoundation/hardhat-typechain": patch
3+
---
4+
5+
Added support for the `attach` method in `hardhat-typechain`.

v-next/hardhat-typechain/src/internal/generate-types.ts

+44
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,8 @@ function addCompiledFilesTransformerIfAbsent(
110110
'declare module "@nomicfoundation/hardhat-ethers/types"',
111111
);
112112

113+
modifiedContent = addSupportForAttachMethod(modifiedContent);
114+
113115
return modifiedContent;
114116
};
115117

@@ -140,3 +142,45 @@ export function addJsExtensionsIfNeeded(content: string): string {
140142
`import ${imports} from ${quote}${path}/index.js${quote};`,
141143
);
142144
}
145+
146+
// We expect the structure of the factory files to be:
147+
// /* eslint-disable */
148+
// ...
149+
// export class [contractName]__factory extends ContractFactory {
150+
// ...
151+
// static connect(
152+
// ...
153+
// }
154+
function addSupportForAttachMethod(modifiedContent: string): string {
155+
const pattern = /class\s+(\w+)__factory/; // Pattern to find the contract name in factory files
156+
const match = modifiedContent.match(pattern);
157+
158+
if (match === null) {
159+
// File is not a factory file, so there is no need to modify it
160+
return modifiedContent;
161+
}
162+
163+
const contractName = match[1];
164+
165+
// Insert the "attach" snippet right before the "connect" method
166+
const insertPoint = modifiedContent.lastIndexOf("static connect(");
167+
168+
const attachMethod = `
169+
override attach(address: string | Addressable): ${contractName} {
170+
return super.attach(address) as ${contractName};
171+
}
172+
`;
173+
174+
modifiedContent =
175+
modifiedContent.slice(0, insertPoint) +
176+
attachMethod +
177+
modifiedContent.slice(insertPoint);
178+
179+
// Import the "Addressable" type as it is required by the "attach" method
180+
modifiedContent = modifiedContent.replace(
181+
"/* eslint-disable */",
182+
'/* eslint-disable */\nimport type { Addressable } from "ethers";',
183+
);
184+
185+
return modifiedContent;
186+
}

v-next/hardhat-typechain/test/index.ts

+25-9
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,6 @@ describe("hardhat-typechain", () => {
1818

1919
before(async () => {
2020
await remove(`${process.cwd()}/types`);
21-
});
22-
23-
it("should generate the types", async () => {
24-
// Check that the types are generated with the expected addition of the "/index.js" extensions
25-
// and the v3 modules
2621

2722
const hardhatConfig = await import(
2823
// eslint-disable-next-line import/no-relative-packages -- allow for fixture projects
@@ -36,6 +31,11 @@ describe("hardhat-typechain", () => {
3631
await hre.tasks.getTask("clean").run();
3732

3833
await hre.tasks.getTask("compile").run();
34+
});
35+
36+
it("should generate the types for the `hardhat.d.ts` file", async () => {
37+
// Check that the types are generated with the expected addition of the "/index.js" extensions
38+
// and the v3 modules
3939

4040
const content = await readUtf8File(
4141
path.join(process.cwd(), "types", "ethers-contracts", "hardhat.d.ts"),
@@ -63,12 +63,28 @@ describe("hardhat-typechain", () => {
6363

6464
// The import from a npm package should have ".js" extensions
6565
assert.equal(content.includes(`import { ethers } from 'ethers'`), true);
66+
});
6667

67-
// Check that the types for the contract are generated
68-
assert.equal(
69-
await exists(
70-
`${process.cwd()}/types/ethers-contracts/factories/A__factory.ts`,
68+
it("should generated types for the contracts and add the support for the `attach` method", async () => {
69+
const content = await readUtf8File(
70+
path.join(
71+
process.cwd(),
72+
"types",
73+
"ethers-contracts",
74+
"factories",
75+
"A__factory.ts",
7176
),
77+
);
78+
79+
// The "Addressable" type should be imported
80+
assert.equal(
81+
content.includes(`import type { Addressable } from "ethers";`),
82+
true,
83+
);
84+
85+
// The "attach" method should be added to the factory
86+
assert.equal(
87+
content.includes(`override attach(address: string | Addressable): A {`),
7288
true,
7389
);
7490
});

0 commit comments

Comments
 (0)