@rocketh/router 0.17.12 → 0.17.13
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.
- package/README.md +255 -3
- package/package.json +5 -4
package/README.md
CHANGED
|
@@ -1,7 +1,259 @@
|
|
|
1
1
|
# @rocketh/router
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Router-based proxy deployment for Rocketh. Deploy contracts using a selector-based routing pattern where multiple implementation contracts are accessed through a single entry point.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## Features
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
- 🔀 **Selector Routing** - Route function calls to different implementations based on function selectors
|
|
8
|
+
- 📦 **ABI Merging** - Automatically merge ABIs from all route contracts
|
|
9
|
+
- 🔄 **Deterministic Deployment** - Support for CREATE2 deterministic addresses
|
|
10
|
+
- 📄 **Documentation Merging** - Merge devdoc and userdoc from all routes
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
# Using pnpm
|
|
16
|
+
pnpm add @rocketh/router
|
|
17
|
+
|
|
18
|
+
# Using npm
|
|
19
|
+
npm install @rocketh/router
|
|
20
|
+
|
|
21
|
+
# Using yarn
|
|
22
|
+
yarn add @rocketh/router
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Usage
|
|
26
|
+
|
|
27
|
+
### Basic Router Deployment
|
|
28
|
+
|
|
29
|
+
```typescript
|
|
30
|
+
import { deployScript, artifacts } from '../rocketh/deploy.js';
|
|
31
|
+
|
|
32
|
+
export default deployScript(
|
|
33
|
+
async ({ deployViaRouter, namedAccounts }) => {
|
|
34
|
+
const { deployer } = namedAccounts;
|
|
35
|
+
|
|
36
|
+
await deployViaRouter(
|
|
37
|
+
'MyRouter',
|
|
38
|
+
{
|
|
39
|
+
account: deployer,
|
|
40
|
+
},
|
|
41
|
+
[
|
|
42
|
+
{
|
|
43
|
+
name: 'UserModule',
|
|
44
|
+
artifact: artifacts.UserModule,
|
|
45
|
+
args: [],
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
name: 'PaymentModule',
|
|
49
|
+
artifact: artifacts.PaymentModule,
|
|
50
|
+
args: [],
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
name: 'AdminModule',
|
|
54
|
+
artifact: artifacts.AdminModule,
|
|
55
|
+
args: [],
|
|
56
|
+
},
|
|
57
|
+
]
|
|
58
|
+
);
|
|
59
|
+
},
|
|
60
|
+
{ tags: ['MyRouter'] }
|
|
61
|
+
);
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Using the Extension
|
|
65
|
+
|
|
66
|
+
First, add the router extension to your Rocketh config:
|
|
67
|
+
|
|
68
|
+
```typescript
|
|
69
|
+
// rocketh/config.ts
|
|
70
|
+
import * as deployExtension from '@rocketh/deploy';
|
|
71
|
+
import * as routerExtension from '@rocketh/router';
|
|
72
|
+
|
|
73
|
+
const extensions = {
|
|
74
|
+
...deployExtension,
|
|
75
|
+
...routerExtension,
|
|
76
|
+
};
|
|
77
|
+
export { extensions };
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Then use it in your deploy scripts:
|
|
81
|
+
|
|
82
|
+
```typescript
|
|
83
|
+
import { deployScript, artifacts } from '../rocketh/deploy.js';
|
|
84
|
+
|
|
85
|
+
export default deployScript(
|
|
86
|
+
async (env) => {
|
|
87
|
+
const { deployer } = env.namedAccounts;
|
|
88
|
+
|
|
89
|
+
// deployViaRouter is now available on env
|
|
90
|
+
await env.deployViaRouter(
|
|
91
|
+
'MyRouter',
|
|
92
|
+
{ account: deployer },
|
|
93
|
+
[
|
|
94
|
+
{ name: 'ModuleA', artifact: artifacts.ModuleA, args: [] },
|
|
95
|
+
{ name: 'ModuleB', artifact: artifacts.ModuleB, args: [] },
|
|
96
|
+
]
|
|
97
|
+
);
|
|
98
|
+
},
|
|
99
|
+
{ tags: ['MyRouter'] }
|
|
100
|
+
);
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## API Reference
|
|
104
|
+
|
|
105
|
+
### `deployViaRouter(env)`
|
|
106
|
+
|
|
107
|
+
Creates a router deployment function.
|
|
108
|
+
|
|
109
|
+
**Parameters:**
|
|
110
|
+
- `env` - The Rocketh environment
|
|
111
|
+
|
|
112
|
+
**Returns:** A deployment function with the signature:
|
|
113
|
+
|
|
114
|
+
```typescript
|
|
115
|
+
function deployViaRouter<TAbi extends Abi>(
|
|
116
|
+
name: string,
|
|
117
|
+
params: RouterEnhancedDeploymentConstruction,
|
|
118
|
+
routes: Route<Abi>[],
|
|
119
|
+
options?: RouterDeployOptions
|
|
120
|
+
): Promise<DeployResult<TAbi>>
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### Deployment Parameters
|
|
124
|
+
|
|
125
|
+
#### `name`
|
|
126
|
+
The name for the router deployment.
|
|
127
|
+
|
|
128
|
+
#### `params`
|
|
129
|
+
- `account` - The deployer account (named account or address)
|
|
130
|
+
|
|
131
|
+
#### `routes`
|
|
132
|
+
Array of route definitions:
|
|
133
|
+
```typescript
|
|
134
|
+
interface Route<TAbi extends Abi> {
|
|
135
|
+
name: string; // Name for this route implementation
|
|
136
|
+
artifact: Artifact<TAbi>; // Contract artifact
|
|
137
|
+
args?: unknown[]; // Constructor arguments
|
|
138
|
+
}
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
#### `options`
|
|
142
|
+
```typescript
|
|
143
|
+
interface RouterDeployOptions extends DeployOptions {
|
|
144
|
+
extraABIs?: Abi[]; // Additional ABIs to merge
|
|
145
|
+
routerContract?: { // Custom router contract
|
|
146
|
+
type: 'custom';
|
|
147
|
+
artifact: Artifact;
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## How It Works
|
|
153
|
+
|
|
154
|
+
1. **Deploy Routes**: Each route contract is deployed separately as `{name}_Router_{routeName}_Route`
|
|
155
|
+
2. **Build Selector Map**: Function selectors from all routes are collected and mapped to implementation indices
|
|
156
|
+
3. **Deploy Router**: The router contract is deployed with the selector map and implementation addresses
|
|
157
|
+
4. **Merge ABIs**: All route ABIs are merged into a single ABI for the final deployment
|
|
158
|
+
|
|
159
|
+
### Selector Map Format
|
|
160
|
+
|
|
161
|
+
The router uses a sorted array of `bytes6` values where:
|
|
162
|
+
- First 4 bytes: Function selector
|
|
163
|
+
- Last 2 bytes: Implementation index (1-based, 0 means no implementation)
|
|
164
|
+
|
|
165
|
+
```
|
|
166
|
+
[0x12345678 + 0x0001] -> Function 0x12345678 routes to implementation 1
|
|
167
|
+
[0xabcdef01 + 0x0002] -> Function 0xabcdef01 routes to implementation 2
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
## Example: Multi-Module Token
|
|
171
|
+
|
|
172
|
+
```typescript
|
|
173
|
+
// deploy/deploy_MultiModuleToken.ts
|
|
174
|
+
import { deployScript, artifacts } from '../rocketh/deploy.js';
|
|
175
|
+
|
|
176
|
+
export default deployScript(
|
|
177
|
+
async ({ deployViaRouter, namedAccounts }) => {
|
|
178
|
+
const { deployer, treasury } = namedAccounts;
|
|
179
|
+
|
|
180
|
+
await deployViaRouter(
|
|
181
|
+
'MultiModuleToken',
|
|
182
|
+
{
|
|
183
|
+
account: deployer,
|
|
184
|
+
},
|
|
185
|
+
[
|
|
186
|
+
{
|
|
187
|
+
name: 'ERC20Core',
|
|
188
|
+
artifact: artifacts.ERC20CoreModule,
|
|
189
|
+
args: ['My Token', 'MTK', 18],
|
|
190
|
+
},
|
|
191
|
+
{
|
|
192
|
+
name: 'Mintable',
|
|
193
|
+
artifact: artifacts.MintableModule,
|
|
194
|
+
args: [treasury],
|
|
195
|
+
},
|
|
196
|
+
{
|
|
197
|
+
name: 'Burnable',
|
|
198
|
+
artifact: artifacts.BurnableModule,
|
|
199
|
+
args: [],
|
|
200
|
+
},
|
|
201
|
+
{
|
|
202
|
+
name: 'Pausable',
|
|
203
|
+
artifact: artifacts.PausableModule,
|
|
204
|
+
args: [deployer], // Admin address
|
|
205
|
+
},
|
|
206
|
+
],
|
|
207
|
+
{
|
|
208
|
+
deterministic: true, // Deploy deterministically
|
|
209
|
+
}
|
|
210
|
+
);
|
|
211
|
+
},
|
|
212
|
+
{ tags: ['MultiModuleToken'] }
|
|
213
|
+
);
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
## Custom Router Contract
|
|
217
|
+
|
|
218
|
+
You can provide a custom router contract that follows the same interface:
|
|
219
|
+
|
|
220
|
+
```typescript
|
|
221
|
+
await deployViaRouter(
|
|
222
|
+
'MyRouter',
|
|
223
|
+
{ account: deployer },
|
|
224
|
+
routes,
|
|
225
|
+
{
|
|
226
|
+
routerContract: {
|
|
227
|
+
type: 'custom',
|
|
228
|
+
artifact: myCustomRouterArtifact,
|
|
229
|
+
},
|
|
230
|
+
}
|
|
231
|
+
);
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
The custom router must accept constructor arguments in the format:
|
|
235
|
+
```solidity
|
|
236
|
+
struct RouterParams {
|
|
237
|
+
address fallbackImplementation;
|
|
238
|
+
address[] implementations;
|
|
239
|
+
bytes6[] sigMap;
|
|
240
|
+
}
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
## Deployment Artifacts
|
|
244
|
+
|
|
245
|
+
After deployment, several artifacts are created:
|
|
246
|
+
|
|
247
|
+
- `{name}` - The main router with merged ABI
|
|
248
|
+
- `{name}_Router` - The router proxy contract
|
|
249
|
+
- `{name}_Router_{routeName}_Route` - Each route implementation
|
|
250
|
+
|
|
251
|
+
## Related Packages
|
|
252
|
+
|
|
253
|
+
- [`rocketh`](../rocketh) - Core deployment environment
|
|
254
|
+
- [`@rocketh/deploy`](../rocketh-deploy) - Standard deployment functions
|
|
255
|
+
- [`@rocketh/proxy`](../rocketh-proxy) - Proxy deployment patterns
|
|
256
|
+
|
|
257
|
+
## License
|
|
258
|
+
|
|
259
|
+
[MIT](../../LICENSE)
|
package/package.json
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rocketh/router",
|
|
3
|
-
"version": "0.17.
|
|
3
|
+
"version": "0.17.13",
|
|
4
|
+
"license": "MIT",
|
|
4
5
|
"description": "provide router based proxy deployment for rocketh",
|
|
5
6
|
"publishConfig": {
|
|
6
7
|
"access": "public"
|
|
@@ -27,11 +28,11 @@
|
|
|
27
28
|
"named-logs": "^0.4.1",
|
|
28
29
|
"solidity-proxy": "^0.4.2",
|
|
29
30
|
"viem": "^2.45.0",
|
|
30
|
-
"@rocketh/core": "0.17.
|
|
31
|
-
"@rocketh/deploy": "0.17.
|
|
31
|
+
"@rocketh/core": "0.17.11",
|
|
32
|
+
"@rocketh/deploy": "0.17.11"
|
|
32
33
|
},
|
|
33
34
|
"devDependencies": {
|
|
34
|
-
"as-soon": "^0.1.
|
|
35
|
+
"as-soon": "^0.1.5",
|
|
35
36
|
"rimraf": "^6.1.2",
|
|
36
37
|
"typescript": "^5.9.3"
|
|
37
38
|
},
|