rocketh 0.11.20 → 0.11.22-testing.0
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/CHANGELOG.md +12 -0
- package/dist/cli.js.map +1 -1
- package/dist/environment/index.d.ts +0 -3
- package/dist/environment/index.d.ts.map +1 -1
- package/dist/environment/index.js +14 -15
- package/dist/environment/index.js.map +1 -1
- package/dist/environment/types.d.ts +8 -4
- package/dist/environment/types.d.ts.map +1 -1
- package/dist/executor/index.d.ts +98 -3
- package/dist/executor/index.d.ts.map +1 -1
- package/dist/executor/index.js +82 -36
- package/dist/executor/index.js.map +1 -1
- package/dist/executor/setup.test.d.ts +13 -0
- package/dist/executor/setup.test.d.ts.map +1 -0
- package/dist/executor/setup.test.js +106 -0
- package/dist/executor/setup.test.js.map +1 -0
- package/dist/executor/types.d.ts +20 -0
- package/dist/executor/types.d.ts.map +1 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -1
- package/dist/index.js.map +1 -1
- package/dist/internal/types.d.ts +2 -0
- package/dist/internal/types.d.ts.map +1 -1
- package/dist/utils/curry.d.ts +35 -0
- package/dist/utils/curry.d.ts.map +1 -0
- package/dist/utils/curry.js +30 -0
- package/dist/utils/curry.js.map +1 -0
- package/dist/utils/curry.test.d.ts +16 -0
- package/dist/utils/curry.test.d.ts.map +1 -0
- package/dist/utils/curry.test.js +33 -0
- package/dist/utils/curry.test.js.map +1 -0
- package/package.json +1 -1
- package/src/cli.ts +1 -1
- package/src/environment/index.ts +16 -18
- package/src/environment/types.ts +10 -4
- package/src/executor/index.ts +111 -53
- package/src/executor/setup.test.ts +133 -0
- package/src/executor/types.ts +45 -0
- package/src/index.ts +0 -1
- package/src/internal/types.ts +3 -0
- package/src/utils/curry.test.ts +42 -0
- package/src/utils/curry.ts +60 -0
package/src/executor/index.ts
CHANGED
|
@@ -5,13 +5,13 @@ import type {
|
|
|
5
5
|
Config,
|
|
6
6
|
Environment,
|
|
7
7
|
ResolvedConfig,
|
|
8
|
-
ResolvedNamedAccounts,
|
|
9
8
|
UnknownDeployments,
|
|
10
9
|
UnresolvedNetworkSpecificData,
|
|
11
10
|
UnresolvedUnknownNamedAccounts,
|
|
12
11
|
} from '../environment/types.js';
|
|
13
|
-
import {createEnvironment} from '../environment/index.js';
|
|
14
|
-
import {DeployScriptFunction, DeployScriptModule} from './types.js';
|
|
12
|
+
import {createEnvironment, SignerProtocolFunction} from '../environment/index.js';
|
|
13
|
+
import {DeployScriptFunction, DeployScriptModule, EnhancedDeployScriptFunction, EnhancedEnvironment} from './types.js';
|
|
14
|
+
import {withEnvironment} from '../utils/curry.js';
|
|
15
15
|
import {logger, setLogLevel, spin} from '../internal/logging.js';
|
|
16
16
|
import {EIP1193GenericRequestProvider, EIP1193ProviderWithoutEvents} from 'eip-1193';
|
|
17
17
|
import {getRoughGasPriceEstimate} from '../utils/eth.js';
|
|
@@ -19,24 +19,70 @@ import prompts from 'prompts';
|
|
|
19
19
|
import {formatEther} from 'viem';
|
|
20
20
|
import {tsImport} from 'tsx/esm/api';
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
/**
|
|
23
|
+
* Setup function that creates the execute function for deploy scripts. It allow to specify a set of functions that will be available in the environment.
|
|
24
|
+
*
|
|
25
|
+
* @param functions - An object of utility functions that expect Environment as their first parameter
|
|
26
|
+
* @returns An execute function that provides an enhanced environment with curried functions
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```typescript
|
|
30
|
+
* const functions = {
|
|
31
|
+
* deploy: (env: Environment, contractName: string, args: any[]) => Promise<void>,
|
|
32
|
+
* verify: (env: Environment, address: string) => Promise<boolean>
|
|
33
|
+
* };
|
|
34
|
+
*
|
|
35
|
+
* const execute = setup(functions);
|
|
36
|
+
*
|
|
37
|
+
* export default execute(async (env, args) => {
|
|
38
|
+
* // env now includes both the original environment AND the curried functions
|
|
39
|
+
* await env.deploy('MyContract', []); // No need to pass env
|
|
40
|
+
* await env.verify('0x123...'); // No need to pass env
|
|
41
|
+
*
|
|
42
|
+
* // Original environment properties are still available
|
|
43
|
+
* console.log(env.network.name);
|
|
44
|
+
* const deployment = env.get('MyContract');
|
|
45
|
+
* }, { tags: ['deploy'] });
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
48
|
+
export function setup<
|
|
49
|
+
Functions extends Record<string, (env: Environment<any, any, any>, ...args: any[]) => any> = {},
|
|
23
50
|
NamedAccounts extends UnresolvedUnknownNamedAccounts = UnresolvedUnknownNamedAccounts,
|
|
24
51
|
Data extends UnresolvedNetworkSpecificData = UnresolvedNetworkSpecificData,
|
|
25
|
-
ArgumentsType = undefined,
|
|
26
52
|
Deployments extends UnknownDeployments = UnknownDeployments
|
|
27
|
-
>(
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
53
|
+
>(functions: Functions, signerProtocols?: Record<string, SignerProtocolFunction>) {
|
|
54
|
+
return function enhancedExecute<ArgumentsType = undefined>(
|
|
55
|
+
callback: EnhancedDeployScriptFunction<NamedAccounts, Data, ArgumentsType, Deployments, Functions>,
|
|
56
|
+
options: {tags?: string[]; dependencies?: string[]; id?: string; runAtTheEnd?: boolean}
|
|
57
|
+
): DeployScriptModule<NamedAccounts, Data, ArgumentsType, Deployments> {
|
|
58
|
+
const scriptModule: DeployScriptModule<NamedAccounts, Data, ArgumentsType, Deployments> = (
|
|
59
|
+
env: Environment<NamedAccounts, Data, Deployments>,
|
|
60
|
+
args?: ArgumentsType
|
|
61
|
+
) => {
|
|
62
|
+
if (signerProtocols) {
|
|
63
|
+
for (const key of Object.keys(signerProtocols)) {
|
|
64
|
+
env.registerProtocol(key, signerProtocols[key]);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Create the enhanced environment by combining the original environment with curried functions
|
|
69
|
+
const curriedFunctions = withEnvironment(env, functions);
|
|
70
|
+
const enhancedEnv = Object.assign(
|
|
71
|
+
Object.create(Object.getPrototypeOf(env)),
|
|
72
|
+
env,
|
|
73
|
+
curriedFunctions
|
|
74
|
+
) as EnhancedEnvironment<NamedAccounts, Data, Deployments, Functions>;
|
|
75
|
+
|
|
76
|
+
return callback(enhancedEnv, args);
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
scriptModule.tags = options.tags;
|
|
80
|
+
scriptModule.dependencies = options.dependencies;
|
|
81
|
+
scriptModule.id = options.id;
|
|
82
|
+
scriptModule.runAtTheEnd = options.runAtTheEnd;
|
|
83
|
+
|
|
84
|
+
return scriptModule;
|
|
85
|
+
};
|
|
40
86
|
}
|
|
41
87
|
|
|
42
88
|
export type NamedAccountExecuteFunction<
|
|
@@ -107,43 +153,10 @@ export type UserConfig<
|
|
|
107
153
|
data?: Data;
|
|
108
154
|
};
|
|
109
155
|
|
|
110
|
-
export
|
|
156
|
+
export function transformUserConfig<
|
|
111
157
|
NamedAccounts extends UnresolvedUnknownNamedAccounts = UnresolvedUnknownNamedAccounts,
|
|
112
158
|
Data extends UnresolvedNetworkSpecificData = UnresolvedNetworkSpecificData
|
|
113
|
-
>(
|
|
114
|
-
type ConfigFile = UserConfig<NamedAccounts, Data>;
|
|
115
|
-
let configFile: ConfigFile | undefined;
|
|
116
|
-
|
|
117
|
-
// TODO more sophisticated config file finding mechanism (look up parents, etc..)
|
|
118
|
-
const tsFilePath = path.join(process.cwd(), 'rocketh.ts');
|
|
119
|
-
const jsFilePath = path.join(process.cwd(), 'rocketh.js');
|
|
120
|
-
|
|
121
|
-
const tsVersionExists = fs.existsSync(tsFilePath);
|
|
122
|
-
const jsVersionExists = fs.existsSync(jsFilePath);
|
|
123
|
-
const existingConfigs = [tsVersionExists, jsVersionExists].filter(Boolean).length;
|
|
124
|
-
|
|
125
|
-
// console.log({tsFilePath, tsVersionExists, existingConfigs});
|
|
126
|
-
|
|
127
|
-
// Throw error if multiple config files exist
|
|
128
|
-
if (existingConfigs > 1) {
|
|
129
|
-
throw new Error('Multiple configuration files found. Please use only one of: rocketh.ts, rocketh.js');
|
|
130
|
-
}
|
|
131
|
-
if (tsVersionExists) {
|
|
132
|
-
const moduleLoaded = await tsImport(`file://${tsFilePath}`, import.meta.url);
|
|
133
|
-
configFile = moduleLoaded.config;
|
|
134
|
-
// console.log({tsVersionExists: configFile});
|
|
135
|
-
// if ((configFile as any).default) {
|
|
136
|
-
// configFile = (configFile as any).default as ConfigFile;
|
|
137
|
-
// if ((configFile as any).default) {
|
|
138
|
-
// logger.warn(`double default...`);
|
|
139
|
-
// configFile = (configFile as any).default as ConfigFile;
|
|
140
|
-
// }
|
|
141
|
-
// }
|
|
142
|
-
} else if (jsVersionExists) {
|
|
143
|
-
const moduleLoaded = await tsImport(`file://${jsFilePath}`, import.meta.url);
|
|
144
|
-
configFile = moduleLoaded.config;
|
|
145
|
-
}
|
|
146
|
-
|
|
159
|
+
>(configFile: UserConfig<NamedAccounts, Data> | undefined, options: ConfigOptions) {
|
|
147
160
|
if (configFile) {
|
|
148
161
|
if (!options.deployments && configFile.deployments) {
|
|
149
162
|
options.deployments = configFile.deployments;
|
|
@@ -257,6 +270,51 @@ export async function readConfig<
|
|
|
257
270
|
}
|
|
258
271
|
}
|
|
259
272
|
|
|
273
|
+
export async function readConfig<
|
|
274
|
+
NamedAccounts extends UnresolvedUnknownNamedAccounts = UnresolvedUnknownNamedAccounts,
|
|
275
|
+
Data extends UnresolvedNetworkSpecificData = UnresolvedNetworkSpecificData
|
|
276
|
+
>(options: ConfigOptions): Promise<Config<NamedAccounts, Data>> {
|
|
277
|
+
type ConfigFile = UserConfig<NamedAccounts, Data>;
|
|
278
|
+
let configFile: ConfigFile | undefined;
|
|
279
|
+
|
|
280
|
+
let tsVersion: string | undefined;
|
|
281
|
+
let jsVersion: string | undefined;
|
|
282
|
+
|
|
283
|
+
if (typeof process !== 'undefined') {
|
|
284
|
+
// TODO more sophisticated config file finding mechanism (look up parents, etc..)
|
|
285
|
+
const tsFilePath = path.join(process.cwd(), 'rocketh.ts');
|
|
286
|
+
const jsFilePath = path.join(process.cwd(), 'rocketh.js');
|
|
287
|
+
|
|
288
|
+
tsVersion = fs.existsSync(tsFilePath) ? `file://${tsFilePath}` : undefined;
|
|
289
|
+
jsVersion = fs.existsSync(jsFilePath) ? `file://${jsFilePath}` : undefined;
|
|
290
|
+
}
|
|
291
|
+
const existingConfigs = [tsVersion, jsVersion].filter(Boolean).length;
|
|
292
|
+
|
|
293
|
+
// console.log({tsFilePath, tsVersionExists, existingConfigs});
|
|
294
|
+
|
|
295
|
+
// Throw error if multiple config files exist
|
|
296
|
+
if (existingConfigs > 1) {
|
|
297
|
+
throw new Error('Multiple configuration files found. Please use only one of: rocketh.ts, rocketh.js');
|
|
298
|
+
}
|
|
299
|
+
if (tsVersion) {
|
|
300
|
+
const moduleLoaded = await tsImport(tsVersion, import.meta.url);
|
|
301
|
+
configFile = moduleLoaded.config;
|
|
302
|
+
// console.log({tsVersionExists: configFile});
|
|
303
|
+
// if ((configFile as any).default) {
|
|
304
|
+
// configFile = (configFile as any).default as ConfigFile;
|
|
305
|
+
// if ((configFile as any).default) {
|
|
306
|
+
// logger.warn(`double default...`);
|
|
307
|
+
// configFile = (configFile as any).default as ConfigFile;
|
|
308
|
+
// }
|
|
309
|
+
// }
|
|
310
|
+
} else if (jsVersion) {
|
|
311
|
+
const moduleLoaded = await tsImport(jsVersion, import.meta.url);
|
|
312
|
+
configFile = moduleLoaded.config;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
return transformUserConfig(configFile, options);
|
|
316
|
+
}
|
|
317
|
+
|
|
260
318
|
export async function readAndResolveConfig<
|
|
261
319
|
NamedAccounts extends UnresolvedUnknownNamedAccounts = UnresolvedUnknownNamedAccounts,
|
|
262
320
|
Data extends UnresolvedNetworkSpecificData = UnresolvedNetworkSpecificData
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import type {Environment} from '../environment/types.js';
|
|
2
|
+
import {setup} from './index.js';
|
|
3
|
+
|
|
4
|
+
// Mock environment for testing
|
|
5
|
+
const mockEnv = {} as Environment;
|
|
6
|
+
|
|
7
|
+
// Example utility functions that take Environment as first parameter
|
|
8
|
+
const utilityFunctions = {
|
|
9
|
+
deployContract: async (env: Environment, contractName: string, args: any[] = []): Promise<string> => {
|
|
10
|
+
console.log(`Deploying ${contractName} with args:`, args);
|
|
11
|
+
return '0x1234567890123456789012345678901234567890';
|
|
12
|
+
},
|
|
13
|
+
|
|
14
|
+
verifyContract: async (env: Environment, address: string): Promise<boolean> => {
|
|
15
|
+
console.log(`Verifying contract at ${address}`);
|
|
16
|
+
return true;
|
|
17
|
+
},
|
|
18
|
+
|
|
19
|
+
getBalance: async (env: Environment, address: string): Promise<bigint> => {
|
|
20
|
+
console.log(`Getting balance for ${address}`);
|
|
21
|
+
return BigInt('1000000000000000000'); // 1 ETH
|
|
22
|
+
},
|
|
23
|
+
|
|
24
|
+
calculateGas: (env: Environment, operation: string): number => {
|
|
25
|
+
console.log(`Calculating gas for ${operation}`);
|
|
26
|
+
return 21000;
|
|
27
|
+
},
|
|
28
|
+
|
|
29
|
+
isDeployed: (env: Environment, contractName: string): boolean => {
|
|
30
|
+
console.log(`Checking if ${contractName} is deployed`);
|
|
31
|
+
return false;
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
// Create the enhanced execute function using setup
|
|
36
|
+
const execute = setup(utilityFunctions);
|
|
37
|
+
|
|
38
|
+
// Test the enhanced execute function
|
|
39
|
+
const testScript = execute(
|
|
40
|
+
async (env, args) => {
|
|
41
|
+
// Type test: env should have both original Environment properties AND curried functions
|
|
42
|
+
|
|
43
|
+
// Test curried functions (no need to pass env)
|
|
44
|
+
const address = await env.deployContract('MyToken', ['TokenName', 'TKN']);
|
|
45
|
+
const isVerified = await env.verifyContract(address);
|
|
46
|
+
const balance = await env.getBalance(address);
|
|
47
|
+
const gasEstimate = env.calculateGas('transfer');
|
|
48
|
+
const deployed = env.isDeployed('MyToken');
|
|
49
|
+
|
|
50
|
+
// Test that original environment properties are still accessible
|
|
51
|
+
// (These would normally be available on a real environment)
|
|
52
|
+
// console.log('Network name:', env.network?.name);
|
|
53
|
+
// console.log('Chain ID:', env.network?.chain?.id);
|
|
54
|
+
|
|
55
|
+
console.log('Test results:', {
|
|
56
|
+
address,
|
|
57
|
+
isVerified,
|
|
58
|
+
balance: balance.toString(),
|
|
59
|
+
gasEstimate,
|
|
60
|
+
deployed,
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
return true; // Return true to indicate successful completion
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
tags: ['test'],
|
|
67
|
+
dependencies: [],
|
|
68
|
+
id: 'test-setup-function',
|
|
69
|
+
}
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
// Type tests - these should compile without errors
|
|
73
|
+
async function testTypes() {
|
|
74
|
+
// The script should be a valid DeployScriptModule
|
|
75
|
+
console.log('Script tags:', testScript.tags);
|
|
76
|
+
console.log('Script dependencies:', testScript.dependencies);
|
|
77
|
+
console.log('Script ID:', testScript.id);
|
|
78
|
+
|
|
79
|
+
// The script should be callable with an environment
|
|
80
|
+
try {
|
|
81
|
+
const result = await testScript(mockEnv, undefined);
|
|
82
|
+
console.log('Script execution result:', result);
|
|
83
|
+
} catch (error) {
|
|
84
|
+
console.log('Script execution test completed (expected with mock env)');
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Example of how this would be used in a real deployment script
|
|
89
|
+
export const exampleUsage = () => {
|
|
90
|
+
// Define your utility functions
|
|
91
|
+
const myFunctions = {
|
|
92
|
+
deployERC20: async (env: Environment, name: string, symbol: string): Promise<string> => {
|
|
93
|
+
// Implementation would use env.save, env.network.provider, etc.
|
|
94
|
+
return '0x...';
|
|
95
|
+
},
|
|
96
|
+
|
|
97
|
+
setupPermissions: async (env: Environment, contractAddress: string, admin: string): Promise<void> => {
|
|
98
|
+
// Implementation would interact with contracts
|
|
99
|
+
},
|
|
100
|
+
|
|
101
|
+
verifyOnEtherscan: async (env: Environment, address: string, constructorArgs: any[]): Promise<boolean> => {
|
|
102
|
+
// Implementation would call verification service
|
|
103
|
+
return true;
|
|
104
|
+
},
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
// Create the enhanced execute function
|
|
108
|
+
const execute = setup(myFunctions);
|
|
109
|
+
|
|
110
|
+
// Export your deployment script
|
|
111
|
+
return execute(
|
|
112
|
+
async (env, args) => {
|
|
113
|
+
// Now you can use the functions without passing env each time
|
|
114
|
+
const tokenAddress = await env.deployERC20('MyToken', 'MTK');
|
|
115
|
+
await env.setupPermissions(tokenAddress, env.namedAccounts.deployer);
|
|
116
|
+
await env.verifyOnEtherscan(tokenAddress, ['MyToken', 'MTK']);
|
|
117
|
+
|
|
118
|
+
// Original environment is still fully accessible
|
|
119
|
+
console.log(`Deployed on network: ${env.network.name}`);
|
|
120
|
+
const deployment = env.get('MyToken');
|
|
121
|
+
|
|
122
|
+
return true;
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
tags: ['token', 'deploy'],
|
|
126
|
+
dependencies: ['setup'],
|
|
127
|
+
id: 'deploy-my-token',
|
|
128
|
+
}
|
|
129
|
+
);
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
// Export for potential use in actual tests
|
|
133
|
+
export {testTypes, testScript, utilityFunctions};
|
package/src/executor/types.ts
CHANGED
|
@@ -30,3 +30,48 @@ export type ScriptCallback<
|
|
|
30
30
|
Data extends UnresolvedNetworkSpecificData = UnresolvedNetworkSpecificData,
|
|
31
31
|
Deployments extends UnknownDeployments = UnknownDeployments
|
|
32
32
|
> = (env: Environment<NamedAccounts, Data, Deployments>) => Promise<void>;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Utility type to remove the first parameter from a function type
|
|
36
|
+
*/
|
|
37
|
+
type RemoveFirstParameter<T> = T extends (first: any, ...rest: infer R) => infer Return
|
|
38
|
+
? (...args: R) => Return
|
|
39
|
+
: never;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Utility type to transform an object of functions by removing their first parameter
|
|
43
|
+
*/
|
|
44
|
+
type CurriedFunctions<T> = {
|
|
45
|
+
[K in keyof T]: RemoveFirstParameter<T[K]>;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Type for the enhanced environment proxy that includes both the original environment
|
|
50
|
+
* and the curried functions
|
|
51
|
+
*/
|
|
52
|
+
export type EnhancedEnvironment<
|
|
53
|
+
NamedAccounts extends UnresolvedUnknownNamedAccounts = UnresolvedUnknownNamedAccounts,
|
|
54
|
+
Data extends UnresolvedNetworkSpecificData = UnresolvedNetworkSpecificData,
|
|
55
|
+
Deployments extends UnknownDeployments = UnknownDeployments,
|
|
56
|
+
Functions extends Record<
|
|
57
|
+
string,
|
|
58
|
+
(env: Environment<NamedAccounts, Data, Deployments>, ...args: any[]) => any
|
|
59
|
+
> = Record<string, (env: Environment<NamedAccounts, Data, Deployments>, ...args: any[]) => any>
|
|
60
|
+
> = Environment<NamedAccounts, Data, Deployments> & CurriedFunctions<Functions>;
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Type for a deploy script function that receives an enhanced environment
|
|
64
|
+
*/
|
|
65
|
+
export type EnhancedDeployScriptFunction<
|
|
66
|
+
NamedAccounts extends UnresolvedUnknownNamedAccounts = UnresolvedUnknownNamedAccounts,
|
|
67
|
+
Data extends UnresolvedNetworkSpecificData = UnresolvedNetworkSpecificData,
|
|
68
|
+
ArgumentsTypes = undefined,
|
|
69
|
+
Deployments extends UnknownDeployments = UnknownDeployments,
|
|
70
|
+
Functions extends Record<
|
|
71
|
+
string,
|
|
72
|
+
(env: Environment<NamedAccounts, Data, Deployments>, ...args: any[]) => any
|
|
73
|
+
> = Record<string, (env: Environment<NamedAccounts, Data, Deployments>, ...args: any[]) => any>
|
|
74
|
+
> = (
|
|
75
|
+
env: EnhancedEnvironment<NamedAccounts, Data, Deployments, Functions>,
|
|
76
|
+
args?: ArgumentsTypes
|
|
77
|
+
) => Promise<void | boolean>;
|
package/src/index.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
export * from './executor/index.js';
|
|
2
2
|
export * from './executor/types.js';
|
|
3
3
|
export * from './environment/types.js';
|
|
4
|
-
export {extendEnvironment, handleSignerProtocol} from './environment/index.js';
|
|
5
4
|
export {loadDeployments} from './environment/deployments.js';
|
|
6
5
|
export * from './environment/utils/artifacts.js';
|
|
7
6
|
export * from './environment/utils/chains.js';
|
package/src/internal/types.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
import {SignerProtocol} from '../environment/index.js';
|
|
2
|
+
|
|
1
3
|
export type InternalEnvironment = {
|
|
2
4
|
exportDeploymentsAsTypes(): Promise<void>;
|
|
3
5
|
recoverTransactionsIfAny(): Promise<void>;
|
|
4
6
|
recordMigration(id: string): void;
|
|
7
|
+
getSignerProtocol(protocol: string): SignerProtocol | undefined;
|
|
5
8
|
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type {Environment} from '../environment/types.js';
|
|
2
|
+
import {withEnvironment} from './curry.js';
|
|
3
|
+
|
|
4
|
+
// Mock environment for testing
|
|
5
|
+
const mockEnv = {} as Environment;
|
|
6
|
+
|
|
7
|
+
// Example functions that take environment as first parameter
|
|
8
|
+
const exampleFunctions = {
|
|
9
|
+
deploy: (env: Environment, contractName: string, args: any[]): Promise<void> => {
|
|
10
|
+
return Promise.resolve();
|
|
11
|
+
},
|
|
12
|
+
|
|
13
|
+
verify: (env: Environment, address: string): Promise<boolean> => {
|
|
14
|
+
return Promise.resolve(true);
|
|
15
|
+
},
|
|
16
|
+
|
|
17
|
+
getBalance: (env: Environment, address: string): Promise<bigint> => {
|
|
18
|
+
return Promise.resolve(BigInt(0));
|
|
19
|
+
},
|
|
20
|
+
|
|
21
|
+
syncFunction: (env: Environment, value: number): number => {
|
|
22
|
+
return value * 2;
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
// Test the currying function
|
|
27
|
+
const curriedFunctions = withEnvironment(mockEnv, exampleFunctions);
|
|
28
|
+
|
|
29
|
+
// Type tests - these should compile without errors
|
|
30
|
+
async function testTypes() {
|
|
31
|
+
// These calls should work without passing env
|
|
32
|
+
await curriedFunctions.deploy('MyContract', []);
|
|
33
|
+
const isVerified = await curriedFunctions.verify('0x123...');
|
|
34
|
+
const balance = await curriedFunctions.getBalance('0x456...');
|
|
35
|
+
const doubled = curriedFunctions.syncFunction(42);
|
|
36
|
+
|
|
37
|
+
console.log('Type tests passed!');
|
|
38
|
+
console.log({isVerified, balance, doubled});
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Export for potential use in actual tests
|
|
42
|
+
export {testTypes, curriedFunctions, exampleFunctions};
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
Environment,
|
|
3
|
+
UnknownDeployments,
|
|
4
|
+
UnresolvedNetworkSpecificData,
|
|
5
|
+
UnresolvedUnknownNamedAccounts,
|
|
6
|
+
} from '../environment/types.js';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Utility type to remove the first parameter from a function type
|
|
10
|
+
*/
|
|
11
|
+
type RemoveFirstParameter<T> = T extends (first: any, ...rest: infer R) => infer Return
|
|
12
|
+
? (...args: R) => Return
|
|
13
|
+
: never;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Utility type to transform an object of functions by removing their first parameter
|
|
17
|
+
*/
|
|
18
|
+
type CurriedFunctions<T> = {
|
|
19
|
+
[K in keyof T]: RemoveFirstParameter<T[K]>;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Creates a curried version of functions that automatically inject an environment as the first parameter.
|
|
24
|
+
*
|
|
25
|
+
* @param env - The environment object to inject as the first parameter
|
|
26
|
+
* @param functions - An object containing functions that expect the environment as their first parameter
|
|
27
|
+
* @returns An object with the same function names, but with the environment parameter removed
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```typescript
|
|
31
|
+
* const functions = {
|
|
32
|
+
* deploy: (env: Environment, contractName: string, args: any[]) => Promise<void>,
|
|
33
|
+
* verify: (env: Environment, address: string) => Promise<boolean>
|
|
34
|
+
* };
|
|
35
|
+
*
|
|
36
|
+
* const curriedFunctions = withEnvironment(env, functions);
|
|
37
|
+
*
|
|
38
|
+
* // Now you can call without passing env:
|
|
39
|
+
* await curriedFunctions.deploy('MyContract', []);
|
|
40
|
+
* await curriedFunctions.verify('0x123...');
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
43
|
+
export function withEnvironment<
|
|
44
|
+
NamedAccounts extends UnresolvedUnknownNamedAccounts = UnresolvedUnknownNamedAccounts,
|
|
45
|
+
Data extends UnresolvedNetworkSpecificData = UnresolvedNetworkSpecificData,
|
|
46
|
+
Deployments extends UnknownDeployments = UnknownDeployments,
|
|
47
|
+
T extends Record<string, (env: Environment<NamedAccounts, Data, Deployments>, ...args: any[]) => any> = Record<
|
|
48
|
+
string,
|
|
49
|
+
(env: Environment<NamedAccounts, Data, Deployments>, ...args: any[]) => any
|
|
50
|
+
>
|
|
51
|
+
>(env: Environment<NamedAccounts, Data, Deployments>, functions: T): CurriedFunctions<T> {
|
|
52
|
+
const result = {} as CurriedFunctions<T>;
|
|
53
|
+
|
|
54
|
+
for (const [key, func] of Object.entries(functions)) {
|
|
55
|
+
// Create a new function that automatically passes the environment as the first argument
|
|
56
|
+
(result as any)[key] = (...args: any[]) => func(env, ...args);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return result;
|
|
60
|
+
}
|