@openzeppelin/wizard 0.10.4 → 0.10.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/dist/common-options.js +1 -1
  2. package/dist/common-options.js.map +1 -1
  3. package/dist/contract.d.ts +1 -1
  4. package/dist/contract.d.ts.map +1 -1
  5. package/dist/contract.js +1 -1
  6. package/dist/contract.js.map +1 -1
  7. package/dist/environments/hardhat/polkadot/package-lock.json +12683 -0
  8. package/dist/environments/hardhat/polkadot/package.json +17 -0
  9. package/dist/erc20.d.ts +7 -0
  10. package/dist/erc20.d.ts.map +1 -1
  11. package/dist/erc20.js +46 -35
  12. package/dist/erc20.js.map +1 -1
  13. package/dist/get-versioned-remappings.js +3 -3
  14. package/dist/get-versioned-remappings.js.map +1 -1
  15. package/dist/index.d.ts +23 -15
  16. package/dist/index.d.ts.map +1 -1
  17. package/dist/index.js +34 -21
  18. package/dist/index.js.map +1 -1
  19. package/dist/options.d.ts +3 -0
  20. package/dist/options.d.ts.map +1 -1
  21. package/dist/options.js.map +1 -1
  22. package/dist/print.d.ts.map +1 -1
  23. package/dist/print.js +38 -26
  24. package/dist/print.js.map +1 -1
  25. package/dist/utils/convert-strings.d.ts +21 -2
  26. package/dist/utils/convert-strings.d.ts.map +1 -1
  27. package/dist/utils/convert-strings.js +28 -4
  28. package/dist/utils/convert-strings.js.map +1 -1
  29. package/dist/zip-hardhat-polkadot.d.ts +5 -0
  30. package/dist/zip-hardhat-polkadot.d.ts.map +1 -0
  31. package/dist/zip-hardhat-polkadot.js +115 -0
  32. package/dist/zip-hardhat-polkadot.js.map +1 -0
  33. package/dist/zip-hardhat.d.ts +21 -0
  34. package/dist/zip-hardhat.d.ts.map +1 -1
  35. package/dist/zip-hardhat.js +181 -115
  36. package/dist/zip-hardhat.js.map +1 -1
  37. package/package.json +3 -3
  38. package/src/common-options.ts +1 -1
  39. package/src/contract.ts +2 -2
  40. package/src/environments/hardhat/polkadot/package-lock.json +12683 -0
  41. package/src/environments/hardhat/polkadot/package.json +17 -0
  42. package/src/erc20.ts +55 -36
  43. package/src/get-versioned-remappings.ts +1 -1
  44. package/src/index.ts +30 -18
  45. package/src/options.ts +3 -1
  46. package/src/print.ts +47 -26
  47. package/src/utils/convert-strings.ts +28 -4
  48. package/src/zip-hardhat-polkadot.ts +86 -0
  49. package/src/zip-hardhat.ts +203 -129
  50. /package/{openzeppelin-contracts-version.d.ts → openzeppelin-contracts-version.json.d.ts} +0 -0
@@ -0,0 +1,17 @@
1
+ {
2
+ "name": "hardhat-sample",
3
+ "version": "0.0.1",
4
+ "description": "",
5
+ "main": "index.js",
6
+ "scripts": {
7
+ "test": "hardhat test"
8
+ },
9
+ "author": "",
10
+ "license": "ISC",
11
+ "devDependencies": {
12
+ "@openzeppelin/contracts": "^5.5.0",
13
+ "@parity/hardhat-polkadot": "^0.2.7",
14
+ "@nomicfoundation/hardhat-toolbox": "^6.1.0",
15
+ "hardhat": "^2.22.0"
16
+ }
17
+ }
package/src/erc20.ts CHANGED
@@ -173,7 +173,7 @@ export function isValidChainId(str: string): boolean {
173
173
  return chainIdPattern.test(str);
174
174
  }
175
175
 
176
- function scaleByPowerOfTen(base: bigint, exponent: number): bigint {
176
+ export function scaleByPowerOfTen(base: bigint, exponent: number): bigint {
177
177
  if (exponent < 0) {
178
178
  return base / BigInt(10) ** BigInt(-exponent);
179
179
  } else {
@@ -181,55 +181,74 @@ function scaleByPowerOfTen(base: bigint, exponent: number): bigint {
181
181
  }
182
182
  }
183
183
 
184
+ export interface PremintCalculation {
185
+ units: string;
186
+ exp: string;
187
+ decimalPlace: number;
188
+ }
189
+
190
+ export function calculatePremint(amount: string): PremintCalculation | undefined {
191
+ const m = amount.match(premintPattern);
192
+ if (!m) {
193
+ throw new OptionsError({
194
+ premint: 'Not a valid number',
195
+ });
196
+ }
197
+
198
+ const integer = m[1]?.replace(/^0+/, '') ?? '';
199
+ const decimals = m[2]?.replace(/0+$/, '') ?? '';
200
+ const exponent = Number(m[3] ?? 0);
201
+
202
+ if (Number(integer + decimals) > 0) {
203
+ const decimalPlace = decimals.length - exponent;
204
+ const zeroes = new Array(Math.max(0, -decimalPlace)).fill('0').join('');
205
+ const units = integer + decimals + zeroes;
206
+ const exp = decimalPlace <= 0 ? 'decimals()' : `(decimals() - ${decimalPlace})`;
207
+
208
+ return { units, exp, decimalPlace };
209
+ } else {
210
+ return undefined;
211
+ }
212
+ }
213
+
184
214
  function addPremint(
185
215
  c: ContractBuilder,
186
216
  amount: string,
187
217
  premintChainId: string,
188
218
  crossChainBridging: CrossChainBridging,
189
219
  ) {
190
- const m = amount.match(premintPattern);
191
- if (m) {
192
- const integer = m[1]?.replace(/^0+/, '') ?? '';
193
- const decimals = m[2]?.replace(/0+$/, '') ?? '';
194
- const exponent = Number(m[3] ?? 0);
195
-
196
- if (Number(integer + decimals) > 0) {
197
- const decimalPlace = decimals.length - exponent;
198
- const zeroes = new Array(Math.max(0, -decimalPlace)).fill('0').join('');
199
- const units = integer + decimals + zeroes;
200
- const exp = decimalPlace <= 0 ? 'decimals()' : `(decimals() - ${decimalPlace})`;
220
+ const premintCalculation = calculatePremint(amount);
221
+ if (premintCalculation === undefined) {
222
+ return;
223
+ }
201
224
 
202
- const validatedBaseUnits = toUint256(units, 'premint');
203
- checkPotentialPremintOverflow(validatedBaseUnits, decimalPlace);
225
+ const { units, exp, decimalPlace } = premintCalculation;
204
226
 
205
- c.addConstructorArgument({ type: 'address', name: 'recipient' });
227
+ const validatedBaseUnits = toUint256(units, 'premint');
228
+ checkPotentialPremintOverflow(validatedBaseUnits, decimalPlace);
206
229
 
207
- const mintLine = `_mint(recipient, ${units} * 10 ** ${exp});`;
230
+ c.addConstructorArgument({ type: 'address', name: 'recipient' });
208
231
 
209
- if (crossChainBridging) {
210
- if (premintChainId === '') {
211
- throw new OptionsError({
212
- premintChainId: 'Chain ID is required when using Premint with Cross-Chain Bridging',
213
- });
214
- }
232
+ const mintLine = `_mint(recipient, ${units} * 10 ** ${exp});`;
215
233
 
216
- if (!isValidChainId(premintChainId)) {
217
- throw new OptionsError({
218
- premintChainId: 'Not a valid chain ID',
219
- });
220
- }
234
+ if (crossChainBridging) {
235
+ if (premintChainId === '') {
236
+ throw new OptionsError({
237
+ premintChainId: 'Chain ID is required when using Premint with Cross-Chain Bridging',
238
+ });
239
+ }
221
240
 
222
- c.addConstructorCode(`if (block.chainid == ${premintChainId}) {`);
223
- c.addConstructorCode(` ${mintLine}`);
224
- c.addConstructorCode(`}`);
225
- } else {
226
- c.addConstructorCode(mintLine);
227
- }
241
+ if (!isValidChainId(premintChainId)) {
242
+ throw new OptionsError({
243
+ premintChainId: 'Not a valid chain ID',
244
+ });
228
245
  }
246
+
247
+ c.addConstructorCode(`if (block.chainid == ${premintChainId}) {`);
248
+ c.addConstructorCode(` ${mintLine}`);
249
+ c.addConstructorCode(`}`);
229
250
  } else {
230
- throw new OptionsError({
231
- premint: 'Not a valid number',
232
- });
251
+ c.addConstructorCode(mintLine);
233
252
  }
234
253
  }
235
254
 
@@ -1,5 +1,5 @@
1
1
  import type { CommonOptions } from './common-options';
2
- import contractsVersion from '../openzeppelin-contracts-version';
2
+ import contractsVersion from '../openzeppelin-contracts-version.json';
3
3
 
4
4
  export function getVersionedRemappings(opts?: CommonOptions): string[] {
5
5
  const remappings = [`@openzeppelin/contracts/=@openzeppelin/contracts@${contractsVersion.version}/`];
package/src/index.ts CHANGED
@@ -1,21 +1,37 @@
1
+ // ===== Public API =====
2
+
3
+ export { erc20, erc721, erc1155, stablecoin, realWorldAsset, account, governor, custom } from './api';
4
+ export type { WizardContractAPI, AccessControlAPI } from './api';
5
+
6
+ export type { ERC20Options } from './erc20';
7
+ export type { ERC721Options } from './erc721';
8
+ export type { ERC1155Options } from './erc1155';
9
+ export type { StablecoinOptions } from './stablecoin';
10
+ export type { AccountOptions } from './account';
11
+ export type { GovernorOptions } from './governor';
12
+ export type { CustomOptions } from './custom';
13
+
14
+ // ===== Internal API - Intended for use by other Wizard packages only =====
15
+
1
16
  export type { GenericOptions, KindedOptions } from './build-generic';
2
17
  export { buildGeneric } from './build-generic';
3
18
 
4
19
  export { generateAlternatives } from './generate/alternatives';
5
20
 
6
- export type { Contract, BaseFunction, Value, ReferencedContract } from './contract';
21
+ export type { Contract, BaseFunction, Value, ReferencedContract, FunctionArgument } from './contract';
7
22
  export { ContractBuilder } from './contract';
8
23
 
9
24
  export { printContract } from './print';
10
25
 
11
26
  export type { Access } from './set-access-control';
27
+ export { accessOptions, setAccessControl, requireAccessControl } from './set-access-control';
28
+ export { addPausable } from './add-pausable';
12
29
  export type { Upgradeable } from './set-upgradeable';
13
30
  export type { Info } from './set-info';
14
31
 
15
32
  export { premintPattern, chainIdPattern } from './erc20';
16
- export { defaults as infoDefaults, infoOptions, setInfo } from './set-info';
17
- export { accessOptions, setAccessControl, requireAccessControl } from './set-access-control';
18
- export { addPausable } from './add-pausable';
33
+ export { defaults as infoDefaults, setInfo, infoOptions } from './set-info';
34
+ export { supportsInterface } from './common-functions';
19
35
 
20
36
  export type { OptionsErrorMessages } from './error';
21
37
  export { OptionsError } from './error';
@@ -23,21 +39,17 @@ export { OptionsError } from './error';
23
39
  export type { Kind } from './kind';
24
40
  export { sanitizeKind } from './kind';
25
41
 
26
- export { erc20, erc721, erc1155, stablecoin, realWorldAsset, account, governor, custom } from './api';
27
- export type { WizardContractAPI, AccessControlAPI } from './api';
28
-
29
42
  export { compatibleContractsSemver } from './utils/version';
30
- export { findCover } from './utils/find-cover';
31
- export { defineFunctions } from './utils/define-functions';
32
43
 
44
+ export { defineFunctions } from './utils/define-functions';
33
45
  export type { CommonOptions } from './common-options';
34
46
  export { withCommonDefaults, defaults as commonDefaults } from './common-options';
35
- export { supportsInterface } from './common-functions';
36
-
37
- export type { ERC20Options } from './erc20';
38
- export type { ERC721Options } from './erc721';
39
- export type { ERC1155Options } from './erc1155';
40
- export type { StablecoinOptions } from './stablecoin';
41
- export type { AccountOptions } from './account';
42
- export type { GovernorOptions } from './governor';
43
- export type { CustomOptions } from './custom';
47
+ export type { ClockMode } from './set-clock-mode';
48
+ export { clockModeDefault, setClockMode, clockModeOptions } from './set-clock-mode';
49
+ export { toBigInt } from './utils/convert-strings';
50
+ export type { Options } from './options';
51
+ export type { Lines } from './utils/format-lines';
52
+ export { formatLinesWithSpaces, spaceBetween } from './utils/format-lines';
53
+ export { findCover } from './utils/find-cover';
54
+ export type { PremintCalculation } from './erc20';
55
+ export { calculatePremint as calculateERC20Premint, scaleByPowerOfTen } from './erc20';
package/src/options.ts CHANGED
@@ -29,8 +29,10 @@ export interface Options {
29
29
  transformImport?: (parent: ImportContract) => ImportContract;
30
30
  /**
31
31
  * Add additional libraries to the compatibility banner printed at the top of the contract.
32
+ *
33
+ * If `alwaysKeepOzPrefix` is true, the library name will always keep the "OpenZeppelin " prefix, even if there are multiple libraries from OpenZeppelin being imported.
32
34
  */
33
- additionalCompatibleLibraries?: { name: string; path: string; version: string }[];
35
+ additionalCompatibleLibraries?: { name: string; path: string; version: string; alwaysKeepOzPrefix?: boolean }[];
34
36
  }
35
37
 
36
38
  export interface Helpers extends Required<Options> {
package/src/print.ts CHANGED
@@ -75,15 +75,20 @@ function printVariableOrErrorDefinitionsWithoutComments(
75
75
  return withoutComments.map(v => v.code);
76
76
  }
77
77
 
78
+ type LibraryDescription = {
79
+ nameAndVersion: string;
80
+ alwaysKeepOzPrefix?: boolean;
81
+ };
82
+
78
83
  function printCompatibleLibraryVersions(contract: Contract, opts?: Options): string {
79
- const libraries: string[] = [];
84
+ const libraryDescriptions: LibraryDescription[] = [];
80
85
  if (importsLibrary(contract, '@openzeppelin/contracts')) {
81
- libraries.push(`OpenZeppelin Contracts ${compatibleContractsSemver}`);
86
+ libraryDescriptions.push({ nameAndVersion: `OpenZeppelin Contracts ${compatibleContractsSemver}` });
82
87
  }
83
88
  if (importsLibrary(contract, '@openzeppelin/community-contracts')) {
84
89
  try {
85
90
  const commit = getCommunityContractsGitCommit();
86
- libraries.push(`Community Contracts commit ${commit}`);
91
+ libraryDescriptions.push({ nameAndVersion: `OpenZeppelin Community Contracts commit ${commit}` });
87
92
  } catch (e) {
88
93
  console.error(e);
89
94
  }
@@ -91,14 +96,35 @@ function printCompatibleLibraryVersions(contract: Contract, opts?: Options): str
91
96
  if (opts?.additionalCompatibleLibraries) {
92
97
  for (const library of opts.additionalCompatibleLibraries) {
93
98
  if (importsLibrary(contract, library.path)) {
94
- libraries.push(`${library.name} ${library.version}`);
99
+ libraryDescriptions.push({
100
+ nameAndVersion: `${library.name} ${library.version}`,
101
+ alwaysKeepOzPrefix: library.alwaysKeepOzPrefix,
102
+ });
95
103
  }
96
104
  }
97
105
  }
98
106
 
99
- if (libraries.length === 0) return '';
100
- if (libraries.length === 1) return `// Compatible with ${libraries[0]}`;
101
- return `// Compatible with ${libraries.slice(0, -1).join(', ')} and ${libraries.slice(-1)}`;
107
+ if (libraryDescriptions.length === 0) {
108
+ return '';
109
+ } else if (libraryDescriptions.length === 1) {
110
+ return `// Compatible with ${libraryDescriptions[0]!.nameAndVersion}`;
111
+ } else {
112
+ const OZ_PREFIX_WITH_SPACE = 'OpenZeppelin ';
113
+ if (libraryDescriptions[0]!.nameAndVersion.startsWith(OZ_PREFIX_WITH_SPACE)) {
114
+ for (let i = 1; i < libraryDescriptions.length; i++) {
115
+ if (
116
+ libraryDescriptions[i]!.nameAndVersion.startsWith(OZ_PREFIX_WITH_SPACE) &&
117
+ !libraryDescriptions[i]!.alwaysKeepOzPrefix
118
+ ) {
119
+ libraryDescriptions[i]!.nameAndVersion = libraryDescriptions[i]!.nameAndVersion.slice(
120
+ OZ_PREFIX_WITH_SPACE.length,
121
+ );
122
+ }
123
+ }
124
+ }
125
+ const librariesToPrint = libraryDescriptions.map(l => l.nameAndVersion);
126
+ return `// Compatible with ${librariesToPrint.slice(0, -1).join(', ')} and ${librariesToPrint.slice(-1)}`;
127
+ }
102
128
  }
103
129
 
104
130
  function printInheritance(contract: Contract, { transformName }: Helpers): [] | [string] {
@@ -334,30 +360,25 @@ function printNatspecTags(tags: NatspecTag[]): string[] {
334
360
  }
335
361
 
336
362
  function printImports(imports: ImportContract[], helpers: Helpers): string[] {
337
- // Sort imports by name
338
- imports.sort((a, b) => {
339
- if (a.name < b.name) return -1;
340
- if (a.name > b.name) return 1;
341
- return 0;
342
- });
343
-
344
- const lines: string[] = [];
345
- imports.map(p => {
346
- const importContract = helpers.transformImport(p);
347
- lines.push(`import {${importContract.name}} from "${importContract.path}";`);
348
- });
363
+ const itemByPath = new Map<string, Set<string>>();
349
364
 
350
- return lines;
365
+ for (const p of imports) {
366
+ const { name, path } = helpers.transformImport(p);
367
+ const _ = itemByPath.get(path)?.add(name) ?? itemByPath.set(path, new Set([name]));
368
+ }
369
+
370
+ return Array.from(itemByPath.keys())
371
+ .sort()
372
+ .map(path => `import {${Array.from(itemByPath.get(path)!).sort().join(', ')}} from "${path}";`);
351
373
  }
352
374
 
353
375
  function printLibraries(contract: Contract, { transformName }: Helpers): string[] {
354
376
  if (!contract.libraries || contract.libraries.length === 0) return [];
355
377
 
356
378
  return contract.libraries
357
- .sort((a, b) => a.library.name.localeCompare(b.library.name))
358
- .flatMap(lib =>
359
- [...lib.usingFor]
360
- .sort((a, b) => a.localeCompare(b))
361
- .map(type => `using ${transformName(lib.library)} for ${type};`),
362
- );
379
+ .sort((a, b) => a.library.name.localeCompare(b.library.name)) // Sort by import path
380
+ .map(lib => {
381
+ const sortedTypes = Array.from(lib.usingFor).sort((a, b) => a.localeCompare(b)); // Sort types
382
+ return `using ${transformName(lib.library)} for ${sortedTypes.join(', ')};`;
383
+ });
363
384
  }
@@ -3,21 +3,32 @@ import { OptionsError } from '../error';
3
3
  export const UINT256_MAX = BigInt(2) ** BigInt(256) - BigInt(1);
4
4
 
5
5
  /**
6
- * Checks that a string is a valid `uint256` value and converts it to bigint.
6
+ * Checks that a string is a valid number, and convert to bigint.
7
7
  *
8
8
  * @param value The string value to check and convert.
9
9
  * @param field The field name to use in the error message if the value is invalid.
10
- * @throws OptionsError if the value is not a valid number or is greater than the maximum value for `uint256`.
10
+ * @throws OptionsError if the value is not a valid number.
11
11
  * @returns The validated value as a bigint.
12
12
  */
13
- export function toUint256(value: string, field: string): bigint {
13
+ export function toBigInt(value: string, field: string): bigint {
14
14
  const isValidNumber = /^\d+$/.test(value);
15
15
  if (!isValidNumber) {
16
16
  throw new OptionsError({
17
17
  [field]: 'Not a valid number',
18
18
  });
19
19
  }
20
- const numValue = BigInt(value);
20
+ return BigInt(value);
21
+ }
22
+
23
+ /**
24
+ * Checks that a bigint value fits within `uint256`.
25
+ *
26
+ * @param numValue The value to check.
27
+ * @param field The field name to use in the error if the value is invalid.
28
+ * @throws OptionsError if the value is greater than the maximum value for `uint256`.
29
+ * @returns The value as a bigint.
30
+ */
31
+ export function validateUint256(numValue: bigint, field: string): bigint {
21
32
  if (numValue > UINT256_MAX) {
22
33
  throw new OptionsError({
23
34
  [field]: 'Value is greater than uint256 max value',
@@ -25,3 +36,16 @@ export function toUint256(value: string, field: string): bigint {
25
36
  }
26
37
  return numValue;
27
38
  }
39
+
40
+ /**
41
+ * Checks that a string is a valid number, and fits within `uint256`.
42
+ * Convenience function that calls `toBigInt` and `validateUint256`.
43
+ *
44
+ * @param value The value to check.
45
+ * @param field The field name to use in the error if the value is invalid.
46
+ * @throws OptionsError if the value is not a valid number or is greater than the maximum value for `uint256`.
47
+ * @returns The value as a bigint.
48
+ */
49
+ export function toUint256(value: string, field: string): bigint {
50
+ return validateUint256(toBigInt(value, field), field);
51
+ }
@@ -0,0 +1,86 @@
1
+ import type JSZip from 'jszip';
2
+ import type { Contract } from './contract';
3
+ import { HardhatZipGenerator } from './zip-hardhat';
4
+ import type { GenericOptions } from './build-generic';
5
+ import SOLIDITY_VERSION from './solidity-version.json';
6
+
7
+ class HardhatPolkadotZipGenerator extends HardhatZipGenerator {
8
+ protected getAdditionalHardhatImports(): string[] {
9
+ return ['@parity/hardhat-polkadot'];
10
+ }
11
+
12
+ protected getHardhatConfigJsonString(): string {
13
+ return `\
14
+ {
15
+ solidity: {
16
+ version: "${SOLIDITY_VERSION}",
17
+ settings: {
18
+ evmVersion: 'cancun',
19
+ optimizer: {
20
+ enabled: true,
21
+ },
22
+ },
23
+ },
24
+ resolc: {
25
+ compilerSource: 'npm',
26
+ },
27
+ networks: {
28
+ hardhat: {
29
+ polkavm: true,
30
+ nodeConfig: {
31
+ nodeBinaryPath: 'INSERT_PATH_TO_REVIVE_DEV_NODE',
32
+ rpcPort: 8000,
33
+ dev: true,
34
+ },
35
+ adapterConfig: {
36
+ adapterBinaryPath: 'INSERT_PATH_TO_ETH_RPC_ADAPTER',
37
+ dev: true,
38
+ },
39
+ },
40
+ },
41
+ }`;
42
+ }
43
+
44
+ protected async getPackageJson(c: Contract): Promise<unknown> {
45
+ const { default: packageJson } = await import('./environments/hardhat/polkadot/package.json');
46
+ packageJson.license = c.license;
47
+ return packageJson;
48
+ }
49
+
50
+ protected async getPackageLock(c: Contract): Promise<unknown> {
51
+ const { default: packageLock } = await import('./environments/hardhat/polkadot/package-lock.json');
52
+ packageLock.packages[''].license = c.license;
53
+ return packageLock;
54
+ }
55
+
56
+ protected getReadmePrerequisitesSection(): string {
57
+ return `\
58
+ ## Prerequisites
59
+
60
+ Ensure you have the following installed:
61
+ - [Node.js 22.5+](https://nodejs.org/en/download/)
62
+ - npm 10.9.0+
63
+
64
+ `;
65
+ }
66
+
67
+ protected getReadmeTestingEnvironmentSetupSection(): string {
68
+ return `\
69
+ ## Setting up a testing environment
70
+
71
+ Follow the steps in [Polkadot's documentation](https://docs.polkadot.com/smart-contracts/dev-environments/local-dev-node/) to set up a local development node and replace the placeholder values \`INSERT_PATH_TO_REVIVE_DEV_NODE\` and \`INSERT_PATH_TO_ETH_RPC_ADAPTER\` in \`hardhat.config.ts\`.
72
+
73
+ `;
74
+ }
75
+
76
+ protected getGitIgnoreHardhatIgnition(): string {
77
+ return `
78
+ # Hardhat Ignition default folder for deployments against a local Polkadot Revive Dev node
79
+ ignition/deployments/chain-420420420
80
+ `;
81
+ }
82
+ }
83
+
84
+ export async function zipHardhatPolkadot(c: Contract, opts?: GenericOptions): Promise<JSZip> {
85
+ return new HardhatPolkadotZipGenerator().zipHardhat(c, opts);
86
+ }