Skip to content

Commit 7912a5e

Browse files
authored
Fix Uniswap Hooks Wizard package, readme, changelog (#743)
1 parent 985d5a4 commit 7912a5e

File tree

6 files changed

+222
-152
lines changed

6 files changed

+222
-152
lines changed

.changeset/lovely-wings-bow.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@openzeppelin/wizard-uniswap-hooks': patch
3+
---
4+
5+
Fix package dependency

packages/core/solidity/src/package.test.ts

Lines changed: 27 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7,41 +7,46 @@ import { join } from 'path';
77

88
const execAsync = promisify(exec);
99

10+
async function packPackage(packageRoot: string): Promise<string> {
11+
const { stdout: packOutput } = await execAsync('npm pack', { cwd: packageRoot });
12+
// npm pack outputs the filename as the last line
13+
const lines = packOutput.trim().split('\n');
14+
const packedFile = lines[lines.length - 1]?.trim();
15+
if (!packedFile) {
16+
throw new Error('Failed to get packed filename from npm pack output');
17+
}
18+
return join(packageRoot, packedFile);
19+
}
20+
1021
test('packed package can be installed and imported', async t => {
1122
const packageRoot = join(__dirname, '..');
1223
const tempDir = await mkdtemp(join(tmpdir(), 'wizard-package-test-'));
1324

1425
try {
1526
// Pack the package
16-
const { stdout: packOutput } = await execAsync('npm pack', { cwd: packageRoot });
17-
// npm pack outputs the filename as the last line
18-
const lines = packOutput.trim().split('\n');
19-
const packedFile = lines[lines.length - 1]?.trim();
20-
if (!packedFile) {
21-
throw new Error('Failed to get packed filename from npm pack output');
22-
}
23-
const packedPath = join(packageRoot, packedFile);
27+
const packedPath = await packPackage(packageRoot);
2428

25-
// Create a test project in temp directory
26-
await execAsync('npm init -y', { cwd: tempDir });
29+
try {
30+
// Create a test project in temp directory
31+
await execAsync('npm init -y', { cwd: tempDir });
2732

28-
// Install the packed package
29-
await execAsync(`npm install "${packedPath}"`, { cwd: tempDir });
30-
31-
// Test that the package can be imported
32-
const testScript = `const { erc20 } = require('@openzeppelin/wizard');
33+
// Install the packed package
34+
await execAsync(`npm install "${packedPath}"`, { cwd: tempDir });
3335

36+
// Test that the package can be imported
37+
const testScript = `const { erc20 } = require('@openzeppelin/wizard');
3438
console.log('SUCCESS');
3539
`;
3640

37-
const testScriptPath = join(tempDir, 'test.js');
38-
await writeFile(testScriptPath, testScript);
39-
const { stdout } = await execAsync('node test.js', { cwd: tempDir });
40-
41-
t.true(stdout.includes('SUCCESS'));
41+
const testScriptPath = join(tempDir, 'test.js');
42+
await writeFile(testScriptPath, testScript);
43+
const { stdout } = await execAsync('node test.js', { cwd: tempDir });
4244

43-
// Clean up the packed file
44-
await rm(packedPath, { force: true });
45+
t.true(stdout.includes('SUCCESS'));
46+
} finally {
47+
// Clean up the packed file
48+
await rm(packedPath, { force: true });
49+
}
4550
} finally {
4651
// Clean up temp directory
4752
await rm(tempDir, { recursive: true, force: true });
Lines changed: 1 addition & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -1,128 +1 @@
1-
# OpenZeppelin Contracts Wizard for Uniswap Hooks
2-
3-
[![NPM Package](https://img.shields.io/npm/v/@openzeppelin/wizard-uniswap-hooks?color=%234e5de4)](https://www.npmjs.com/package/@openzeppelin/wizard-uniswap-hooks)
4-
5-
Interactively build a [Uniswap v4 Hook](https://docs.uniswap.org/contracts/v4/concepts/hooks) contract out of components from [OpenZeppelin Uniswap Hooks](https://github.com/OpenZeppelin/uniswap-hooks) and [OpenZeppelin Contracts](https://github.com/OpenZeppelin/openzeppelin-contracts). Provide parameters and desired features for the hook template that you want, and the Wizard will generate all of the necessary code. The resulting code is ready to be compiled and deployed, or it can serve as a starting point and customized further with application specific logic.
6-
7-
This package provides a programmatic API. For a web interface, see https://wizard.openzeppelin.com
8-
9-
### Installation
10-
11-
`npm install @openzeppelin/wizard-uniswap-hooks`
12-
13-
### Hook templates
14-
15-
The following hook templates are supported:
16-
- `BaseHook` - Provides standard entry points, permission checks, and validation utilities for building hooks
17-
- `BaseAsyncSwap` - Enables asynchronous swap execution with separate fulfillment
18-
- `BaseCustomAccounting` - Allows custom liquidity accounting and shares management
19-
- `BaseCustomCurve` - Enables custom pricing curves and swap calculations
20-
- `BaseDynamicFee` - Provides dynamic fee calculation based on pool conditions
21-
- `BaseOverrideFee` - Allows overriding the pool's swap fee
22-
- `BaseDynamicAfterFee` - Implements dynamic fees with post-swap adjustments
23-
- `BaseHookFee` - Enables hooks to collect fees on swaps
24-
- `AntiSandwichHook` - Protects against sandwich attacks with penalty fees
25-
- `LimitOrderHook` - Implements limit order functionality
26-
- `LiquidityPenaltyHook` - Applies penalties to early liquidity removals
27-
- `ReHypothecationHook` - Enables yield generation from deposited liquidity
28-
29-
### Examples
30-
31-
Import the hooks API from the `@openzeppelin/wizard-uniswap-hooks` package:
32-
33-
```js
34-
import { hooks } from '@openzeppelin/wizard-uniswap-hooks';
35-
```
36-
37-
To generate the source code for a basic hook with all of the default settings:
38-
```js
39-
const contract = hooks.print();
40-
```
41-
42-
To generate the source code for a hook with a custom name and specific hook type:
43-
```js
44-
const contract = hooks.print({
45-
name: 'MyDynamicFeeHook',
46-
hook: 'BaseDynamicFee',
47-
});
48-
```
49-
50-
To generate the source code for a hook with pausability and access control:
51-
```js
52-
const contract = hooks.print({
53-
name: 'MyPausableHook',
54-
hook: 'BaseHook',
55-
pausable: true,
56-
access: 'ownable',
57-
});
58-
```
59-
60-
To generate the source code for a custom accounting hook with ERC20 shares:
61-
```js
62-
const contract = hooks.print({
63-
name: 'MyLiquidityHook',
64-
hook: 'BaseCustomAccounting',
65-
shares: {
66-
options: 'ERC20',
67-
name: 'My Liquidity Shares',
68-
symbol: 'MLS',
69-
},
70-
});
71-
```
72-
73-
To generate the source code for a hook with specific permissions:
74-
```js
75-
const contract = hooks.print({
76-
name: 'MySwapHook',
77-
hook: 'BaseHook',
78-
permissions: {
79-
beforeSwap: true,
80-
afterSwap: true,
81-
beforeInitialize: false,
82-
afterInitialize: false,
83-
beforeAddLiquidity: false,
84-
beforeRemoveLiquidity: false,
85-
afterAddLiquidity: false,
86-
afterRemoveLiquidity: false,
87-
beforeDonate: false,
88-
afterDonate: false,
89-
beforeSwapReturnDelta: false,
90-
afterSwapReturnDelta: false,
91-
afterAddLiquidityReturnDelta: false,
92-
afterRemoveLiquidityReturnDelta: false,
93-
},
94-
});
95-
```
96-
97-
To generate the source code for a hook with utility libraries:
98-
```js
99-
const contract = hooks.print({
100-
name: 'MyAdvancedHook',
101-
hook: 'BaseHook',
102-
currencySettler: true, // Includes CurrencySettler library
103-
safeCast: true, // Includes SafeCast library
104-
transientStorage: true, // Includes TransientSlot and SlotDerivation libraries
105-
});
106-
```
107-
108-
### Options Reference
109-
110-
The `HooksOptions` interface supports the following properties:
111-
112-
- **`hook`** (`HookName`): The base hook template to extend. Default: `'BaseHook'`
113-
- **`name`** (`string`): The name of the hook contract. Default: `'MyHook'`
114-
- **`pausable`** (`boolean`): Whether to include emergency pause functionality. Default: `false`
115-
- **`access`** (`'ownable' | 'roles' | 'managed' | false`): Access control mechanism. Default: `false`
116-
- **`currencySettler`** (`boolean`): Include CurrencySettler library for currency operations. Default: `false`
117-
- **`safeCast`** (`boolean`): Include SafeCast library for safe type casting. Default: `false`
118-
- **`transientStorage`** (`boolean`): Include transient storage utilities. Default: `false`
119-
- **`shares`** (`Shares`): Configuration for token shares. Default: `{ options: false }`
120-
- **`options`** (`false | 'ERC20' | 'ERC6909' | 'ERC1155'`): The token standard to use for shares
121-
- **`name`** (`string`, optional): Token name (for ERC20)
122-
- **`symbol`** (`string`, optional): Token symbol (for ERC20)
123-
- **`uri`** (`string`, optional): Token URI (for ERC1155)
124-
- **`permissions`** (`Permissions`): Hook lifecycle permissions bitmap with 14 different permissions. Default: all `false`
125-
- **`inputs`** (`object`): Hook-specific configuration inputs. Default: `{ blockNumberOffset: 10 }`
126-
- **`info`** (`Info`, optional): Contract metadata (license, security contact)
127-
128-
> Note: Upgradeability is not yet available for Uniswap v4 Hooks.
1+
# Changelog
Lines changed: 128 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,128 @@
1-
# OpenZeppelin Contracts Wizard for Uniswap Hooks
1+
# OpenZeppelin Contracts Wizard for Uniswap Hooks
2+
3+
[![NPM Package](https://img.shields.io/npm/v/@openzeppelin/wizard-uniswap-hooks?color=%234e5de4)](https://www.npmjs.com/package/@openzeppelin/wizard-uniswap-hooks)
4+
5+
Interactively build a [Uniswap v4 Hook](https://docs.uniswap.org/contracts/v4/concepts/hooks) contract out of components from [OpenZeppelin Uniswap Hooks](https://github.com/OpenZeppelin/uniswap-hooks) and [OpenZeppelin Contracts](https://github.com/OpenZeppelin/openzeppelin-contracts). Provide parameters and desired features for the hook template that you want, and the Wizard will generate all of the necessary code. The resulting code is ready to be compiled and deployed, or it can serve as a starting point and customized further with application specific logic.
6+
7+
This package provides a programmatic API. For a web interface, see https://wizard.openzeppelin.com
8+
9+
### Installation
10+
11+
`npm install @openzeppelin/wizard-uniswap-hooks`
12+
13+
### Hook templates
14+
15+
The following hook templates are supported:
16+
- `BaseHook` - Provides standard entry points, permission checks, and validation utilities for building hooks
17+
- `BaseAsyncSwap` - Enables asynchronous swap execution with separate fulfillment
18+
- `BaseCustomAccounting` - Allows custom liquidity accounting and shares management
19+
- `BaseCustomCurve` - Enables custom pricing curves and swap calculations
20+
- `BaseDynamicFee` - Provides dynamic fee calculation based on pool conditions
21+
- `BaseOverrideFee` - Allows overriding the pool's swap fee
22+
- `BaseDynamicAfterFee` - Implements dynamic fees with post-swap adjustments
23+
- `BaseHookFee` - Enables hooks to collect fees on swaps
24+
- `AntiSandwichHook` - Protects against sandwich attacks with penalty fees
25+
- `LimitOrderHook` - Implements limit order functionality
26+
- `LiquidityPenaltyHook` - Applies penalties to early liquidity removals
27+
- `ReHypothecationHook` - Enables yield generation from deposited liquidity
28+
29+
### Examples
30+
31+
Import the hooks API from the `@openzeppelin/wizard-uniswap-hooks` package:
32+
33+
```js
34+
import { hooks } from '@openzeppelin/wizard-uniswap-hooks';
35+
```
36+
37+
To generate the source code for a basic hook with all of the default settings:
38+
```js
39+
const contract = hooks.print();
40+
```
41+
42+
To generate the source code for a hook with a custom name and specific hook type:
43+
```js
44+
const contract = hooks.print({
45+
name: 'MyDynamicFeeHook',
46+
hook: 'BaseDynamicFee',
47+
});
48+
```
49+
50+
To generate the source code for a hook with pausability and access control:
51+
```js
52+
const contract = hooks.print({
53+
name: 'MyPausableHook',
54+
hook: 'BaseHook',
55+
pausable: true,
56+
access: 'ownable',
57+
});
58+
```
59+
60+
To generate the source code for a custom accounting hook with ERC20 shares:
61+
```js
62+
const contract = hooks.print({
63+
name: 'MyLiquidityHook',
64+
hook: 'BaseCustomAccounting',
65+
shares: {
66+
options: 'ERC20',
67+
name: 'My Liquidity Shares',
68+
symbol: 'MLS',
69+
},
70+
});
71+
```
72+
73+
To generate the source code for a hook with specific permissions:
74+
```js
75+
const contract = hooks.print({
76+
name: 'MySwapHook',
77+
hook: 'BaseHook',
78+
permissions: {
79+
beforeSwap: true,
80+
afterSwap: true,
81+
beforeInitialize: false,
82+
afterInitialize: false,
83+
beforeAddLiquidity: false,
84+
beforeRemoveLiquidity: false,
85+
afterAddLiquidity: false,
86+
afterRemoveLiquidity: false,
87+
beforeDonate: false,
88+
afterDonate: false,
89+
beforeSwapReturnDelta: false,
90+
afterSwapReturnDelta: false,
91+
afterAddLiquidityReturnDelta: false,
92+
afterRemoveLiquidityReturnDelta: false,
93+
},
94+
});
95+
```
96+
97+
To generate the source code for a hook with utility libraries:
98+
```js
99+
const contract = hooks.print({
100+
name: 'MyAdvancedHook',
101+
hook: 'BaseHook',
102+
currencySettler: true, // Includes CurrencySettler library
103+
safeCast: true, // Includes SafeCast library
104+
transientStorage: true, // Includes TransientSlot and SlotDerivation libraries
105+
});
106+
```
107+
108+
### Options Reference
109+
110+
The `HooksOptions` interface supports the following properties:
111+
112+
- **`hook`** (`HookName`): The base hook template to extend. Default: `'BaseHook'`
113+
- **`name`** (`string`): The name of the hook contract. Default: `'MyHook'`
114+
- **`pausable`** (`boolean`): Whether to include emergency pause functionality. Default: `false`
115+
- **`access`** (`'ownable' | 'roles' | 'managed' | false`): Access control mechanism. Default: `false`
116+
- **`currencySettler`** (`boolean`): Include CurrencySettler library for currency operations. Default: `false`
117+
- **`safeCast`** (`boolean`): Include SafeCast library for safe type casting. Default: `false`
118+
- **`transientStorage`** (`boolean`): Include transient storage utilities. Default: `false`
119+
- **`shares`** (`Shares`): Configuration for token shares. Default: `{ options: false }`
120+
- **`options`** (`false | 'ERC20' | 'ERC6909' | 'ERC1155'`): The token standard to use for shares
121+
- **`name`** (`string`, optional): Token name (for ERC20)
122+
- **`symbol`** (`string`, optional): Token symbol (for ERC20)
123+
- **`uri`** (`string`, optional): Token URI (for ERC1155)
124+
- **`permissions`** (`Permissions`): Hook lifecycle permissions bitmap with 14 different permissions. Default: all `false`
125+
- **`inputs`** (`object`): Hook-specific configuration inputs. Default: `{ blockNumberOffset: 10 }`
126+
- **`info`** (`Info`, optional): Contract metadata (license, security contact)
127+
128+
> Note: Upgradeability is not yet available for Uniswap v4 Hooks.

packages/core/uniswap-hooks/package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@
2121
"test:update-snapshots": "ava --update-snapshots",
2222
"test:watch": "ava --watch"
2323
},
24+
"dependencies": {
25+
"@openzeppelin/wizard": "^0.10.3"
26+
},
2427
"devDependencies": {
2528
"@openzeppelin/contracts": "^5.5.0",
2629
"@openzeppelin/uniswap-hooks": "^1.2.1",
@@ -35,4 +38,4 @@
3538
"ts-node": "^10.4.0",
3639
"typescript": "^5.0.0"
3740
}
38-
}
41+
}

0 commit comments

Comments
 (0)