Skip to content

Commit 1b45ebf

Browse files
authored
Merge pull request #883 from LIT-Protocol/feature/jss-81-naga-bug-overwrite-rpc-url-based-880
[Feature] Overwrite RPC URL
2 parents 7b54590 + 249d8ac commit 1b45ebf

File tree

14 files changed

+277
-36
lines changed

14 files changed

+277
-36
lines changed

e2e/src/e2e.spec.ts

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,14 @@ import {
1919
} from './helper/tests';
2020
import { init } from './init';
2121

22+
const RPC_OVERRIDE = process.env['LIT_YELLOWSTONE_PRIVATE_RPC_URL'];
23+
if (RPC_OVERRIDE) {
24+
console.log(
25+
'🧪 E2E: Using RPC override (LIT_YELLOWSTONE_PRIVATE_RPC_URL):',
26+
RPC_OVERRIDE
27+
);
28+
}
29+
2230
describe('all', () => {
2331
// Singleton baby
2432
let ctx: Awaited<ReturnType<typeof init>>;
@@ -178,3 +186,114 @@ describe('all', () => {
178186
});
179187
});
180188
});
189+
190+
describe('rpc override', () => {
191+
const TEST_RPC = process.env.LIT_YELLOWSTONE_PRIVATE_RPC_URL;
192+
// const TEST_RPC = 'https://yellowstone-override.example';
193+
194+
// beforeAll(() => {
195+
// process.env.LIT_YELLOWSTONE_PRIVATE_RPC_URL = TEST_RPC;
196+
// });
197+
198+
// afterAll(() => {
199+
// process.env.LIT_YELLOWSTONE_PRIVATE_RPC_URL = ORIGINAL_RPC;
200+
// });
201+
202+
it('applies env rpc override to module and client', async () => {
203+
const networks = await import('@lit-protocol/networks');
204+
205+
// choose module by NETWORK env (same way init.ts does)
206+
const network = process.env.NETWORK || 'naga-dev';
207+
const importNameMap: Record<string, string> = {
208+
'naga-dev': 'nagaDev',
209+
'naga-test': 'nagaTest',
210+
'naga-local': 'nagaLocal',
211+
'naga-staging': 'nagaStaging',
212+
};
213+
const importName = importNameMap[network];
214+
const baseModule: any = (networks as any)[importName];
215+
216+
// apply override
217+
const mod =
218+
typeof baseModule.withOverrides === 'function'
219+
? baseModule.withOverrides({ rpcUrl: TEST_RPC })
220+
: baseModule;
221+
222+
// log for verification
223+
// base vs effective (when override is supported)
224+
const baseRpcUrl =
225+
typeof baseModule.getRpcUrl === 'function'
226+
? baseModule.getRpcUrl()
227+
: 'n/a';
228+
const effRpcUrl =
229+
typeof mod.getRpcUrl === 'function' ? mod.getRpcUrl() : 'n/a';
230+
// eslint-disable-next-line no-console
231+
console.log('[rpc-override] TEST_RPC:', TEST_RPC);
232+
// eslint-disable-next-line no-console
233+
console.log(
234+
'[rpc-override] module rpc (base → effective):',
235+
baseRpcUrl,
236+
'→',
237+
effRpcUrl
238+
);
239+
try {
240+
const baseChain =
241+
typeof baseModule.getChainConfig === 'function'
242+
? baseModule.getChainConfig()
243+
: null;
244+
const effChain =
245+
typeof mod.getChainConfig === 'function' ? mod.getChainConfig() : null;
246+
if (baseChain && effChain) {
247+
// eslint-disable-next-line no-console
248+
console.log(
249+
'[rpc-override] module chain id/name (base → effective):',
250+
`${baseChain.id}/${baseChain.name}`,
251+
'→',
252+
`${effChain.id}/${effChain.name}`
253+
);
254+
// eslint-disable-next-line no-console
255+
console.log(
256+
'[rpc-override] module rpcUrls.default.http (base → effective):',
257+
baseChain.rpcUrls.default.http,
258+
'→',
259+
effChain.rpcUrls.default.http
260+
);
261+
// eslint-disable-next-line no-console
262+
console.log(
263+
'[rpc-override] module rpcUrls.public.http (base → effective):',
264+
(baseChain.rpcUrls as any)['public']?.http,
265+
'→',
266+
(effChain.rpcUrls as any)['public']?.http
267+
);
268+
}
269+
} catch {}
270+
271+
// module reflects override
272+
expect(mod.getRpcUrl()).toBe(TEST_RPC);
273+
const chain = mod.getChainConfig();
274+
expect(chain.rpcUrls.default.http[0]).toBe(TEST_RPC);
275+
expect((chain.rpcUrls as any)['public'].http[0]).toBe(TEST_RPC);
276+
277+
// client reflects override
278+
const { createLitClient } = await import('@lit-protocol/lit-client');
279+
const client = await createLitClient({ network: mod });
280+
const cc = client.getChainConfig();
281+
282+
// eslint-disable-next-line no-console
283+
console.log('[rpc-override] client rpcUrl:', cc.rpcUrl);
284+
// eslint-disable-next-line no-console
285+
console.log(
286+
'[rpc-override] client viem rpcUrls.default:',
287+
cc.viemConfig.rpcUrls.default.http
288+
);
289+
// eslint-disable-next-line no-console
290+
console.log(
291+
'[rpc-override] client viem rpcUrls.public:',
292+
(cc.viemConfig.rpcUrls as any)['public']?.http
293+
);
294+
295+
expect(cc.rpcUrl).toBe(TEST_RPC);
296+
expect(cc.viemConfig.rpcUrls.default.http[0]).toBe(TEST_RPC);
297+
expect((cc.viemConfig.rpcUrls as any)['public'].http[0]).toBe(TEST_RPC);
298+
});
299+
});

e2e/src/init.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,21 @@ export const init = async (
119119

120120
// Dynamic import of network module
121121
const networksModule = await import('@lit-protocol/networks');
122-
const _networkModule = networksModule[config.importName];
122+
const _baseNetworkModule = networksModule[config.importName];
123+
124+
// Optional RPC override from env
125+
const rpcOverride = process.env['LIT_YELLOWSTONE_PRIVATE_RPC_URL'];
126+
const _networkModule =
127+
rpcOverride && typeof _baseNetworkModule.withOverrides === 'function'
128+
? _baseNetworkModule.withOverrides({ rpcUrl: rpcOverride })
129+
: _baseNetworkModule;
130+
131+
if (rpcOverride) {
132+
console.log(
133+
'✅ Using RPC override (LIT_YELLOWSTONE_PRIVATE_RPC_URL):',
134+
rpcOverride
135+
);
136+
}
123137

124138
// Fund accounts based on network type
125139
const isLocal = config.type === 'local';

packages/auth-services/src/_setup/initSystemContext.ts

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,13 @@ declare global {
1515
};
1616
}
1717

18-
export async function initSystemContext({ appName }: { appName: string }) {
18+
export async function initSystemContext({
19+
appName,
20+
rpcUrl,
21+
}: {
22+
appName: string;
23+
rpcUrl?: string;
24+
}) {
1925
console.log('🔥 [initSystemContext] Initializing system context...');
2026

2127
let networkModule: any;
@@ -34,8 +40,22 @@ export async function initSystemContext({ appName }: { appName: string }) {
3440
throw new Error(`Unsupported network: ${env.NETWORK}`);
3541
}
3642

43+
const overrideRpc = rpcUrl || env.LIT_TXSENDER_RPC_URL;
44+
45+
// Apply runtime override if rpcUrl provided
46+
const effectiveModule =
47+
overrideRpc && typeof networkModule.withOverrides === 'function'
48+
? networkModule.withOverrides({ rpcUrl: overrideRpc })
49+
: networkModule;
50+
51+
try {
52+
const baseRpc = typeof networkModule.getRpcUrl === 'function' ? networkModule.getRpcUrl() : 'n/a';
53+
const effRpc = typeof effectiveModule.getRpcUrl === 'function' ? effectiveModule.getRpcUrl() : 'n/a';
54+
console.log('[initSystemContext] RPC (base → effective):', baseRpc, '→', effRpc);
55+
} catch {}
56+
3757
const litClient = await createLitClient({
38-
network: networkModule,
58+
network: effectiveModule,
3959
});
4060

4161
const account = privateKeyToAccount(env.LIT_TXSENDER_PRIVATE_KEY as Hex);

packages/auth-services/src/auth-server/src/createAuthServer.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,10 @@ export const createLitAuthServer = (
9191
// =============================================================
9292
// Ensure system context is initialized before server fully starts, using appName from config
9393
// This was originally at the top level, moved here to use config.appName
94-
await initSystemContext({ appName: config.appName });
94+
await initSystemContext({
95+
appName: config.appName,
96+
rpcUrl: config.litTxsenderRpcUrl,
97+
});
9598
})
9699
.get('/', () => ({
97100
message: 'PKP Auth Service is running. PKP minting is now asynchronous.',

packages/auth-services/src/queue-manager/worker.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { initSystemContext } from '../_setup/initSystemContext';
22
import { bullmqConnectionOptions, mainQueueName } from './src/bullmqSetup';
33
import { createGenericWorker } from './src/genericWorker';
4+
import { env } from '../env';
45

56
interface ParsedRedisConnectionOpts {
67
host?: string;
@@ -10,7 +11,7 @@ interface ParsedRedisConnectionOpts {
1011
}
1112

1213
export async function startAuthServiceWorker() {
13-
await initSystemContext({ appName: 'auth-services-worker' });
14+
await initSystemContext({ appName: 'auth-services-worker', rpcUrl: env.LIT_TXSENDER_RPC_URL });
1415
console.log('------------------------------------------------------');
1516
console.log(' Attempting to start Generic BullMQ Worker Process... ');
1617
console.log('------------------------------------------------------');

packages/lit-client/src/lib/LitClient/createLitClient.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ import {
1010
} from '@lit-protocol/access-control-conditions';
1111
import { encrypt as blsEncrypt } from '@lit-protocol/crypto';
1212
import { getChildLogger } from '@lit-protocol/logger';
13-
import type {
14-
LitNetworkModule,
15-
PKPStorageProvider,
13+
import {
14+
type LitNetworkModule,
15+
type PKPStorageProvider,
1616
} from '@lit-protocol/networks';
1717
import {
1818
AuthContextSchema2,

packages/lit-client/src/lib/LitClient/intergrations/createPkpViemAccount.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -120,16 +120,14 @@ export async function createPKPViemAccount({
120120
tx,
121121
address,
122122
chain,
123-
transportUrl,
124123
}: {
125124
tx: Partial<TransactionSerializable>;
126125
address: `0x${string}`;
127126
chain: Chain;
128-
transportUrl: string;
129127
}): Promise<TransactionSerializable> {
130128
const client = createPublicClient({
131129
chain,
132-
transport: http(transportUrl),
130+
transport: http(chain.rpcUrls.default.http[0]),
133131
});
134132

135133
try {
@@ -246,7 +244,6 @@ export async function createPKPViemAccount({
246244
tx: txRequest,
247245
address,
248246
chain: chainConfig,
249-
transportUrl: chainConfig.rpcUrls.default.http[0],
250247
});
251248
} else {
252249
// Ensure minimum required fields for transaction type inference

packages/networks/src/chains/ChronicleYellowstone.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,27 @@ export const WagmiConfig = createConfig({
4141
[viemChainConfig.id]: http(),
4242
},
4343
});
44+
45+
/**
46+
* Resolve the effective RPC URL from an optional override.
47+
*/
48+
export function resolveRpcUrl(overrideRpc?: string): string {
49+
return overrideRpc ?? RPC_URL;
50+
}
51+
52+
/**
53+
* Build a Chain config using the base Chronicle Yellowstone config,
54+
* applying an optional RPC override to both default and public http URLs.
55+
*/
56+
export function buildViemChainConfig(overrideRpc?: string): Chain {
57+
const rpc = resolveRpcUrl(overrideRpc);
58+
const base = viemChainConfig;
59+
return {
60+
...base,
61+
rpcUrls: {
62+
...base.rpcUrls,
63+
default: { ...base.rpcUrls.default, http: [rpc] },
64+
public: { ...(base.rpcUrls as any)['public'], http: [rpc] },
65+
},
66+
} as Chain;
67+
}

packages/networks/src/networks/vNaga/envs/base/BaseNetworkEnvironment.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ export interface BaseEnvironmentOptions<T, M> {
1515
minimumThreshold?: number;
1616
httpProtocol?: 'http://' | 'https://';
1717
requiredAttestation?: boolean;
18+
rpcUrlOverride?: string;
1819
}
1920

2021
export abstract class BaseNetworkEnvironment<T, M> {
@@ -24,9 +25,9 @@ export abstract class BaseNetworkEnvironment<T, M> {
2425
this.config = {
2526
minimumThreshold: options.minimumThreshold || 3,
2627
network: options.network,
27-
rpcUrl: this.getRpcUrl(),
28+
rpcUrl: this.getRpcUrl(options.rpcUrlOverride),
2829
abiSignatures: options.abiSignatures,
29-
chainConfig: this.getChainConfig(),
30+
chainConfig: this.getChainConfig(options.rpcUrlOverride),
3031
httpProtocol: options.httpProtocol || 'https://',
3132
networkSpecificConfigs: options.networkSpecificConfigs,
3233
endpoints: this.getEndpoints(),
@@ -51,8 +52,8 @@ export abstract class BaseNetworkEnvironment<T, M> {
5152
return this.config.services;
5253
}
5354

54-
protected abstract getRpcUrl(): string;
55-
protected abstract getChainConfig(): Chain;
55+
protected abstract getRpcUrl(overrideRpc?: string): string;
56+
protected abstract getChainConfig(overrideRpc?: string): Chain;
5657
protected abstract getEndpoints(): NagaEndpointsType;
5758
protected abstract getDefaultRealmId(): bigint;
5859
}

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

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ export class NagaDevEnvironment extends BaseNetworkEnvironment<
2020
NagaDevSignatures,
2121
NagaDevSpecificConfigs
2222
> {
23-
constructor() {
23+
constructor(options?: { rpcUrlOverride?: string }) {
2424
super({
2525
network: NETWORK,
2626
abiSignatures: nagaDevSignatures,
@@ -34,15 +34,16 @@ export class NagaDevEnvironment extends BaseNetworkEnvironment<
3434
minimumThreshold: MINIMUM_THRESHOLD,
3535
httpProtocol: PROTOCOL,
3636
requiredAttestation: false,
37+
rpcUrlOverride: options?.rpcUrlOverride,
3738
});
3839
}
3940

40-
protected getRpcUrl(): string {
41-
return chainInfo.RPC_URL;
41+
protected getRpcUrl(overrideRpc?: string): string {
42+
return chainInfo.resolveRpcUrl(overrideRpc);
4243
}
4344

44-
protected getChainConfig(): Chain {
45-
return chainInfo.viemChainConfig;
45+
protected getChainConfig(overrideRpc?: string): Chain {
46+
return chainInfo.buildViemChainConfig(overrideRpc);
4647
}
4748

4849
protected getEndpoints(): NagaEndpointsType {

0 commit comments

Comments
 (0)