import { Connection , PublicKey , Transaction , TransactionInstruction , } from '@solana/web3.js' ; import BN from 'bn.js' ; import { PROGRAM_VERSION , PROGRAM_VERSION_V1 } from '../registry/constants' ; import { BN_ZERO } from '../tools/numbers' ; import { getProgramDataAccount } from '../tools/sdk/bpfUpgradeableLoader' ; import { ProgramAccount , simulateTransaction } from '../tools/sdk/runtime' ; import { parseVersion } from '../tools/version' ; import { getProgramMetadataAddress , ProgramMetadata } from './accounts' ; import { GovernanceAccountParser } from './serialisation' ; import { withUpdateProgramMetadata } from './withUpdateProgramMetadata' ; export async function getGovernanceProgramVersion ( connection , programId , env ) { const programMetadataPk = await getProgramMetadataAddress ( programId ) ; try { const programMetadataInfo = await connection . getAccountInfo ( programMetadataPk ) ; if ( programMetadataInfo ) { const programMetadata = GovernanceAccountParser ( ProgramMetadata ) ( programMetadataPk , programMetadataInfo ) as ProgramAccount < ProgramMetadata > ; let deploySlot = BN_ZERO ; try { const programData = await getProgramDataAccount ( connection , new PublicKey ( programId ) ) ; deploySlot = new BN ( programData . slot ) ; } catch { } if ( programMetadata . account . updatedAt . gte ( deploySlot ) ) { const version = parseVersion ( programMetadata . account . version ) ; console . log ( 'Program version (metadata)' , version ) ; return version . major ; } } } catch { } try { let instructions = [ ] ; let walletPk = new PublicKey ( 'ENmcpFCpxN1CqyUjuog9yyUVfdXBKF3LVCwLr7grJZpk' ) ; await withUpdateProgramMetadata ( instructions , programId , walletPk ) ; const transaction = new Transaction ( { feePayer : walletPk } ) ; transaction . add ( ... instructions ) ; const getVersion = await simulateTransaction ( connection , transaction , 'recent' ) ; if ( ! getVersion . value . err && getVersion . value . logs ) { const prefix = 'PROGRAM-VERSION:"' ; const simVersion = getVersion . value . logs . filter ( l => l . includes ( prefix ) ) . map ( l => { const versionStart = l . indexOf ( prefix ) ; return parseVersion ( l . substring ( versionStart + prefix . length , l . length - 1 ) ) ; } ) [ 0 ] ; console . log ( 'Program version (simulation)' , simVersion ) ; return simVersion . major ; } } catch ( ex ) { console . log ( "Can't determine program version" , ex ) ; } if ( env === 'localnet' ) { return PROGRAM_VERSION ; } return PROGRAM_VERSION_V1 ; }