@rocketh/test-utils 0.0.2
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/LICENSE +21 -0
- package/README.md +7 -0
- package/dist/index.d.ts +185 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +340 -0
- package/dist/index.js.map +1 -0
- package/package.json +37 -0
- package/src/index.ts +488 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2018-present Ronan Sandford
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# @rocketh/test-utils
|
|
2
|
+
|
|
3
|
+
Test utilities for rocketh packages, providing helper functions and utilities used across rocketh's test suites.
|
|
4
|
+
|
|
5
|
+
For full documentation, visit [rocketh.dev](https://rocketh.dev).
|
|
6
|
+
|
|
7
|
+
For hardhat-deploy documentation, see [rocketh.dev/hardhat-deploy/](https://rocketh.dev/hardhat-deploy/).
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @rocketh/test-utils
|
|
3
|
+
*
|
|
4
|
+
* Test utilities for rocketh packages. Provides mock environments, providers,
|
|
5
|
+
* and artifacts for testing deployment scenarios.
|
|
6
|
+
*/
|
|
7
|
+
import type { Abi, Artifact, Environment } from '@rocketh/core/types';
|
|
8
|
+
import type { EIP1193Provider } from 'eip-1193';
|
|
9
|
+
/**
|
|
10
|
+
* Configuration for mock provider responses.
|
|
11
|
+
* Allows tests to specify custom return values for specific RPC methods.
|
|
12
|
+
*/
|
|
13
|
+
export type MockProviderConfig = {
|
|
14
|
+
/**
|
|
15
|
+
* Override responses for specific RPC methods.
|
|
16
|
+
* Can be a static value or a function that receives params and returns a value.
|
|
17
|
+
*/
|
|
18
|
+
responses?: {
|
|
19
|
+
[method: string]: unknown | ((params?: unknown[]) => unknown | Promise<unknown>);
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Called when an unmocked method is requested.
|
|
23
|
+
* If not provided, returns null and logs a warning.
|
|
24
|
+
*/
|
|
25
|
+
onUnmockedMethod?: (method: string, params?: unknown[]) => unknown | Promise<unknown>;
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* A mock EIP-1193 provider with configurable responses.
|
|
29
|
+
*/
|
|
30
|
+
export type MockProvider = EIP1193Provider & {
|
|
31
|
+
/**
|
|
32
|
+
* Update the configuration for the mock provider.
|
|
33
|
+
*/
|
|
34
|
+
setConfig: (config: MockProviderConfig) => void;
|
|
35
|
+
/**
|
|
36
|
+
* Update or add a specific response for an RPC method.
|
|
37
|
+
*/
|
|
38
|
+
setResponse: (method: string, response: unknown | ((params?: unknown[]) => unknown | Promise<unknown>)) => void;
|
|
39
|
+
/**
|
|
40
|
+
* Get all recorded requests made to the provider.
|
|
41
|
+
*/
|
|
42
|
+
getRequests: () => Array<{
|
|
43
|
+
method: string;
|
|
44
|
+
params?: unknown[];
|
|
45
|
+
}>;
|
|
46
|
+
/**
|
|
47
|
+
* Clear recorded requests.
|
|
48
|
+
*/
|
|
49
|
+
clearRequests: () => void;
|
|
50
|
+
/**
|
|
51
|
+
* Add an event listener (no-op in mock).
|
|
52
|
+
*/
|
|
53
|
+
on: (event: string, listener: (...args: unknown[]) => void) => MockProvider;
|
|
54
|
+
/**
|
|
55
|
+
* Remove an event listener (no-op in mock).
|
|
56
|
+
*/
|
|
57
|
+
removeListener: (event: string, listener: (...args: unknown[]) => void) => MockProvider;
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* Options for creating a mock environment.
|
|
61
|
+
*/
|
|
62
|
+
export type MockEnvironmentOptions = {
|
|
63
|
+
/**
|
|
64
|
+
* Custom provider configuration.
|
|
65
|
+
*/
|
|
66
|
+
providerConfig?: MockProviderConfig;
|
|
67
|
+
/**
|
|
68
|
+
* Custom named accounts. Defaults to deployer, user1, user2.
|
|
69
|
+
*/
|
|
70
|
+
namedAccounts?: Record<string, `0x${string}`>;
|
|
71
|
+
/**
|
|
72
|
+
* Chain ID. Defaults to 31337 (localhost).
|
|
73
|
+
*/
|
|
74
|
+
chainId?: number;
|
|
75
|
+
/**
|
|
76
|
+
* Chain name. Defaults to 'localhost'.
|
|
77
|
+
*/
|
|
78
|
+
chainName?: string;
|
|
79
|
+
/**
|
|
80
|
+
* Tags to set on the environment.
|
|
81
|
+
*/
|
|
82
|
+
tags?: Record<string, boolean>;
|
|
83
|
+
};
|
|
84
|
+
/**
|
|
85
|
+
* Result of creating a mock environment.
|
|
86
|
+
*/
|
|
87
|
+
export type MockEnvironmentResult = {
|
|
88
|
+
/**
|
|
89
|
+
* The mock environment.
|
|
90
|
+
*/
|
|
91
|
+
env: Environment;
|
|
92
|
+
/**
|
|
93
|
+
* The mock provider (for inspecting/updating responses).
|
|
94
|
+
*/
|
|
95
|
+
provider: MockProvider;
|
|
96
|
+
/**
|
|
97
|
+
* The deployments record (for inspecting saved deployments).
|
|
98
|
+
*/
|
|
99
|
+
deployments: Record<string, unknown>;
|
|
100
|
+
};
|
|
101
|
+
/**
|
|
102
|
+
* Creates a mock EIP-1193 provider with configurable responses.
|
|
103
|
+
*
|
|
104
|
+
* @param config - Optional configuration for custom responses
|
|
105
|
+
* @returns A mock provider that can be used in tests
|
|
106
|
+
*
|
|
107
|
+
* @example
|
|
108
|
+
* ```typescript
|
|
109
|
+
* const provider = createMockProvider({
|
|
110
|
+
* responses: {
|
|
111
|
+
* eth_getCode: '0x6080...', // Return deployed code
|
|
112
|
+
* eth_getBalance: (params) => {
|
|
113
|
+
* const address = params?.[0];
|
|
114
|
+
* return address === '0x123...' ? '0x0' : '0x1000';
|
|
115
|
+
* },
|
|
116
|
+
* },
|
|
117
|
+
* });
|
|
118
|
+
* ```
|
|
119
|
+
*/
|
|
120
|
+
export declare function createMockProvider(config?: MockProviderConfig): MockProvider;
|
|
121
|
+
/**
|
|
122
|
+
* Default ABI for mock artifacts.
|
|
123
|
+
*/
|
|
124
|
+
declare const DEFAULT_ABI: Abi;
|
|
125
|
+
/**
|
|
126
|
+
* Creates a mock artifact for testing.
|
|
127
|
+
*
|
|
128
|
+
* @param name - Contract name
|
|
129
|
+
* @param abi - Optional ABI (defaults to a simple contract with constructor and getValue)
|
|
130
|
+
* @returns A mock artifact object
|
|
131
|
+
*
|
|
132
|
+
* @example
|
|
133
|
+
* ```typescript
|
|
134
|
+
* const artifact = createMockArtifact('MyContract', [
|
|
135
|
+
* {
|
|
136
|
+
* type: 'constructor',
|
|
137
|
+
* inputs: [{type: 'address', name: 'owner'}],
|
|
138
|
+
* stateMutability: 'nonpayable',
|
|
139
|
+
* },
|
|
140
|
+
* ]);
|
|
141
|
+
* ```
|
|
142
|
+
*/
|
|
143
|
+
export declare function createMockArtifact<TAbi extends Abi = typeof DEFAULT_ABI>(name: string, abi?: TAbi): Artifact<TAbi>;
|
|
144
|
+
export declare function createExampleArtifact(name: string, templateNumber: number): Artifact<Abi>;
|
|
145
|
+
/**
|
|
146
|
+
* Creates a mock artifact with library references.
|
|
147
|
+
*
|
|
148
|
+
* @param name - Contract name
|
|
149
|
+
* @param libraryName - Name of the library to reference
|
|
150
|
+
* @param abi - Optional ABI
|
|
151
|
+
* @returns A mock artifact with library link references
|
|
152
|
+
*
|
|
153
|
+
* @example
|
|
154
|
+
* ```typescript
|
|
155
|
+
* const artifact = createMockArtifactWithLibrary('Calculator', 'MathLib');
|
|
156
|
+
* ```
|
|
157
|
+
*/
|
|
158
|
+
export declare function createMockArtifactWithLibrary<TAbi extends Abi = typeof DEFAULT_ABI>(name: string, libraryName: string, abi?: TAbi): Artifact<TAbi>;
|
|
159
|
+
/**
|
|
160
|
+
* Creates a mock environment for testing deployments.
|
|
161
|
+
*
|
|
162
|
+
* @param options - Optional configuration
|
|
163
|
+
* @returns An object containing the environment, provider, and deployments record
|
|
164
|
+
*
|
|
165
|
+
* @example
|
|
166
|
+
* ```typescript
|
|
167
|
+
* // Basic usage
|
|
168
|
+
* const {env, provider} = createMockEnvironment();
|
|
169
|
+
*
|
|
170
|
+
* // With custom provider responses
|
|
171
|
+
* const {env, provider} = createMockEnvironment({
|
|
172
|
+
* providerConfig: {
|
|
173
|
+
* responses: {
|
|
174
|
+
* eth_getCode: '0x6080...', // Simulate deployed contract
|
|
175
|
+
* },
|
|
176
|
+
* },
|
|
177
|
+
* });
|
|
178
|
+
*
|
|
179
|
+
* // Update responses during test
|
|
180
|
+
* provider.setResponse('eth_getCode', '0x'); // Reset to empty
|
|
181
|
+
* ```
|
|
182
|
+
*/
|
|
183
|
+
export declare function createMockEnvironment(options?: MockEnvironmentOptions): MockEnvironmentResult;
|
|
184
|
+
export type { Environment } from '@rocketh/core/types';
|
|
185
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,340 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @rocketh/test-utils
|
|
3
|
+
*
|
|
4
|
+
* Test utilities for rocketh packages. Provides mock environments, providers,
|
|
5
|
+
* and artifacts for testing deployment scenarios.
|
|
6
|
+
*/
|
|
7
|
+
// ============================================================================
|
|
8
|
+
// Mock Provider
|
|
9
|
+
// ============================================================================
|
|
10
|
+
/**
|
|
11
|
+
* Default RPC method responses for a mock provider.
|
|
12
|
+
* These simulate a basic EVM environment.
|
|
13
|
+
*/
|
|
14
|
+
function getDefaultResponses(txCounter) {
|
|
15
|
+
return {
|
|
16
|
+
eth_sendTransaction: () => {
|
|
17
|
+
txCounter.value++;
|
|
18
|
+
return `0x${'0'.repeat(63)}${txCounter.value.toString(16)}`;
|
|
19
|
+
},
|
|
20
|
+
eth_sendRawTransaction: () => {
|
|
21
|
+
txCounter.value++;
|
|
22
|
+
return `0x${'1'.repeat(63)}${txCounter.value.toString(16)}`;
|
|
23
|
+
},
|
|
24
|
+
eth_getCode: () => '0x',
|
|
25
|
+
eth_getBalance: () => '0x' + BigInt('1000000000000000000000').toString(16),
|
|
26
|
+
evm_mine: () => null,
|
|
27
|
+
eth_getTransactionReceipt: (params) => ({
|
|
28
|
+
contractAddress: ('0x' + 'a'.repeat(40)),
|
|
29
|
+
status: '0x1',
|
|
30
|
+
blockNumber: '0x1',
|
|
31
|
+
blockHash: `0x${'b'.repeat(64)}`,
|
|
32
|
+
transactionHash: params?.[0] || `0x${'c'.repeat(64)}`,
|
|
33
|
+
gasUsed: '0x5208',
|
|
34
|
+
}),
|
|
35
|
+
eth_chainId: () => '0x7a69', // 31337
|
|
36
|
+
eth_blockNumber: () => '0x1',
|
|
37
|
+
eth_gasPrice: () => '0x3b9aca00', // 1 gwei
|
|
38
|
+
eth_estimateGas: () => '0x5208', // 21000
|
|
39
|
+
eth_getTransactionCount: () => '0x0',
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Creates a mock EIP-1193 provider with configurable responses.
|
|
44
|
+
*
|
|
45
|
+
* @param config - Optional configuration for custom responses
|
|
46
|
+
* @returns A mock provider that can be used in tests
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* ```typescript
|
|
50
|
+
* const provider = createMockProvider({
|
|
51
|
+
* responses: {
|
|
52
|
+
* eth_getCode: '0x6080...', // Return deployed code
|
|
53
|
+
* eth_getBalance: (params) => {
|
|
54
|
+
* const address = params?.[0];
|
|
55
|
+
* return address === '0x123...' ? '0x0' : '0x1000';
|
|
56
|
+
* },
|
|
57
|
+
* },
|
|
58
|
+
* });
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
61
|
+
export function createMockProvider(config = {}) {
|
|
62
|
+
const txCounter = { value: 0 };
|
|
63
|
+
const defaultResponses = getDefaultResponses(txCounter);
|
|
64
|
+
let currentConfig = { ...config };
|
|
65
|
+
const requests = [];
|
|
66
|
+
const request = async ({ method, params }) => {
|
|
67
|
+
requests.push({ method, params: params });
|
|
68
|
+
// Check custom responses first
|
|
69
|
+
const customResponse = currentConfig.responses?.[method];
|
|
70
|
+
if (customResponse !== undefined) {
|
|
71
|
+
if (typeof customResponse === 'function') {
|
|
72
|
+
return customResponse(params);
|
|
73
|
+
}
|
|
74
|
+
return customResponse;
|
|
75
|
+
}
|
|
76
|
+
// Check default responses
|
|
77
|
+
const defaultResponse = defaultResponses[method];
|
|
78
|
+
if (defaultResponse !== undefined) {
|
|
79
|
+
if (typeof defaultResponse === 'function') {
|
|
80
|
+
return defaultResponse(params);
|
|
81
|
+
}
|
|
82
|
+
return defaultResponse;
|
|
83
|
+
}
|
|
84
|
+
// Handle unmocked method
|
|
85
|
+
if (currentConfig.onUnmockedMethod) {
|
|
86
|
+
return currentConfig.onUnmockedMethod(method, params);
|
|
87
|
+
}
|
|
88
|
+
console.warn(`Unmocked provider method: ${method}`);
|
|
89
|
+
return null;
|
|
90
|
+
};
|
|
91
|
+
const provider = {
|
|
92
|
+
request: request,
|
|
93
|
+
on: () => provider, // No-op event listener
|
|
94
|
+
removeListener: () => provider, // No-op event listener removal
|
|
95
|
+
setConfig: (newConfig) => {
|
|
96
|
+
currentConfig = { ...newConfig };
|
|
97
|
+
},
|
|
98
|
+
setResponse: (method, response) => {
|
|
99
|
+
if (!currentConfig.responses) {
|
|
100
|
+
currentConfig.responses = {};
|
|
101
|
+
}
|
|
102
|
+
currentConfig.responses[method] = response;
|
|
103
|
+
},
|
|
104
|
+
getRequests: () => [...requests],
|
|
105
|
+
clearRequests: () => {
|
|
106
|
+
requests.length = 0;
|
|
107
|
+
},
|
|
108
|
+
};
|
|
109
|
+
return provider;
|
|
110
|
+
}
|
|
111
|
+
// ============================================================================
|
|
112
|
+
// Mock Artifacts
|
|
113
|
+
// ============================================================================
|
|
114
|
+
/**
|
|
115
|
+
* Default ABI for mock artifacts.
|
|
116
|
+
*/
|
|
117
|
+
const DEFAULT_ABI = [
|
|
118
|
+
{
|
|
119
|
+
type: 'function',
|
|
120
|
+
name: 'getValue',
|
|
121
|
+
inputs: [],
|
|
122
|
+
outputs: [{ type: 'uint256' }],
|
|
123
|
+
stateMutability: 'view',
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
type: 'constructor',
|
|
127
|
+
inputs: [{ type: 'uint256', name: '_initialValue' }],
|
|
128
|
+
stateMutability: 'nonpayable',
|
|
129
|
+
},
|
|
130
|
+
];
|
|
131
|
+
/**
|
|
132
|
+
* Creates a mock artifact for testing.
|
|
133
|
+
*
|
|
134
|
+
* @param name - Contract name
|
|
135
|
+
* @param abi - Optional ABI (defaults to a simple contract with constructor and getValue)
|
|
136
|
+
* @returns A mock artifact object
|
|
137
|
+
*
|
|
138
|
+
* @example
|
|
139
|
+
* ```typescript
|
|
140
|
+
* const artifact = createMockArtifact('MyContract', [
|
|
141
|
+
* {
|
|
142
|
+
* type: 'constructor',
|
|
143
|
+
* inputs: [{type: 'address', name: 'owner'}],
|
|
144
|
+
* stateMutability: 'nonpayable',
|
|
145
|
+
* },
|
|
146
|
+
* ]);
|
|
147
|
+
* ```
|
|
148
|
+
*/
|
|
149
|
+
export function createMockArtifact(name, abi = DEFAULT_ABI) {
|
|
150
|
+
return {
|
|
151
|
+
contractName: name,
|
|
152
|
+
abi,
|
|
153
|
+
bytecode: '0x6080604052348015600f57600080fd5b50',
|
|
154
|
+
deployedBytecode: '0x6080604052',
|
|
155
|
+
linkReferences: {},
|
|
156
|
+
metadata: JSON.stringify({ compiler: { version: '0.8.20' }, settings: { optimizer: { enabled: true } } }),
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
export function createExampleArtifact(name, templateNumber) {
|
|
160
|
+
const mock = createMockArtifact(name);
|
|
161
|
+
if (templateNumber == 0) {
|
|
162
|
+
mock.abi = [
|
|
163
|
+
{
|
|
164
|
+
type: 'function',
|
|
165
|
+
name: 'getValue0',
|
|
166
|
+
inputs: [],
|
|
167
|
+
outputs: [{ type: 'uint256' }],
|
|
168
|
+
stateMutability: 'view',
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
type: 'constructor',
|
|
172
|
+
inputs: [{ type: 'uint256', name: '_initialValue' }],
|
|
173
|
+
stateMutability: 'nonpayable',
|
|
174
|
+
},
|
|
175
|
+
];
|
|
176
|
+
}
|
|
177
|
+
else if (templateNumber == 1) {
|
|
178
|
+
mock.abi = [
|
|
179
|
+
{
|
|
180
|
+
type: 'function',
|
|
181
|
+
name: 'getValue1',
|
|
182
|
+
inputs: [],
|
|
183
|
+
outputs: [{ type: 'uint256' }],
|
|
184
|
+
stateMutability: 'view',
|
|
185
|
+
},
|
|
186
|
+
{
|
|
187
|
+
type: 'constructor',
|
|
188
|
+
inputs: [{ type: 'uint256', name: '_initialValue' }],
|
|
189
|
+
stateMutability: 'nonpayable',
|
|
190
|
+
},
|
|
191
|
+
];
|
|
192
|
+
}
|
|
193
|
+
else if (templateNumber == 2) {
|
|
194
|
+
mock.abi = [
|
|
195
|
+
{
|
|
196
|
+
type: 'function',
|
|
197
|
+
name: 'getValue2',
|
|
198
|
+
inputs: [],
|
|
199
|
+
outputs: [{ type: 'uint256' }],
|
|
200
|
+
stateMutability: 'view',
|
|
201
|
+
},
|
|
202
|
+
{
|
|
203
|
+
type: 'constructor',
|
|
204
|
+
inputs: [{ type: 'uint256', name: '_initialValue' }],
|
|
205
|
+
stateMutability: 'nonpayable',
|
|
206
|
+
},
|
|
207
|
+
];
|
|
208
|
+
}
|
|
209
|
+
else {
|
|
210
|
+
throw new Error(`no template ${templateNumber}`);
|
|
211
|
+
}
|
|
212
|
+
return mock;
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Creates a mock artifact with library references.
|
|
216
|
+
*
|
|
217
|
+
* @param name - Contract name
|
|
218
|
+
* @param libraryName - Name of the library to reference
|
|
219
|
+
* @param abi - Optional ABI
|
|
220
|
+
* @returns A mock artifact with library link references
|
|
221
|
+
*
|
|
222
|
+
* @example
|
|
223
|
+
* ```typescript
|
|
224
|
+
* const artifact = createMockArtifactWithLibrary('Calculator', 'MathLib');
|
|
225
|
+
* ```
|
|
226
|
+
*/
|
|
227
|
+
export function createMockArtifactWithLibrary(name, libraryName, abi = DEFAULT_ABI) {
|
|
228
|
+
return {
|
|
229
|
+
contractName: name,
|
|
230
|
+
abi,
|
|
231
|
+
bytecode: '0x6080604052348015600f57600080fd5b50',
|
|
232
|
+
deployedBytecode: '0x6080604052',
|
|
233
|
+
linkReferences: {
|
|
234
|
+
'contracts/libraries.sol': {
|
|
235
|
+
[libraryName]: [{ length: 20, start: 50 }],
|
|
236
|
+
},
|
|
237
|
+
},
|
|
238
|
+
metadata: JSON.stringify({ compiler: { version: '0.8.20' }, settings: { optimizer: { enabled: true } } }),
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
// ============================================================================
|
|
242
|
+
// Mock Environment
|
|
243
|
+
// ============================================================================
|
|
244
|
+
/**
|
|
245
|
+
* Default named accounts for testing.
|
|
246
|
+
*/
|
|
247
|
+
const DEFAULT_NAMED_ACCOUNTS = {
|
|
248
|
+
deployer: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266',
|
|
249
|
+
user1: '0x70997970C51812dc3A010C7d01b50e0d17dc79C8',
|
|
250
|
+
user2: '0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC',
|
|
251
|
+
};
|
|
252
|
+
/**
|
|
253
|
+
* Creates a mock environment for testing deployments.
|
|
254
|
+
*
|
|
255
|
+
* @param options - Optional configuration
|
|
256
|
+
* @returns An object containing the environment, provider, and deployments record
|
|
257
|
+
*
|
|
258
|
+
* @example
|
|
259
|
+
* ```typescript
|
|
260
|
+
* // Basic usage
|
|
261
|
+
* const {env, provider} = createMockEnvironment();
|
|
262
|
+
*
|
|
263
|
+
* // With custom provider responses
|
|
264
|
+
* const {env, provider} = createMockEnvironment({
|
|
265
|
+
* providerConfig: {
|
|
266
|
+
* responses: {
|
|
267
|
+
* eth_getCode: '0x6080...', // Simulate deployed contract
|
|
268
|
+
* },
|
|
269
|
+
* },
|
|
270
|
+
* });
|
|
271
|
+
*
|
|
272
|
+
* // Update responses during test
|
|
273
|
+
* provider.setResponse('eth_getCode', '0x'); // Reset to empty
|
|
274
|
+
* ```
|
|
275
|
+
*/
|
|
276
|
+
export function createMockEnvironment(options = {}) {
|
|
277
|
+
const deployments = {};
|
|
278
|
+
const provider = createMockProvider(options.providerConfig);
|
|
279
|
+
const namedAccounts = options.namedAccounts || DEFAULT_NAMED_ACCOUNTS;
|
|
280
|
+
const chainId = options.chainId ?? 31337;
|
|
281
|
+
const chainName = options.chainName ?? 'localhost';
|
|
282
|
+
const addressSigners = {};
|
|
283
|
+
for (const address of Object.values(namedAccounts)) {
|
|
284
|
+
addressSigners[address] = {
|
|
285
|
+
type: 'remote',
|
|
286
|
+
signer: provider,
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
const env = {
|
|
290
|
+
namedAccounts: namedAccounts,
|
|
291
|
+
network: {
|
|
292
|
+
chain: {
|
|
293
|
+
id: chainId,
|
|
294
|
+
name: chainName,
|
|
295
|
+
nativeCurrency: { name: 'Ether', symbol: 'ETH', decimals: 18 },
|
|
296
|
+
},
|
|
297
|
+
provider,
|
|
298
|
+
deterministicDeployment: {
|
|
299
|
+
create2: {
|
|
300
|
+
factory: '0x4e59b44847b379578588920cA78FbF26c0B4956C',
|
|
301
|
+
deployer: '0x3f39e218c8a8b13d2488ccf2a3b7d0e3c0c8e8d9',
|
|
302
|
+
signedTx: '0xf8a5',
|
|
303
|
+
funding: '100000000000000000',
|
|
304
|
+
},
|
|
305
|
+
create3: {
|
|
306
|
+
factory: '0x000000000004d4f168daE7DB3C610F408eE22F57',
|
|
307
|
+
salt: '0x5361109ca02853ca8e22046b7125306d9ec4ae4cdecc393c567b6be861df3db6',
|
|
308
|
+
bytecode: '0x6080604052348015600f57600080fd5b506103ca8061001f6000396000f3fe6080604052600436106100295760003560e01c8063360d0fad1461002e5780639881d19514610077575b600080fd5b34801561003a57600080fd5b5061004e610049366004610228565b61008a565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b61004e61008536600461029c565b6100ee565b6040517fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606084901b166020820152603481018290526000906054016040516020818303038152906040528051906020012091506100e78261014c565b9392505050565b6040517fffffffffffffffffffffffffffffffffffffffff0000000000000000000000003360601b166020820152603481018290526000906054016040516020818303038152906040528051906020012091506100e734848461015e565b600061015882306101ce565b92915050565b60006f67363d3d37363d34f03d5260086018f3600052816010806000f58061018e5763301164256000526004601cfd5b8060145261d69460005260016034536017601e20915060008085516020870188855af1823b026101c65763301164256000526004601cfd5b509392505050565b60006040518260005260ff600b53836020527f21c35dbe1b344a2488cf3321d6ce542f8e9f305544ff09e4993a62319a497c1f6040526055600b20601452806040525061d694600052600160345350506017601e20919050565b6000806040838503121561023b57600080fd5b823573ffffffffffffffffffffffffffffffffffffffff8116811461025f57600080fd5b946020939093013593505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080604083850312156102af57600080fd5b823567ffffffffffffffff8111156102c657600080fd5b8301601f810185136102d757600080fd5b803567ffffffffffffffff8111156102f1576102f161026d565b6040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8501160116810181811067ffffffffffffffff8211171561035d5761035d61026d565b60405281815282820160200187101561037557600080fd5b816020840160208301376000602092820183015296940135945050505056fea264697066735822122059dcc5dc6453397d13ff28021e28472a80a45bbd97f3135f69bd2650773aeb0164736f6c634300081a0033',
|
|
309
|
+
proxyBytecode: '0x67363d3d37363d34f03d5260086018f3',
|
|
310
|
+
},
|
|
311
|
+
},
|
|
312
|
+
},
|
|
313
|
+
addressSigners,
|
|
314
|
+
tags: {
|
|
315
|
+
test: true,
|
|
316
|
+
'auto-mine': true,
|
|
317
|
+
...(options.tags || {}),
|
|
318
|
+
},
|
|
319
|
+
get: (name) => deployments[name],
|
|
320
|
+
getOrNull: (name) => deployments[name] || null,
|
|
321
|
+
save: async (name, deployment) => {
|
|
322
|
+
deployments[name] = deployment;
|
|
323
|
+
return deployment;
|
|
324
|
+
},
|
|
325
|
+
savePendingDeployment: async (pendingDeployment) => {
|
|
326
|
+
const pd = pendingDeployment;
|
|
327
|
+
return {
|
|
328
|
+
...pd.partialDeployment,
|
|
329
|
+
address: pd.expectedAddress || ('0x' + '1'.repeat(40)),
|
|
330
|
+
newlyDeployed: true,
|
|
331
|
+
};
|
|
332
|
+
},
|
|
333
|
+
savePendingExecution: async () => { },
|
|
334
|
+
showMessage: (message) => {
|
|
335
|
+
// Could be configured to capture messages for testing
|
|
336
|
+
},
|
|
337
|
+
};
|
|
338
|
+
return { env, provider, deployments };
|
|
339
|
+
}
|
|
340
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@rocketh/test-utils",
|
|
3
|
+
"version": "0.0.2",
|
|
4
|
+
"description": "Test utilities for rocketh packages",
|
|
5
|
+
"publishConfig": {
|
|
6
|
+
"access": "public"
|
|
7
|
+
},
|
|
8
|
+
"type": "module",
|
|
9
|
+
"main": "dist/index.js",
|
|
10
|
+
"module": "dist/index.js",
|
|
11
|
+
"types": "dist/index.d.ts",
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"import": {
|
|
15
|
+
"types": "./dist/index.d.ts",
|
|
16
|
+
"default": "./dist/index.js"
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"files": [
|
|
21
|
+
"dist",
|
|
22
|
+
"src"
|
|
23
|
+
],
|
|
24
|
+
"dependencies": {
|
|
25
|
+
"eip-1193": "^0.6.5",
|
|
26
|
+
"viem": "^2.44.4",
|
|
27
|
+
"@rocketh/core": "0.17.9"
|
|
28
|
+
},
|
|
29
|
+
"devDependencies": {
|
|
30
|
+
"as-soon": "^0.1.4",
|
|
31
|
+
"typescript": "^5.9.3"
|
|
32
|
+
},
|
|
33
|
+
"scripts": {
|
|
34
|
+
"build": "tsc --project tsconfig.json",
|
|
35
|
+
"dev": "as-soon -w src pnpm build"
|
|
36
|
+
}
|
|
37
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,488 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @rocketh/test-utils
|
|
3
|
+
*
|
|
4
|
+
* Test utilities for rocketh packages. Provides mock environments, providers,
|
|
5
|
+
* and artifacts for testing deployment scenarios.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type {Abi, Artifact, Environment} from '@rocketh/core/types';
|
|
9
|
+
import type {EIP1193Provider} from 'eip-1193';
|
|
10
|
+
|
|
11
|
+
// ============================================================================
|
|
12
|
+
// Types
|
|
13
|
+
// ============================================================================
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Configuration for mock provider responses.
|
|
17
|
+
* Allows tests to specify custom return values for specific RPC methods.
|
|
18
|
+
*/
|
|
19
|
+
export type MockProviderConfig = {
|
|
20
|
+
/**
|
|
21
|
+
* Override responses for specific RPC methods.
|
|
22
|
+
* Can be a static value or a function that receives params and returns a value.
|
|
23
|
+
*/
|
|
24
|
+
responses?: {
|
|
25
|
+
[method: string]: unknown | ((params?: unknown[]) => unknown | Promise<unknown>);
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Called when an unmocked method is requested.
|
|
30
|
+
* If not provided, returns null and logs a warning.
|
|
31
|
+
*/
|
|
32
|
+
onUnmockedMethod?: (method: string, params?: unknown[]) => unknown | Promise<unknown>;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* A mock EIP-1193 provider with configurable responses.
|
|
37
|
+
*/
|
|
38
|
+
export type MockProvider = EIP1193Provider & {
|
|
39
|
+
/**
|
|
40
|
+
* Update the configuration for the mock provider.
|
|
41
|
+
*/
|
|
42
|
+
setConfig: (config: MockProviderConfig) => void;
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Update or add a specific response for an RPC method.
|
|
46
|
+
*/
|
|
47
|
+
setResponse: (method: string, response: unknown | ((params?: unknown[]) => unknown | Promise<unknown>)) => void;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Get all recorded requests made to the provider.
|
|
51
|
+
*/
|
|
52
|
+
getRequests: () => Array<{method: string; params?: unknown[]}>;
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Clear recorded requests.
|
|
56
|
+
*/
|
|
57
|
+
clearRequests: () => void;
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Add an event listener (no-op in mock).
|
|
61
|
+
*/
|
|
62
|
+
on: (event: string, listener: (...args: unknown[]) => void) => MockProvider;
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Remove an event listener (no-op in mock).
|
|
66
|
+
*/
|
|
67
|
+
removeListener: (event: string, listener: (...args: unknown[]) => void) => MockProvider;
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Options for creating a mock environment.
|
|
72
|
+
*/
|
|
73
|
+
export type MockEnvironmentOptions = {
|
|
74
|
+
/**
|
|
75
|
+
* Custom provider configuration.
|
|
76
|
+
*/
|
|
77
|
+
providerConfig?: MockProviderConfig;
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Custom named accounts. Defaults to deployer, user1, user2.
|
|
81
|
+
*/
|
|
82
|
+
namedAccounts?: Record<string, `0x${string}`>;
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Chain ID. Defaults to 31337 (localhost).
|
|
86
|
+
*/
|
|
87
|
+
chainId?: number;
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Chain name. Defaults to 'localhost'.
|
|
91
|
+
*/
|
|
92
|
+
chainName?: string;
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Tags to set on the environment.
|
|
96
|
+
*/
|
|
97
|
+
tags?: Record<string, boolean>;
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Result of creating a mock environment.
|
|
102
|
+
*/
|
|
103
|
+
export type MockEnvironmentResult = {
|
|
104
|
+
/**
|
|
105
|
+
* The mock environment.
|
|
106
|
+
*/
|
|
107
|
+
env: Environment;
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* The mock provider (for inspecting/updating responses).
|
|
111
|
+
*/
|
|
112
|
+
provider: MockProvider;
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* The deployments record (for inspecting saved deployments).
|
|
116
|
+
*/
|
|
117
|
+
deployments: Record<string, unknown>;
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
// ============================================================================
|
|
121
|
+
// Mock Provider
|
|
122
|
+
// ============================================================================
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Default RPC method responses for a mock provider.
|
|
126
|
+
* These simulate a basic EVM environment.
|
|
127
|
+
*/
|
|
128
|
+
function getDefaultResponses(txCounter: {
|
|
129
|
+
value: number;
|
|
130
|
+
}): Record<string, unknown | ((params?: unknown[]) => unknown | Promise<unknown>)> {
|
|
131
|
+
return {
|
|
132
|
+
eth_sendTransaction: () => {
|
|
133
|
+
txCounter.value++;
|
|
134
|
+
return `0x${'0'.repeat(63)}${txCounter.value.toString(16)}` as `0x${string}`;
|
|
135
|
+
},
|
|
136
|
+
eth_sendRawTransaction: () => {
|
|
137
|
+
txCounter.value++;
|
|
138
|
+
return `0x${'1'.repeat(63)}${txCounter.value.toString(16)}` as `0x${string}`;
|
|
139
|
+
},
|
|
140
|
+
eth_getCode: () => '0x',
|
|
141
|
+
eth_getBalance: () => '0x' + BigInt('1000000000000000000000').toString(16),
|
|
142
|
+
evm_mine: () => null,
|
|
143
|
+
eth_getTransactionReceipt: (params?: unknown[]) => ({
|
|
144
|
+
contractAddress: ('0x' + 'a'.repeat(40)) as `0x${string}`,
|
|
145
|
+
status: '0x1',
|
|
146
|
+
blockNumber: '0x1',
|
|
147
|
+
blockHash: `0x${'b'.repeat(64)}`,
|
|
148
|
+
transactionHash: (params?.[0] as string) || `0x${'c'.repeat(64)}`,
|
|
149
|
+
gasUsed: '0x5208',
|
|
150
|
+
}),
|
|
151
|
+
eth_chainId: () => '0x7a69', // 31337
|
|
152
|
+
eth_blockNumber: () => '0x1',
|
|
153
|
+
eth_gasPrice: () => '0x3b9aca00', // 1 gwei
|
|
154
|
+
eth_estimateGas: () => '0x5208', // 21000
|
|
155
|
+
eth_getTransactionCount: () => '0x0',
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Creates a mock EIP-1193 provider with configurable responses.
|
|
161
|
+
*
|
|
162
|
+
* @param config - Optional configuration for custom responses
|
|
163
|
+
* @returns A mock provider that can be used in tests
|
|
164
|
+
*
|
|
165
|
+
* @example
|
|
166
|
+
* ```typescript
|
|
167
|
+
* const provider = createMockProvider({
|
|
168
|
+
* responses: {
|
|
169
|
+
* eth_getCode: '0x6080...', // Return deployed code
|
|
170
|
+
* eth_getBalance: (params) => {
|
|
171
|
+
* const address = params?.[0];
|
|
172
|
+
* return address === '0x123...' ? '0x0' : '0x1000';
|
|
173
|
+
* },
|
|
174
|
+
* },
|
|
175
|
+
* });
|
|
176
|
+
* ```
|
|
177
|
+
*/
|
|
178
|
+
export function createMockProvider(config: MockProviderConfig = {}): MockProvider {
|
|
179
|
+
const txCounter = {value: 0};
|
|
180
|
+
const defaultResponses = getDefaultResponses(txCounter);
|
|
181
|
+
let currentConfig = {...config};
|
|
182
|
+
const requests: Array<{method: string; params?: unknown[]}> = [];
|
|
183
|
+
|
|
184
|
+
const request = async ({method, params}: {method: string; params?: unknown[]}): Promise<unknown> => {
|
|
185
|
+
requests.push({method, params: params as unknown[]});
|
|
186
|
+
|
|
187
|
+
// Check custom responses first
|
|
188
|
+
const customResponse = currentConfig.responses?.[method];
|
|
189
|
+
if (customResponse !== undefined) {
|
|
190
|
+
if (typeof customResponse === 'function') {
|
|
191
|
+
return customResponse(params as unknown[]);
|
|
192
|
+
}
|
|
193
|
+
return customResponse;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// Check default responses
|
|
197
|
+
const defaultResponse = defaultResponses[method];
|
|
198
|
+
if (defaultResponse !== undefined) {
|
|
199
|
+
if (typeof defaultResponse === 'function') {
|
|
200
|
+
return defaultResponse(params as unknown[]);
|
|
201
|
+
}
|
|
202
|
+
return defaultResponse;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// Handle unmocked method
|
|
206
|
+
if (currentConfig.onUnmockedMethod) {
|
|
207
|
+
return currentConfig.onUnmockedMethod(method, params as unknown[]);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
console.warn(`Unmocked provider method: ${method}`);
|
|
211
|
+
return null;
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
const provider: MockProvider = {
|
|
215
|
+
request: request as EIP1193Provider['request'],
|
|
216
|
+
on: () => provider, // No-op event listener
|
|
217
|
+
removeListener: () => provider, // No-op event listener removal
|
|
218
|
+
setConfig: (newConfig: MockProviderConfig) => {
|
|
219
|
+
currentConfig = {...newConfig};
|
|
220
|
+
},
|
|
221
|
+
setResponse: (method: string, response: unknown | ((params?: unknown[]) => unknown | Promise<unknown>)) => {
|
|
222
|
+
if (!currentConfig.responses) {
|
|
223
|
+
currentConfig.responses = {};
|
|
224
|
+
}
|
|
225
|
+
currentConfig.responses[method] = response;
|
|
226
|
+
},
|
|
227
|
+
getRequests: () => [...requests],
|
|
228
|
+
clearRequests: () => {
|
|
229
|
+
requests.length = 0;
|
|
230
|
+
},
|
|
231
|
+
};
|
|
232
|
+
return provider;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// ============================================================================
|
|
236
|
+
// Mock Artifacts
|
|
237
|
+
// ============================================================================
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Default ABI for mock artifacts.
|
|
241
|
+
*/
|
|
242
|
+
const DEFAULT_ABI: Abi = [
|
|
243
|
+
{
|
|
244
|
+
type: 'function',
|
|
245
|
+
name: 'getValue',
|
|
246
|
+
inputs: [],
|
|
247
|
+
outputs: [{type: 'uint256'}],
|
|
248
|
+
stateMutability: 'view',
|
|
249
|
+
},
|
|
250
|
+
{
|
|
251
|
+
type: 'constructor',
|
|
252
|
+
inputs: [{type: 'uint256', name: '_initialValue'}],
|
|
253
|
+
stateMutability: 'nonpayable',
|
|
254
|
+
},
|
|
255
|
+
] as const;
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Creates a mock artifact for testing.
|
|
259
|
+
*
|
|
260
|
+
* @param name - Contract name
|
|
261
|
+
* @param abi - Optional ABI (defaults to a simple contract with constructor and getValue)
|
|
262
|
+
* @returns A mock artifact object
|
|
263
|
+
*
|
|
264
|
+
* @example
|
|
265
|
+
* ```typescript
|
|
266
|
+
* const artifact = createMockArtifact('MyContract', [
|
|
267
|
+
* {
|
|
268
|
+
* type: 'constructor',
|
|
269
|
+
* inputs: [{type: 'address', name: 'owner'}],
|
|
270
|
+
* stateMutability: 'nonpayable',
|
|
271
|
+
* },
|
|
272
|
+
* ]);
|
|
273
|
+
* ```
|
|
274
|
+
*/
|
|
275
|
+
export function createMockArtifact<TAbi extends Abi = typeof DEFAULT_ABI>(
|
|
276
|
+
name: string,
|
|
277
|
+
abi: TAbi = DEFAULT_ABI as TAbi,
|
|
278
|
+
): Artifact<TAbi> {
|
|
279
|
+
return {
|
|
280
|
+
contractName: name,
|
|
281
|
+
abi,
|
|
282
|
+
bytecode: '0x6080604052348015600f57600080fd5b50' as `0x${string}`,
|
|
283
|
+
deployedBytecode: '0x6080604052' as `0x${string}`,
|
|
284
|
+
linkReferences: {},
|
|
285
|
+
metadata: JSON.stringify({compiler: {version: '0.8.20'}, settings: {optimizer: {enabled: true}}}),
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
export function createExampleArtifact(name: string, templateNumber: number): Artifact<Abi> {
|
|
290
|
+
const mock = createMockArtifact(name);
|
|
291
|
+
if (templateNumber == 0) {
|
|
292
|
+
(mock as any).abi = [
|
|
293
|
+
{
|
|
294
|
+
type: 'function',
|
|
295
|
+
name: 'getValue0',
|
|
296
|
+
inputs: [],
|
|
297
|
+
outputs: [{type: 'uint256'}],
|
|
298
|
+
stateMutability: 'view',
|
|
299
|
+
},
|
|
300
|
+
{
|
|
301
|
+
type: 'constructor',
|
|
302
|
+
inputs: [{type: 'uint256', name: '_initialValue'}],
|
|
303
|
+
stateMutability: 'nonpayable',
|
|
304
|
+
},
|
|
305
|
+
];
|
|
306
|
+
} else if (templateNumber == 1) {
|
|
307
|
+
(mock as any).abi = [
|
|
308
|
+
{
|
|
309
|
+
type: 'function',
|
|
310
|
+
name: 'getValue1',
|
|
311
|
+
inputs: [],
|
|
312
|
+
outputs: [{type: 'uint256'}],
|
|
313
|
+
stateMutability: 'view',
|
|
314
|
+
},
|
|
315
|
+
{
|
|
316
|
+
type: 'constructor',
|
|
317
|
+
inputs: [{type: 'uint256', name: '_initialValue'}],
|
|
318
|
+
stateMutability: 'nonpayable',
|
|
319
|
+
},
|
|
320
|
+
];
|
|
321
|
+
} else if (templateNumber == 2) {
|
|
322
|
+
(mock as any).abi = [
|
|
323
|
+
{
|
|
324
|
+
type: 'function',
|
|
325
|
+
name: 'getValue2',
|
|
326
|
+
inputs: [],
|
|
327
|
+
outputs: [{type: 'uint256'}],
|
|
328
|
+
stateMutability: 'view',
|
|
329
|
+
},
|
|
330
|
+
{
|
|
331
|
+
type: 'constructor',
|
|
332
|
+
inputs: [{type: 'uint256', name: '_initialValue'}],
|
|
333
|
+
stateMutability: 'nonpayable',
|
|
334
|
+
},
|
|
335
|
+
];
|
|
336
|
+
} else {
|
|
337
|
+
throw new Error(`no template ${templateNumber}`);
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
return mock;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
/**
|
|
344
|
+
* Creates a mock artifact with library references.
|
|
345
|
+
*
|
|
346
|
+
* @param name - Contract name
|
|
347
|
+
* @param libraryName - Name of the library to reference
|
|
348
|
+
* @param abi - Optional ABI
|
|
349
|
+
* @returns A mock artifact with library link references
|
|
350
|
+
*
|
|
351
|
+
* @example
|
|
352
|
+
* ```typescript
|
|
353
|
+
* const artifact = createMockArtifactWithLibrary('Calculator', 'MathLib');
|
|
354
|
+
* ```
|
|
355
|
+
*/
|
|
356
|
+
export function createMockArtifactWithLibrary<TAbi extends Abi = typeof DEFAULT_ABI>(
|
|
357
|
+
name: string,
|
|
358
|
+
libraryName: string,
|
|
359
|
+
abi: TAbi = DEFAULT_ABI as TAbi,
|
|
360
|
+
): Artifact<TAbi> {
|
|
361
|
+
return {
|
|
362
|
+
contractName: name,
|
|
363
|
+
abi,
|
|
364
|
+
bytecode: '0x6080604052348015600f57600080fd5b50' as `0x${string}`,
|
|
365
|
+
deployedBytecode: '0x6080604052' as `0x${string}`,
|
|
366
|
+
linkReferences: {
|
|
367
|
+
'contracts/libraries.sol': {
|
|
368
|
+
[libraryName]: [{length: 20, start: 50}],
|
|
369
|
+
},
|
|
370
|
+
},
|
|
371
|
+
metadata: JSON.stringify({compiler: {version: '0.8.20'}, settings: {optimizer: {enabled: true}}}),
|
|
372
|
+
};
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
// ============================================================================
|
|
376
|
+
// Mock Environment
|
|
377
|
+
// ============================================================================
|
|
378
|
+
|
|
379
|
+
/**
|
|
380
|
+
* Default named accounts for testing.
|
|
381
|
+
*/
|
|
382
|
+
const DEFAULT_NAMED_ACCOUNTS: Record<string, `0x${string}`> = {
|
|
383
|
+
deployer: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266',
|
|
384
|
+
user1: '0x70997970C51812dc3A010C7d01b50e0d17dc79C8',
|
|
385
|
+
user2: '0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC',
|
|
386
|
+
};
|
|
387
|
+
|
|
388
|
+
/**
|
|
389
|
+
* Creates a mock environment for testing deployments.
|
|
390
|
+
*
|
|
391
|
+
* @param options - Optional configuration
|
|
392
|
+
* @returns An object containing the environment, provider, and deployments record
|
|
393
|
+
*
|
|
394
|
+
* @example
|
|
395
|
+
* ```typescript
|
|
396
|
+
* // Basic usage
|
|
397
|
+
* const {env, provider} = createMockEnvironment();
|
|
398
|
+
*
|
|
399
|
+
* // With custom provider responses
|
|
400
|
+
* const {env, provider} = createMockEnvironment({
|
|
401
|
+
* providerConfig: {
|
|
402
|
+
* responses: {
|
|
403
|
+
* eth_getCode: '0x6080...', // Simulate deployed contract
|
|
404
|
+
* },
|
|
405
|
+
* },
|
|
406
|
+
* });
|
|
407
|
+
*
|
|
408
|
+
* // Update responses during test
|
|
409
|
+
* provider.setResponse('eth_getCode', '0x'); // Reset to empty
|
|
410
|
+
* ```
|
|
411
|
+
*/
|
|
412
|
+
export function createMockEnvironment(options: MockEnvironmentOptions = {}): MockEnvironmentResult {
|
|
413
|
+
const deployments: Record<string, unknown> = {};
|
|
414
|
+
const provider = createMockProvider(options.providerConfig);
|
|
415
|
+
const namedAccounts = options.namedAccounts || DEFAULT_NAMED_ACCOUNTS;
|
|
416
|
+
const chainId = options.chainId ?? 31337;
|
|
417
|
+
const chainName = options.chainName ?? 'localhost';
|
|
418
|
+
|
|
419
|
+
const addressSigners: Record<string, {type: 'remote'; signer: MockProvider}> = {};
|
|
420
|
+
for (const address of Object.values(namedAccounts)) {
|
|
421
|
+
addressSigners[address] = {
|
|
422
|
+
type: 'remote',
|
|
423
|
+
signer: provider,
|
|
424
|
+
};
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
const env: Environment = {
|
|
428
|
+
namedAccounts: namedAccounts as Record<string, `0x${string}`>,
|
|
429
|
+
network: {
|
|
430
|
+
chain: {
|
|
431
|
+
id: chainId,
|
|
432
|
+
name: chainName,
|
|
433
|
+
nativeCurrency: {name: 'Ether', symbol: 'ETH', decimals: 18},
|
|
434
|
+
},
|
|
435
|
+
provider,
|
|
436
|
+
deterministicDeployment: {
|
|
437
|
+
create2: {
|
|
438
|
+
factory: '0x4e59b44847b379578588920cA78FbF26c0B4956C' as `0x${string}`,
|
|
439
|
+
deployer: '0x3f39e218c8a8b13d2488ccf2a3b7d0e3c0c8e8d9' as `0x${string}`,
|
|
440
|
+
signedTx: '0xf8a5' as `0x${string}`,
|
|
441
|
+
funding: '100000000000000000',
|
|
442
|
+
},
|
|
443
|
+
create3: {
|
|
444
|
+
factory: '0x000000000004d4f168daE7DB3C610F408eE22F57',
|
|
445
|
+
salt: '0x5361109ca02853ca8e22046b7125306d9ec4ae4cdecc393c567b6be861df3db6',
|
|
446
|
+
bytecode:
|
|
447
|
+
'0x6080604052348015600f57600080fd5b506103ca8061001f6000396000f3fe6080604052600436106100295760003560e01c8063360d0fad1461002e5780639881d19514610077575b600080fd5b34801561003a57600080fd5b5061004e610049366004610228565b61008a565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b61004e61008536600461029c565b6100ee565b6040517fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606084901b166020820152603481018290526000906054016040516020818303038152906040528051906020012091506100e78261014c565b9392505050565b6040517fffffffffffffffffffffffffffffffffffffffff0000000000000000000000003360601b166020820152603481018290526000906054016040516020818303038152906040528051906020012091506100e734848461015e565b600061015882306101ce565b92915050565b60006f67363d3d37363d34f03d5260086018f3600052816010806000f58061018e5763301164256000526004601cfd5b8060145261d69460005260016034536017601e20915060008085516020870188855af1823b026101c65763301164256000526004601cfd5b509392505050565b60006040518260005260ff600b53836020527f21c35dbe1b344a2488cf3321d6ce542f8e9f305544ff09e4993a62319a497c1f6040526055600b20601452806040525061d694600052600160345350506017601e20919050565b6000806040838503121561023b57600080fd5b823573ffffffffffffffffffffffffffffffffffffffff8116811461025f57600080fd5b946020939093013593505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080604083850312156102af57600080fd5b823567ffffffffffffffff8111156102c657600080fd5b8301601f810185136102d757600080fd5b803567ffffffffffffffff8111156102f1576102f161026d565b6040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8501160116810181811067ffffffffffffffff8211171561035d5761035d61026d565b60405281815282820160200187101561037557600080fd5b816020840160208301376000602092820183015296940135945050505056fea264697066735822122059dcc5dc6453397d13ff28021e28472a80a45bbd97f3135f69bd2650773aeb0164736f6c634300081a0033',
|
|
448
|
+
proxyBytecode: '0x67363d3d37363d34f03d5260086018f3',
|
|
449
|
+
},
|
|
450
|
+
},
|
|
451
|
+
},
|
|
452
|
+
addressSigners,
|
|
453
|
+
tags: {
|
|
454
|
+
test: true,
|
|
455
|
+
'auto-mine': true,
|
|
456
|
+
...(options.tags || {}),
|
|
457
|
+
},
|
|
458
|
+
get: <T>(name: string) => deployments[name] as T,
|
|
459
|
+
getOrNull: <T>(name: string) => (deployments[name] as T) || null,
|
|
460
|
+
save: async <T>(name: string, deployment: T) => {
|
|
461
|
+
deployments[name] = deployment;
|
|
462
|
+
return deployment as T;
|
|
463
|
+
},
|
|
464
|
+
savePendingDeployment: async (pendingDeployment: unknown) => {
|
|
465
|
+
const pd = pendingDeployment as {
|
|
466
|
+
partialDeployment: Record<string, unknown>;
|
|
467
|
+
expectedAddress?: `0x${string}`;
|
|
468
|
+
};
|
|
469
|
+
return {
|
|
470
|
+
...pd.partialDeployment,
|
|
471
|
+
address: pd.expectedAddress || (('0x' + '1'.repeat(40)) as `0x${string}`),
|
|
472
|
+
newlyDeployed: true,
|
|
473
|
+
};
|
|
474
|
+
},
|
|
475
|
+
savePendingExecution: async () => {},
|
|
476
|
+
showMessage: (message: string) => {
|
|
477
|
+
// Could be configured to capture messages for testing
|
|
478
|
+
},
|
|
479
|
+
} as unknown as Environment;
|
|
480
|
+
|
|
481
|
+
return {env, provider, deployments};
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
// ============================================================================
|
|
485
|
+
// Re-exports
|
|
486
|
+
// ============================================================================
|
|
487
|
+
|
|
488
|
+
export type {Environment} from '@rocketh/core/types';
|