44 Connection ,
55 Keypair ,
66 PublicKey ,
7- SendTransactionError ,
87 SystemProgram ,
98 Transaction ,
109} from "@solana/web3.js" ;
@@ -14,18 +13,21 @@ import NodeWallet from "@project-serum/anchor/dist/cjs/nodewallet";
1413import {
1514 getProposals ,
1615 MultisigParser ,
16+ PythMultisigInstruction ,
1717 WormholeMultisigInstruction ,
1818} from "xc_admin_common" ;
1919import BN from "bn.js" ;
2020import { AnchorProvider } from "@project-serum/anchor" ;
2121import {
2222 getPythClusterApiUrl ,
23+ getPythProgramKeyForCluster ,
2324 PythCluster ,
2425} from "@pythnetwork/client/lib/cluster" ;
2526import {
2627 deriveFeeCollectorKey ,
2728 getWormholeBridgeData ,
2829} from "@certusone/wormhole-sdk/lib/cjs/solana/wormhole" ;
30+ import { parseProductData } from "@pythnetwork/client" ;
2931
3032export function envOrErr ( env : string ) : string {
3133 const val = process . env [ env ] ;
@@ -35,6 +37,9 @@ export function envOrErr(env: string): string {
3537 return String ( process . env [ env ] ) ;
3638}
3739
40+ const PRODUCT_ACCOUNT_SIZE = 512 ;
41+ const PRICE_ACCOUNT_SIZE = 3312 ;
42+
3843const CLUSTER : string = envOrErr ( "CLUSTER" ) ;
3944const COMMITMENT : Commitment =
4045 ( process . env . COMMITMENT as Commitment ) ?? "confirmed" ;
@@ -65,6 +70,7 @@ async function run() {
6570 : 0 ;
6671
6772 const proposals = await getProposals ( squad , VAULT , undefined , "executeReady" ) ;
73+
6874 for ( const proposal of proposals ) {
6975 console . log ( "Trying to execute: " , proposal . publicKey . toBase58 ( ) ) ;
7076 // If we have previously cancelled because the proposal was failing, don't attempt
@@ -100,6 +106,92 @@ async function run() {
100106 fromPubkey : squad . wallet . publicKey ,
101107 } )
102108 ) ;
109+ } else if (
110+ parsedInstruction instanceof PythMultisigInstruction &&
111+ parsedInstruction . name == "addProduct"
112+ ) {
113+ /// Add product, fetch the symbol from updProduct to get the address
114+ i += 1 ;
115+ const nextInstructionPda = getIxPDA (
116+ proposal . publicKey ,
117+ new BN ( i ) ,
118+ squad . multisigProgramId
119+ ) [ 0 ] ;
120+ const nextInstruction = await squad . getInstruction (
121+ nextInstructionPda
122+ ) ;
123+ const nextParsedInstruction = multisigParser . parseInstruction ( {
124+ programId : nextInstruction . programId ,
125+ data : nextInstruction . data as Buffer ,
126+ keys : nextInstruction . keys as AccountMeta [ ] ,
127+ } ) ;
128+
129+ if (
130+ nextParsedInstruction instanceof PythMultisigInstruction &&
131+ nextParsedInstruction . name == "updProduct"
132+ ) {
133+ const productSeed = "product:" + nextParsedInstruction . args . symbol ;
134+ const productAddress = await PublicKey . createWithSeed (
135+ squad . wallet . publicKey ,
136+ productSeed ,
137+ getPythProgramKeyForCluster ( CLUSTER as PythCluster )
138+ ) ;
139+ transaction . add (
140+ SystemProgram . createAccountWithSeed ( {
141+ fromPubkey : squad . wallet . publicKey ,
142+ basePubkey : squad . wallet . publicKey ,
143+ newAccountPubkey : productAddress ,
144+ seed : productSeed ,
145+ space : PRODUCT_ACCOUNT_SIZE ,
146+ lamports :
147+ await squad . connection . getMinimumBalanceForRentExemption (
148+ PRODUCT_ACCOUNT_SIZE
149+ ) ,
150+ programId : getPythProgramKeyForCluster ( CLUSTER as PythCluster ) ,
151+ } )
152+ ) ;
153+ transaction . add (
154+ await squad . buildExecuteInstruction (
155+ proposal . publicKey ,
156+ getIxPDA (
157+ proposal . publicKey ,
158+ new BN ( i - 1 ) ,
159+ squad . multisigProgramId
160+ ) [ 0 ]
161+ )
162+ ) ;
163+ }
164+ } else if (
165+ parsedInstruction instanceof PythMultisigInstruction &&
166+ parsedInstruction . name == "addPrice"
167+ ) {
168+ /// Add price, fetch the symbol from the product account
169+ const productAccount = await squad . connection . getAccountInfo (
170+ parsedInstruction . accounts . named . productAccount . pubkey
171+ ) ;
172+ if ( productAccount ?. data ) {
173+ const priceSeed =
174+ "price:" + parseProductData ( productAccount . data ) . product . symbol ;
175+ const priceAddress = await PublicKey . createWithSeed (
176+ squad . wallet . publicKey ,
177+ priceSeed ,
178+ getPythProgramKeyForCluster ( CLUSTER as PythCluster )
179+ ) ;
180+ transaction . add (
181+ SystemProgram . createAccountWithSeed ( {
182+ fromPubkey : squad . wallet . publicKey ,
183+ basePubkey : squad . wallet . publicKey ,
184+ newAccountPubkey : priceAddress ,
185+ seed : priceSeed ,
186+ space : PRICE_ACCOUNT_SIZE ,
187+ lamports :
188+ await squad . connection . getMinimumBalanceForRentExemption (
189+ PRICE_ACCOUNT_SIZE
190+ ) ,
191+ programId : getPythProgramKeyForCluster ( CLUSTER as PythCluster ) ,
192+ } )
193+ ) ;
194+ }
103195 }
104196
105197 transaction . add (
@@ -109,20 +201,10 @@ async function run() {
109201 )
110202 ) ;
111203
112- try {
113- await new AnchorProvider ( squad . connection , squad . wallet , {
114- commitment : COMMITMENT ,
115- preflightCommitment : COMMITMENT ,
116- } ) . sendAndConfirm ( transaction , [ ] ) ;
117- } catch ( error ) {
118- // Mark the transaction as cancelled if we failed to run it
119- if ( error instanceof SendTransactionError ) {
120- console . error ( error ) ;
121- await squad . cancelTransaction ( proposal . publicKey ) ;
122- console . log ( "Cancelled: " , proposal . publicKey . toBase58 ( ) ) ;
123- }
124- break ;
125- }
204+ await new AnchorProvider ( squad . connection , squad . wallet , {
205+ commitment : COMMITMENT ,
206+ preflightCommitment : COMMITMENT ,
207+ } ) . sendAndConfirm ( transaction , [ ] , { skipPreflight : true } ) ;
126208 }
127209 } else {
128210 console . log ( "Skipping: " , proposal . publicKey . toBase58 ( ) ) ;
0 commit comments