Skip to content

Commit 7102a6f

Browse files
committed
feat(networks): enable naga-local overrides with bundled signatures helper
1 parent 1454d34 commit 7102a6f

File tree

6 files changed

+165
-51
lines changed

6 files changed

+165
-51
lines changed

packages/contracts/src/custom-network-signatures.ts

Lines changed: 56 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,24 @@ interface ContractInfo {
3434
name: string;
3535
}
3636

37-
interface GenerateSignaturesOptions {
37+
export interface GenerateSignaturesOptions {
3838
jsonFilePath: string;
3939
networkName?: string;
4040
outputDir?: string;
4141
useScriptDirectory?: boolean; // If true, paths are relative to script location
4242
callerPath?: string; // The import.meta.url of the calling script
4343
}
4444

45+
export interface BuildSignaturesFromContextOptions
46+
extends Omit<GenerateSignaturesOptions, 'outputDir'> {}
47+
48+
export interface BuildSignaturesFromContextResult {
49+
signatures: GeneratedSignatures;
50+
networkName: string;
51+
resolvedJsonPath: string;
52+
baseDirectory: string;
53+
}
54+
4555
/**
4656
* Gets the base directory for resolving paths
4757
* @param useScriptDirectory - Whether to use script's directory or current working directory
@@ -179,6 +189,43 @@ function generateAbiSignatures(networkData: NetworkCache) {
179189
return signatures;
180190
}
181191

192+
export type GeneratedSignatures = ReturnType<typeof generateAbiSignatures>;
193+
194+
export function buildSignaturesFromContext(
195+
options: BuildSignaturesFromContextOptions
196+
): BuildSignaturesFromContextResult {
197+
const {
198+
jsonFilePath,
199+
networkName = 'custom-network',
200+
useScriptDirectory = false,
201+
callerPath,
202+
} = options;
203+
204+
if (useScriptDirectory && !callerPath) {
205+
throw new Error(
206+
'callerPath (import.meta.url) is required when useScriptDirectory is true'
207+
);
208+
}
209+
210+
const baseDirectory = getBaseDirectory(useScriptDirectory, callerPath);
211+
const resolvedJsonPath = resolvePath(jsonFilePath, baseDirectory);
212+
213+
console.log(`📝 Processing custom network context: ${resolvedJsonPath}`);
214+
215+
const rawJsonData = JSON.parse(fs.readFileSync(resolvedJsonPath, 'utf8'));
216+
const jsonData = convertToNetworkCache(rawJsonData, networkName);
217+
218+
console.log('📊 Generating signatures...');
219+
const signatures = generateAbiSignatures(jsonData);
220+
221+
return {
222+
signatures,
223+
networkName,
224+
resolvedJsonPath,
225+
baseDirectory,
226+
};
227+
}
228+
182229
/**
183230
* Generates signature files from a network context JSON file
184231
* @param options - Configuration options
@@ -187,45 +234,24 @@ function generateAbiSignatures(networkData: NetworkCache) {
187234
export async function generateSignaturesFromContext(
188235
options: GenerateSignaturesOptions
189236
): Promise<void> {
190-
const {
191-
jsonFilePath,
192-
networkName = 'custom-network',
193-
outputDir = './dist/signatures',
194-
useScriptDirectory = false,
195-
callerPath,
196-
} = options;
197-
198237
try {
199-
if (useScriptDirectory && !callerPath) {
200-
throw new Error(
201-
'callerPath (import.meta.url) is required when useScriptDirectory is true'
202-
);
203-
}
238+
const {
239+
signatures,
240+
networkName,
241+
resolvedJsonPath,
242+
baseDirectory,
243+
} = buildSignaturesFromContext(options);
204244

205-
const baseDir = getBaseDirectory(useScriptDirectory, callerPath);
206-
// Don't force relative for jsonFilePath (allow absolute paths)
207-
const resolvedJsonPath = resolvePath(jsonFilePath, baseDir);
208-
// Force relative for outputDir (always relative to script)
209-
const resolvedOutputDir = resolvePath(outputDir, baseDir, true);
245+
const outputDir = options.outputDir ?? './dist/signatures';
246+
const resolvedOutputDir = resolvePath(outputDir, baseDirectory, true);
210247

211248
// Ensure output directory exists
212249
if (!fs.existsSync(resolvedOutputDir)) {
213250
fs.mkdirSync(resolvedOutputDir, { recursive: true });
214251
}
215252

216-
console.log(`📝 Processing custom network context: ${resolvedJsonPath}`);
217253
console.log(`📁 Output directory: ${resolvedOutputDir}`);
218254

219-
// Read and parse the JSON file
220-
const rawJsonData = JSON.parse(fs.readFileSync(resolvedJsonPath, 'utf8'));
221-
222-
// Convert to NetworkCache format
223-
const jsonData = convertToNetworkCache(rawJsonData, networkName);
224-
225-
// Generate signatures using the standard format
226-
console.log('📊 Generating signatures...');
227-
const signatures = generateAbiSignatures(jsonData);
228-
229255
// Write signatures to file
230256
const outputPath = path.join(resolvedOutputDir, `${networkName}.js`);
231257
const outputPathCjs = path.join(resolvedOutputDir, `${networkName}.cjs`);

packages/e2e/src/init.ts

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,32 @@ export const init = async (
125125

126126
// Dynamic import of network module
127127
const networksModule = await import('@lit-protocol/networks');
128-
const _baseNetworkModule = networksModule[config.importName];
128+
let _baseNetworkModule = networksModule[config.importName];
129+
130+
if (_network === 'naga-local') {
131+
const localContextPath = process.env['NAGA_LOCAL_CONTEXT_PATH'];
132+
if (localContextPath) {
133+
const withLocalContext = (_baseNetworkModule as any)?.withLocalContext;
134+
135+
if (typeof withLocalContext === 'function') {
136+
const localContextName = process.env['NAGA_LOCAL_CONTEXT_NAME'];
137+
138+
console.log(
139+
'✅ Loading naga-local signatures from NAGA_LOCAL_CONTEXT_PATH:',
140+
localContextPath
141+
);
142+
143+
_baseNetworkModule = await withLocalContext({
144+
networkContextPath: localContextPath,
145+
networkName: localContextName,
146+
});
147+
} else {
148+
console.warn(
149+
'⚠️ NAGA_LOCAL_CONTEXT_PATH is set but nagaLocal.withLocalContext is unavailable in the current networks build.'
150+
);
151+
}
152+
}
153+
}
129154

130155
// Optional RPC override from env
131156
const rpcOverride = process.env['LIT_YELLOWSTONE_PRIVATE_RPC_URL'];
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
export { nagaLocal } from './naga-local.module';
2+
export type { NagaLocal, NagaLocalContextOptions } from './naga-local.module';

packages/networks/src/networks/vNaga/envs/naga-local/naga-local.env.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import * as chainInfo from '../../../../chains/Anvil';
33
import { NAGA_ENDPOINT } from '../../shared/managers/endpoints-manager/endpoints';
44
import type { NagaEndpointsType } from '../../shared/managers/endpoints-manager/endpoints';
55
import { BaseNetworkEnvironment } from '../base/BaseNetworkEnvironment';
6-
import { signatures } from './generated/naga-develop';
6+
import { signatures as defaultSignatures } from './generated/naga-develop';
77

88
const NETWORK = 'custom';
99
const PROTOCOL = 'http://'; // Note: Different from dev/staging
@@ -15,16 +15,20 @@ export interface NagaLocalSpecificConfigs {
1515
privateKey?: Hex; // Note: Local has private key config
1616
}
1717

18-
export type NagaLocalSignatures = typeof signatures;
18+
export type NagaLocalSignatures = typeof defaultSignatures;
1919

2020
export class NagaLocalEnvironment extends BaseNetworkEnvironment<
2121
NagaLocalSignatures,
2222
NagaLocalSpecificConfigs
2323
> {
24-
constructor(options?: { rpcUrlOverride?: string }) {
24+
constructor(options?: {
25+
rpcUrlOverride?: string;
26+
signatures?: NagaLocalSignatures;
27+
}) {
28+
const resolvedSignatures = options?.signatures ?? defaultSignatures;
2529
super({
2630
network: NETWORK,
27-
abiSignatures: signatures, // Note: Uses locally generated signatures
31+
abiSignatures: resolvedSignatures, // Note: Uses locally generated signatures
2832
networkSpecificConfigs: {
2933
realmId: DEFAULT_REALM_ID,
3034
privateKey: chainInfo.DEV_PRIVATE_KEY, // Note: Includes private key
Lines changed: 70 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,76 @@
1+
import { buildSignaturesFromContext } from '@lit-protocol/contracts/custom-network-signatures';
12
import { createBaseModule } from '../../shared/factories/BaseModuleFactory';
2-
import { createChainManager } from './chain-manager/createChainManager';
3-
import { nagaLocalEnvironment } from './naga-local.env';
3+
import { createChainManagerFactory } from '../../shared/factories/BaseChainManagerFactory';
4+
import {
5+
NagaLocalEnvironment,
6+
nagaLocalEnvironment,
7+
type NagaLocalSignatures,
8+
} from './naga-local.env';
49
import type { ExpectedAccountOrWalletClient } from '../../shared/managers/contract-manager/createContractsManager';
510

6-
const baseModule = createBaseModule({
7-
networkConfig: nagaLocalEnvironment.getConfig(),
8-
moduleName: nagaLocalEnvironment.getNetworkName(),
9-
createChainManager: (account: ExpectedAccountOrWalletClient) =>
10-
createChainManager(account),
11-
});
12-
13-
// Add local-specific methods and maintain backward compatibility
14-
const nagaLocal = {
15-
...baseModule,
16-
// Local environment specific getter for private key
17-
getPrivateKey: () => nagaLocalEnvironment.getPrivateKey(),
11+
type NagaLocalContextOptions = {
12+
networkContextPath: string;
13+
networkName?: string;
14+
rpcUrlOverride?: string;
1815
};
1916

20-
export type NagaLocal = typeof nagaLocal;
17+
const createChainManager = (
18+
env: NagaLocalEnvironment,
19+
account: ExpectedAccountOrWalletClient
20+
) => createChainManagerFactory(env.getConfig(), account);
21+
22+
const buildModule = (env: NagaLocalEnvironment) => {
23+
const base = createBaseModule({
24+
networkConfig: env.getConfig(),
25+
moduleName: env.getNetworkName(),
26+
createChainManager: (account: ExpectedAccountOrWalletClient) =>
27+
createChainManager(env, account),
28+
});
29+
30+
const createWithEnv = (nextEnv: NagaLocalEnvironment) =>
31+
buildModule(nextEnv);
32+
33+
const withOverrides = (overrides: { rpcUrl?: string }) => {
34+
const resolvedRpc =
35+
overrides.rpcUrl ?? env.getConfig().rpcUrl;
36+
37+
return createWithEnv(
38+
new NagaLocalEnvironment({
39+
rpcUrlOverride: resolvedRpc,
40+
signatures: env.getConfig().abiSignatures,
41+
})
42+
);
43+
};
44+
45+
const withLocalContext = (options: NagaLocalContextOptions) => {
46+
const { networkContextPath, networkName, rpcUrlOverride } = options;
47+
48+
const { signatures } = buildSignaturesFromContext({
49+
jsonFilePath: networkContextPath,
50+
networkName: networkName ?? 'naga-develop',
51+
});
52+
53+
const resolvedSignatures =
54+
signatures as unknown as NagaLocalSignatures;
55+
56+
return createWithEnv(
57+
new NagaLocalEnvironment({
58+
rpcUrlOverride: rpcUrlOverride ?? env.getConfig().rpcUrl,
59+
signatures: resolvedSignatures,
60+
})
61+
);
62+
};
63+
64+
return {
65+
...base,
66+
getPrivateKey: () => env.getPrivateKey(),
67+
withOverrides,
68+
withLocalContext,
69+
};
70+
};
71+
72+
const nagaLocal = buildModule(nagaLocalEnvironment);
73+
74+
export type NagaLocal = ReturnType<typeof buildModule>;
75+
export type { NagaLocalContextOptions };
2176
export { nagaLocal };

packages/networks/src/networks/vNaga/index.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
// Naga Local
22
export { nagaLocal } from './envs/naga-local';
3-
export type { NagaLocal as NagaLocalModule } from './envs/naga-local/naga-local.module';
3+
export type {
4+
NagaLocal as NagaLocalModule,
5+
NagaLocalContextOptions,
6+
} from './envs/naga-local/naga-local.module';
47

58
// Naga Dev
69
export { nagaDev } from './envs/naga-dev';

0 commit comments

Comments
 (0)