@@ -47,6 +47,7 @@ function setNestedValue(obj: any, path: string[], value: any): void {
4747 } , obj ) ;
4848 target [ lastKey ] = value ;
4949}
50+
5051import { NTT , SolanaNtt } from "@wormhole-foundation/sdk-solana-ntt" ;
5152import type { EvmNtt , EvmNttWormholeTranceiver } from "@wormhole-foundation/sdk-evm-ntt" ;
5253import type { EvmChains , EvmNativeSigner , EvmUnsignedTransaction } from "@wormhole-foundation/sdk-evm" ;
@@ -1814,6 +1815,8 @@ async function deploySolana<N extends Network, C extends SolanaChains>(
18141815) : Promise < ChainAddress < C > > {
18151816 ensureNttRoot ( pwd ) ;
18161817
1818+ checkSolanaVersion ( pwd ) ;
1819+
18171820 // TODO: if the binary is provided, we should not check addresses in the source tree. (so we should move around the control flow a bit)
18181821 // TODO: factor out some of this into separate functions to help readability of this function (maybe even move to a different file)
18191822
@@ -1961,7 +1964,7 @@ async function deploySolana<N extends Network, C extends SolanaChains>(
19611964 } else {
19621965 // build the program
19631966 // TODO: build with docker
1964- checkAnchorVersion ( ) ;
1967+ checkAnchorVersion ( pwd ) ;
19651968 const proc = Bun . spawn (
19661969 [ "anchor" ,
19671970 "build" ,
@@ -2588,22 +2591,120 @@ export function ensureNttRoot(pwd: string = ".") {
25882591 }
25892592}
25902593
2591- function checkAnchorVersion ( ) {
2592- const expected = "0.29.0" ;
2594+ // Check Solana toolchain version against Anchor.toml requirements
2595+ function checkSolanaVersion ( pwd : string ) : void {
25932596 try {
2594- execSync ( "which anchor" ) ;
2595- } catch {
2596- console . error ( "Anchor CLI is not installed.\nSee https://www.anchor-lang.com/docs/installation" )
2597- process . exit ( 1 ) ;
2597+ // Read required version from Anchor.toml
2598+ const anchorToml = fs . readFileSync ( `${ pwd } /solana/Anchor.toml` , 'utf8' ) ;
2599+ const versionMatch = anchorToml . match ( / s o l a n a _ v e r s i o n = " ( .+ ) " / ) ;
2600+
2601+ if ( ! versionMatch ) {
2602+ console . warn ( chalk . yellow ( "Warning: Could not find solana_version in Anchor.toml" ) ) ;
2603+ return ;
2604+ }
2605+
2606+ const requiredVersion = versionMatch [ 1 ] ;
2607+
2608+ // Get current Solana version and detect client type
2609+ let currentVersion : string ;
2610+ let clientType : 'agave' | 'solanalabs' ;
2611+ try {
2612+ const output = execSync ( 'solana --version' , { encoding : 'utf8' , stdio : 'pipe' } ) ;
2613+ const versionMatch = output . match ( / s o l a n a - c l i ( \d + \. \d + \. \d + ) / ) ;
2614+ if ( ! versionMatch ) {
2615+ console . error ( chalk . red ( "Error: Could not parse solana CLI version" ) ) ;
2616+ process . exit ( 1 ) ;
2617+ }
2618+ currentVersion = versionMatch [ 1 ] ;
2619+
2620+ // Detect client type
2621+ if ( output . includes ( 'Agave' ) ) {
2622+ clientType = 'agave' ;
2623+ } else if ( output . includes ( 'SolanaLabs' ) ) {
2624+ clientType = 'solanalabs' ;
2625+ } else {
2626+ // Default to agave if we can't detect
2627+ clientType = 'agave' ;
2628+ }
2629+ } catch ( error ) {
2630+ console . error ( chalk . red ( "Error: solana CLI not found. Please install the Solana toolchain." ) ) ;
2631+ console . error ( chalk . yellow ( "Install with: sh -c \"$(curl -sSfL https://release.anza.xyz/stable/install)\"" ) ) ;
2632+ process . exit ( 1 ) ;
2633+ }
2634+
2635+ if ( currentVersion !== requiredVersion ) {
2636+ console . log ( chalk . yellow ( `Solana version mismatch detected:` ) ) ;
2637+ console . log ( chalk . yellow ( ` Required: ${ requiredVersion } (from Anchor.toml)` ) ) ;
2638+ console . log ( chalk . yellow ( ` Current: ${ currentVersion } ` ) ) ;
2639+ console . log ( chalk . yellow ( `\nSwitching to required version...` ) ) ;
2640+
2641+ // Run the appropriate version switch command
2642+ const installCommand = clientType === 'agave'
2643+ ? `agave-install init ${ requiredVersion } `
2644+ : `solana-install init ${ requiredVersion } ` ;
2645+
2646+ try {
2647+ execSync ( installCommand , { stdio : 'inherit' } ) ;
2648+ console . log ( chalk . green ( `Successfully switched to Solana version ${ requiredVersion } ` ) ) ;
2649+ } catch ( error ) {
2650+ console . error ( chalk . red ( `Failed to switch Solana version using ${ installCommand } ` ) ) ;
2651+ console . error ( chalk . red ( `Please run manually: ${ installCommand } ` ) ) ;
2652+ process . exit ( 1 ) ;
2653+ }
2654+ }
2655+ } catch ( error ) {
2656+ if ( error instanceof Error && 'code' in error && error . code === 'ENOENT' ) {
2657+ console . warn ( chalk . yellow ( "Warning: Could not read Anchor.toml file" ) ) ;
2658+ } else {
2659+ console . warn ( chalk . yellow ( `Warning: Failed to check Solana version: ${ error instanceof Error ? error . message : error } ` ) ) ;
2660+ }
25982661 }
2599- const version = execSync ( "anchor --version" ) . toString ( ) . trim ( ) ;
2600- // version looks like "anchor-cli 0.14.0"
2601- const [ _ , v ] = version . split ( " " ) ;
2602- if ( v !== expected ) {
2603- console . error ( `Anchor CLI version must be ${ expected } but is ${ v } ` ) ;
2604- process . exit ( 1 ) ;
2662+ }
2663+
2664+ function checkAnchorVersion ( pwd : string ) {
2665+ try {
2666+ // Read required version from Anchor.toml
2667+ const anchorToml = fs . readFileSync ( `${ pwd } /solana/Anchor.toml` , 'utf8' ) ;
2668+ const versionMatch = anchorToml . match ( / a n c h o r _ v e r s i o n = " ( .+ ) " / ) ;
2669+
2670+ if ( ! versionMatch ) {
2671+ console . error ( chalk . red ( "Error: Could not find anchor_version in Anchor.toml" ) ) ;
2672+ process . exit ( 1 ) ;
2673+ }
2674+
2675+ const expected = versionMatch [ 1 ] ;
2676+
2677+ // Check if Anchor CLI is installed
2678+ try {
2679+ execSync ( "which anchor" ) ;
2680+ } catch {
2681+ console . error ( "Anchor CLI is not installed.\nSee https://www.anchor-lang.com/docs/installation" )
2682+ process . exit ( 1 ) ;
2683+ }
2684+
2685+ // Get current Anchor version
2686+ const version = execSync ( "anchor --version" ) . toString ( ) . trim ( ) ;
2687+ // version looks like "anchor-cli 0.14.0"
2688+ const [ _ , v ] = version . split ( " " ) ;
2689+ if ( v !== expected ) {
2690+ console . error ( chalk . red ( `Anchor CLI version mismatch!` ) ) ;
2691+ console . error ( chalk . red ( ` Required: ${ expected } (from Anchor.toml)` ) ) ;
2692+ console . error ( chalk . red ( ` Current: ${ v } ` ) ) ;
2693+ console . error ( chalk . yellow ( `\nTo fix this, install the correct version of Anchor` ) ) ;
2694+ console . error ( chalk . gray ( "See https://www.anchor-lang.com/docs/installation" ) ) ;
2695+ process . exit ( 1 ) ;
2696+ }
2697+ } catch ( error ) {
2698+ if ( error instanceof Error && 'code' in error && error . code === 'ENOENT' ) {
2699+ console . error ( chalk . red ( "Error: Could not read Anchor.toml file" ) ) ;
2700+ console . error ( chalk . yellow ( `Expected file at: ${ pwd } /solana/Anchor.toml` ) ) ;
2701+ process . exit ( 1 ) ;
2702+ } else {
2703+ throw error ;
2704+ }
26052705 }
26062706}
2707+
26072708function loadConfig ( path : string ) : Config {
26082709 if ( ! fs . existsSync ( path ) ) {
26092710 console . error ( `File not found: ${ path } ` ) ;
0 commit comments