Skip to content

Commit c14be02

Browse files
Add Solidity Wizard API function to get versioned remappings (#724)
Co-authored-by: Eric Lau <ericglau@outlook.com>
1 parent 139e0f7 commit c14be02

File tree

7 files changed

+110
-57
lines changed

7 files changed

+110
-57
lines changed

.changeset/long-trams-tease.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@openzeppelin/wizard': patch
3+
---
4+
5+
Add API function to get versioned remappings.

packages/core/solidity/README.md

Lines changed: 17 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -24,81 +24,42 @@ The following contract types are supported:
2424

2525
Note that `stablecoin` and `realWorldAsset` are experimental and may be subject to change.
2626

27-
Each contract type has functions/constants as defined below.
28-
2927
### Functions
3028

29+
Each contract type implements a common API with methods that take contract-specific options (e.g., `ERC20Options` for `erc20`, `ERC721Options` for `erc721`, etc.). This ensures type safety and allows for contract-specific features.
30+
3131
#### `print`
3232
```js
33-
function print(opts?: ERC20Options): string
34-
```
35-
```js
36-
function print(opts?: ERC721Options): string
37-
```
38-
```js
39-
function print(opts?: ERC1155Options): string
40-
```
41-
```js
42-
function print(opts?: StablecoinOptions): string
43-
```
44-
```js
45-
function print(opts?: AccountOptions): string
46-
```
47-
```js
48-
function print(opts?: GovernorOptions): string
49-
```
50-
```js
51-
function print(opts?: CustomOptions): string
33+
function print(opts?: Options): string
5234
```
5335
Returns a string representation of a contract generated using the provided options. If `opts` is not provided, uses [`defaults`](#defaults).
5436

55-
#### `defaults`
56-
```js
57-
const defaults: Required<ERC20Options>
58-
```
59-
```js
60-
const defaults: Required<ERC721Options>
61-
```
62-
```js
63-
const defaults: Required<ERC1155Options>
64-
```
65-
```js
66-
const defaults: Required<StablecoinOptions>
67-
```
37+
#### `getVersionedRemappings`
6838
```js
69-
const defaults: Required<AccountOptions>
39+
function getVersionedRemappings(opts?: Options): string[]
7040
```
41+
Returns an array of remappings that map unversioned import prefixes to versioned import prefixes. For example:
7142
```js
72-
const defaults: Required<GovernorOptions>
43+
[
44+
"@openzeppelin/contracts/=@openzeppelin/contracts@5.5.0/",
45+
"@openzeppelin/contracts-upgradeable/=@openzeppelin/contracts-upgradeable@5.5.0/"
46+
]
7347
```
48+
If the contract options include upgradeability, the upgradeable remapping is included. If `opts` is not provided, uses [`defaults`](#defaults).
49+
50+
#### `defaults`
7451
```js
75-
const defaults: Required<CustomOptions>
52+
const defaults: Required<Options>
7653
```
77-
The default options that are used for [`print`](#print).
54+
The default options that are used for [`print`](#print) and [`getVersionedRemappings`](#getVersionedRemappings).
7855

7956
#### `isAccessControlRequired`
8057
```js
81-
function isAccessControlRequired(opts: Partial<ERC20Options>): boolean
82-
```
83-
```js
84-
function isAccessControlRequired(opts: Partial<ERC721Options>): boolean
85-
```
86-
```js
87-
function isAccessControlRequired(opts: Partial<ERC1155Options>): boolean
88-
```
89-
```js
90-
function isAccessControlRequired(opts: Partial<StablecoinOptions>): boolean
91-
```
92-
```js
93-
function isAccessControlRequired(opts: Partial<GovernorOptions>): boolean
94-
```
95-
```js
96-
function isAccessControlRequired(opts: Partial<CustomOptions>): boolean
58+
function isAccessControlRequired(opts: Partial<Options>): boolean
9759
```
9860
Whether any of the provided options require access control to be enabled. If this returns `true`, then calling `print` with the same options would cause the `access` option to default to `'ownable'` if it was `undefined` or `false`.
9961

100-
> Note that contracts such as `account`, have its own way of handling permissions and do not support the `access` option.
101-
Thus, that type does not include `isAccessControlRequired`.
62+
> Note that contracts such as `account` have their own way of handling permissions and do not support the `access` option. Thus, that type does not include `isAccessControlRequired`.
10263

10364
### Examples
10465

@@ -129,4 +90,3 @@ const contract = erc20.print({
12990
...erc20.defaults,
13091
upgradeable: 'uups',
13192
});
132-
```

packages/core/solidity/src/api.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,26 @@ import {
3737
defaults as customDefaults,
3838
isAccessControlRequired as customIsAccessControlRequired,
3939
} from './custom';
40+
import { getVersionedRemappings } from './get-versioned-remappings';
4041

4142
export interface WizardContractAPI<Options extends CommonOptions> {
4243
/**
4344
* Returns a string representation of a contract generated using the provided options. If opts is not provided, uses `defaults`.
4445
*/
4546
print: (opts?: Options) => string;
4647

48+
/**
49+
* Returns remappings that map unversioned import prefixes to versioned import prefixes.
50+
* @example
51+
* ```ts
52+
* [
53+
* "@openzeppelin/contracts/=@openzeppelin/contracts@5.5.0/",
54+
* "@openzeppelin/contracts-upgradeable/=@openzeppelin/contracts-upgradeable@5.5.0/"
55+
* ]
56+
* ```
57+
*/
58+
getVersionedRemappings: (opts?: Options) => string[];
59+
4760
/**
4861
* The default options that are used for `print`.
4962
*/
@@ -69,40 +82,48 @@ export type Custom = WizardContractAPI<CustomOptions> & AccessControlAPI<CustomO
6982

7083
export const erc20: ERC20 = {
7184
print: printERC20,
85+
getVersionedRemappings: getVersionedRemappings,
7286
defaults: erc20defaults,
7387
isAccessControlRequired: erc20IsAccessControlRequired,
7488
};
7589
export const erc721: ERC721 = {
7690
print: printERC721,
91+
getVersionedRemappings: getVersionedRemappings,
7792
defaults: erc721defaults,
7893
isAccessControlRequired: erc721IsAccessControlRequired,
7994
};
8095
export const erc1155: ERC1155 = {
8196
print: printERC1155,
97+
getVersionedRemappings: getVersionedRemappings,
8298
defaults: erc1155defaults,
8399
isAccessControlRequired: erc1155IsAccessControlRequired,
84100
};
85101
export const stablecoin: Stablecoin = {
86102
print: printStablecoin,
103+
getVersionedRemappings: getVersionedRemappings,
87104
defaults: stablecoinDefaults,
88105
isAccessControlRequired: stablecoinIsAccessControlRequired,
89106
};
90107
export const account: Account = {
91108
print: printAccount,
109+
getVersionedRemappings: getVersionedRemappings,
92110
defaults: accountDefaults,
93111
};
94112
export const realWorldAsset: RealWorldAsset = {
95113
print: printStablecoin,
114+
getVersionedRemappings: getVersionedRemappings,
96115
defaults: stablecoinDefaults,
97116
isAccessControlRequired: stablecoinIsAccessControlRequired,
98117
};
99118
export const governor: Governor = {
100119
print: printGovernor,
120+
getVersionedRemappings: getVersionedRemappings,
101121
defaults: governorDefaults,
102122
isAccessControlRequired: governorIsAccessControlRequired,
103123
};
104124
export const custom: Custom = {
105125
print: printCustom,
126+
getVersionedRemappings: getVersionedRemappings,
106127
defaults: customDefaults,
107128
isAccessControlRequired: customIsAccessControlRequired,
108129
};
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import test from 'ava';
2+
import { getVersionedRemappings } from './get-versioned-remappings';
3+
import contracts from '../openzeppelin-contracts';
4+
5+
test('getVersionedRemappings not upgradeable', t => {
6+
const remappings = getVersionedRemappings({});
7+
t.is(remappings.length, 1);
8+
t.is(remappings[0], `@openzeppelin/contracts/=@openzeppelin/contracts@${contracts.version}/`);
9+
t.snapshot(remappings);
10+
});
11+
12+
test('getVersionedRemappings upgradeable uups', t => {
13+
const remappings = getVersionedRemappings({ upgradeable: 'uups' });
14+
t.is(remappings.length, 2);
15+
t.is(remappings[0], `@openzeppelin/contracts/=@openzeppelin/contracts@${contracts.version}/`);
16+
t.is(remappings[1], `@openzeppelin/contracts-upgradeable/=@openzeppelin/contracts-upgradeable@${contracts.version}/`);
17+
t.snapshot(remappings);
18+
});
19+
20+
test('getVersionedRemappings upgradeable transparent', t => {
21+
const remappings = getVersionedRemappings({ upgradeable: 'transparent' });
22+
t.is(remappings.length, 2);
23+
t.is(remappings[0], `@openzeppelin/contracts/=@openzeppelin/contracts@${contracts.version}/`);
24+
t.is(remappings[1], `@openzeppelin/contracts-upgradeable/=@openzeppelin/contracts-upgradeable@${contracts.version}/`);
25+
t.snapshot(remappings);
26+
});
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# Snapshot report for `src/get-versioned-remappings.test.ts`
2+
3+
The actual snapshot is saved in `get-versioned-remappings.test.ts.snap`.
4+
5+
Generated by [AVA](https://avajs.dev).
6+
7+
## getVersionedRemappings not upgradeable
8+
9+
> Snapshot 1
10+
11+
[
12+
'@openzeppelin/contracts/=@openzeppelin/contracts@5.5.0/',
13+
]
14+
15+
## getVersionedRemappings upgradeable uups
16+
17+
> Snapshot 1
18+
19+
[
20+
'@openzeppelin/contracts/=@openzeppelin/contracts@5.5.0/',
21+
'@openzeppelin/contracts-upgradeable/=@openzeppelin/contracts-upgradeable@5.5.0/',
22+
]
23+
24+
## getVersionedRemappings upgradeable transparent
25+
26+
> Snapshot 1
27+
28+
[
29+
'@openzeppelin/contracts/=@openzeppelin/contracts@5.5.0/',
30+
'@openzeppelin/contracts-upgradeable/=@openzeppelin/contracts-upgradeable@5.5.0/',
31+
]
302 Bytes
Binary file not shown.
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import type { CommonOptions } from './common-options';
2+
import contracts from '../openzeppelin-contracts';
3+
4+
export function getVersionedRemappings(opts?: CommonOptions): string[] {
5+
const remappings = [`@openzeppelin/contracts/=@openzeppelin/contracts@${contracts.version}/`];
6+
if (opts?.upgradeable) {
7+
remappings.push(`@openzeppelin/contracts-upgradeable/=@openzeppelin/contracts-upgradeable@${contracts.version}/`);
8+
}
9+
return remappings;
10+
}

0 commit comments

Comments
 (0)