66 AddStarknetChainParameters ,
77 ChainId ,
88} from "@starknet-io/types-js" ;
9- import { shortString , WalletAccount } from "starknet" ;
9+ import { constants , shortString , WalletAccount } from "starknet" ;
1010import { version } from "../package.json" ;
1111import ControllerAccount from "./account" ;
1212import { NotReadyToConnect } from "./errors" ;
@@ -41,7 +41,19 @@ export default class ControllerProvider extends BaseProvider {
4141 constructor ( options : ControllerOptions ) {
4242 super ( ) ;
4343
44- this . selectedChain = options . defaultChainId ;
44+ // Default Cartridge chains that are always available
45+ const cartridgeChains : Chain [ ] = [
46+ { rpcUrl : "https://api.cartridge.gg/x/starknet/sepolia" } ,
47+ { rpcUrl : "https://api.cartridge.gg/x/starknet/mainnet" } ,
48+ ] ;
49+
50+ // Merge user chains with default chains
51+ // User chains take precedence if they specify the same network
52+ const chains = [ ...( options . chains || [ ] ) , ...cartridgeChains ] ;
53+ const defaultChainId =
54+ options . defaultChainId || constants . StarknetChainId . SN_MAIN ;
55+
56+ this . selectedChain = defaultChainId ;
4557 this . chains = new Map < ChainId , Chain > ( ) ;
4658
4759 this . iframes = {
@@ -54,9 +66,9 @@ export default class ControllerProvider extends BaseProvider {
5466 } ) ,
5567 } ;
5668
57- this . options = options ;
69+ this . options = { ... options , chains , defaultChainId } ;
5870
59- this . validateChains ( options . chains ) ;
71+ this . initializeChains ( chains ) ;
6072
6173 if ( typeof window !== "undefined" ) {
6274 ( window as any ) . starknet_controller = this ;
@@ -166,7 +178,15 @@ export default class ControllerProvider extends BaseProvider {
166178
167179 try {
168180 let response = await this . keychain . connect (
169- this . options . policies || { } ,
181+ // Policy precedence logic:
182+ // 1. If shouldOverridePresetPolicies is true and policies are provided, use policies
183+ // 2. Otherwise, if preset is defined, use empty object (let preset take precedence)
184+ // 3. Otherwise, use provided policies or empty object
185+ this . options . shouldOverridePresetPolicies && this . options . policies
186+ ? this . options . policies
187+ : this . options . preset
188+ ? { }
189+ : this . options . policies || { } ,
170190 this . rpcUrl ( ) ,
171191 this . options . signupOptions ,
172192 version ,
@@ -408,14 +428,28 @@ export default class ControllerProvider extends BaseProvider {
408428 return await this . keychain . delegateAccount ( ) ;
409429 }
410430
411- private async validateChains ( chains : Chain [ ] ) {
431+ private initializeChains ( chains : Chain [ ] ) {
412432 for ( const chain of chains ) {
413433 try {
414434 const url = new URL ( chain . rpcUrl ) ;
415- const chainId = await parseChainId ( url ) ;
435+ const chainId = parseChainId ( url ) ;
436+
437+ // Validate that mainnet and sepolia must use Cartridge RPC
438+ const isMainnet = chainId === constants . StarknetChainId . SN_MAIN ;
439+ const isSepolia = chainId === constants . StarknetChainId . SN_SEPOLIA ;
440+ const isCartridgeRpc = url . hostname === "api.cartridge.gg" ;
441+
442+ if ( ( isMainnet || isSepolia ) && ! isCartridgeRpc ) {
443+ throw new Error (
444+ `Only Cartridge RPC providers are allowed for ${ isMainnet ? "mainnet" : "sepolia" } . ` +
445+ `Please use: https://api.cartridge.gg/x/starknet/${ isMainnet ? "mainnet" : "sepolia" } ` ,
446+ ) ;
447+ }
448+
416449 this . chains . set ( chainId , chain ) ;
417450 } catch ( error ) {
418451 console . error ( `Failed to parse chainId for ${ chain . rpcUrl } :` , error ) ;
452+ throw error ; // Re-throw to ensure invalid chains fail fast
419453 }
420454 }
421455
0 commit comments