@@ -110,15 +110,24 @@ program
110
110
options . ledger ,
111
111
new PublicKey ( options . vaultAddress )
112
112
) ;
113
- const instructions = [
114
- await setIsActiveIx (
115
- vaultAuthority ,
116
- vaultAuthority ,
117
- attesterProgramId ,
118
- options . active
119
- ) ,
113
+ const squadIxs : SquadInstruction [ ] = [
114
+ {
115
+ instruction : await setIsActiveIx (
116
+ vaultAuthority ,
117
+ vaultAuthority ,
118
+ attesterProgramId ,
119
+ options . active
120
+ ) ,
121
+ } ,
120
122
] ;
121
- await addInstructionsToTx ( squad , options . ledger , txKey , instructions ) ;
123
+ await addInstructionsToTx (
124
+ options . cluster ,
125
+ squad ,
126
+ options . ledger ,
127
+ msAccount . publicKey ,
128
+ txKey ,
129
+ squadIxs
130
+ ) ;
122
131
} ) ;
123
132
124
133
program
@@ -140,11 +149,6 @@ program
140
149
"multisig wallet secret key filepath" ,
141
150
"keys/key.json"
142
151
)
143
- . option (
144
- "-m, --message <filepath>" ,
145
- "multisig message account secret key filepath" ,
146
- "keys/message.json"
147
- )
148
152
. requiredOption ( "-t, --tx-pda <address>" , "transaction PDA" )
149
153
. requiredOption ( "-u, --rpc-url <url>" , "wormhole RPC URL" )
150
154
. action ( ( options ) => {
@@ -155,7 +159,6 @@ program
155
159
options . ledgerDerivationAccount ,
156
160
options . ledgerDerivationChange ,
157
161
options . wallet ,
158
- options . message ,
159
162
new PublicKey ( options . txPda ) ,
160
163
options . rpcUrl
161
164
) ;
@@ -166,14 +169,14 @@ program
166
169
program . parse ( ) ;
167
170
168
171
// custom solana cluster type
169
- type Cluster = "devnet" | "mainnet-beta " ;
172
+ type Cluster = "devnet" | "mainnet" ;
170
173
type WormholeNetwork = "TESTNET" | "MAINNET" ;
171
174
172
175
// solana cluster mapping to wormhole cluster
173
176
const solanaClusterMappingToWormholeNetwork : Record < Cluster , WormholeNetwork > =
174
177
{
175
178
devnet : "TESTNET" ,
176
- " mainnet-beta" : "MAINNET" ,
179
+ mainnet : "MAINNET" ,
177
180
} ;
178
181
179
182
async function getSquadsClient (
@@ -224,28 +227,53 @@ async function createTx(
224
227
return newTx . publicKey ;
225
228
}
226
229
230
+ type SquadInstruction = {
231
+ instruction : anchor . web3 . TransactionInstruction ;
232
+ authorityIndex ?: number ;
233
+ authorityBump ?: number ;
234
+ authorityType ?: string ;
235
+ } ;
236
+
227
237
/** Adds the given instructions to the squads transaction at `txKey` and activates the transaction (makes it ready for signing). */
228
238
async function addInstructionsToTx (
239
+ cluster : Cluster ,
229
240
squad : Squads ,
230
241
ledger : boolean ,
242
+ vault : PublicKey ,
231
243
txKey : PublicKey ,
232
- instructions : TransactionInstruction [ ]
244
+ instructions : SquadInstruction [ ]
233
245
) {
234
246
for ( let i = 0 ; i < instructions . length ; i ++ ) {
235
247
console . log (
236
- `Adding instruction ${ i } /${ instructions . length } to transaction...`
248
+ `Adding instruction ${ i + 1 } /${ instructions . length } to transaction...`
237
249
) ;
238
250
if ( ledger ) {
239
251
console . log ( "Please approve the transaction on your ledger device..." ) ;
240
252
}
241
- await squad . addInstruction ( txKey , instructions [ i ] ) ;
253
+ await squad . addInstruction (
254
+ txKey ,
255
+ instructions [ i ] . instruction ,
256
+ instructions [ i ] . authorityIndex ,
257
+ instructions [ i ] . authorityBump ,
258
+ instructions [ i ] . authorityType
259
+ ) ;
242
260
}
243
261
244
262
console . log ( "Activating transaction..." ) ;
245
263
if ( ledger )
246
264
console . log ( "Please approve the transaction on your ledger device..." ) ;
247
265
await squad . activateTransaction ( txKey ) ;
248
266
console . log ( "Transaction created." ) ;
267
+ console . log ( "Approving transaction..." ) ;
268
+ if ( ledger )
269
+ console . log ( "Please approve the transaction on your ledger device..." ) ;
270
+ await squad . approveTransaction ( txKey ) ;
271
+ console . log ( "Transaction approved." ) ;
272
+ console . log (
273
+ `Tx URL: https://mesh${
274
+ cluster === "devnet" ? "-devnet" : ""
275
+ } .squads.so/transactions/${ vault . toBase58 ( ) } /tx/${ txKey . toBase58 ( ) } `
276
+ ) ;
249
277
}
250
278
251
279
async function setIsActiveIx (
@@ -277,7 +305,7 @@ async function setIsActiveIx(
277
305
278
306
const isActiveInt = isActive === true ? 1 : 0 ;
279
307
// first byte is the isActive instruction, second byte is true/false
280
- const data = new Buffer ( [ 4 , isActiveInt ] ) ;
308
+ const data = Buffer . from ( [ 4 , isActiveInt ] ) ;
281
309
282
310
return {
283
311
keys : [ config , opsOwner , payer ] ,
@@ -329,6 +357,22 @@ async function getWormholeMessageIx(
329
357
] ;
330
358
}
331
359
360
+ const getIxAuthority = async (
361
+ txPda : anchor . web3 . PublicKey ,
362
+ index : anchor . BN ,
363
+ programId : anchor . web3 . PublicKey
364
+ ) => {
365
+ return anchor . web3 . PublicKey . findProgramAddress (
366
+ [
367
+ anchor . utils . bytes . utf8 . encode ( "squad" ) ,
368
+ txPda . toBuffer ( ) ,
369
+ index . toArrayLike ( Buffer , "le" , 4 ) ,
370
+ anchor . utils . bytes . utf8 . encode ( "ix_authority" ) ,
371
+ ] ,
372
+ programId
373
+ ) ;
374
+ } ;
375
+
332
376
async function createWormholeMsgMultisigTx (
333
377
cluster : Cluster ,
334
378
squad : Squads ,
@@ -337,7 +381,6 @@ async function createWormholeMsgMultisigTx(
337
381
payload : string
338
382
) {
339
383
const msAccount = await squad . getMultisig ( vault ) ;
340
-
341
384
const emitter = squad . getAuthorityPDA (
342
385
msAccount . publicKey ,
343
386
msAccount . authorityIndex
@@ -346,28 +389,41 @@ async function createWormholeMsgMultisigTx(
346
389
347
390
const txKey = await createTx ( squad , ledger , vault ) ;
348
391
349
- const message = Keypair . generate ( ) ;
350
-
351
- fs . mkdirSync ( "keys" , { recursive : true } ) ;
352
- // save message to Uint8 array keypair file called mesage.json
353
- fs . writeFileSync (
354
- `keys/message-${ txKey . toBase58 ( ) } .json` ,
355
- `[${ message . secretKey . toString ( ) } ]`
392
+ const [ messagePDA , messagePdaBump ] = await getIxAuthority (
393
+ txKey ,
394
+ new anchor . BN ( 1 ) ,
395
+ squad . multisigProgramId
356
396
) ;
357
- console . log ( `Message Address: ${ message . publicKey . toBase58 ( ) } ` ) ;
358
397
359
398
console . log ( "Creating wormhole instructions..." ) ;
360
399
const wormholeIxs = await getWormholeMessageIx (
361
400
cluster ,
362
401
emitter ,
363
402
emitter ,
364
- message . publicKey ,
403
+ messagePDA ,
365
404
squad . connection ,
366
405
payload
367
406
) ;
368
407
console . log ( "Wormhole instructions created." ) ;
369
408
370
- await addInstructionsToTx ( squad , ledger , txKey , wormholeIxs ) ;
409
+ const squadIxs : SquadInstruction [ ] = [
410
+ { instruction : wormholeIxs [ 0 ] } ,
411
+ {
412
+ instruction : wormholeIxs [ 1 ] ,
413
+ authorityIndex : 1 ,
414
+ authorityBump : messagePdaBump ,
415
+ authorityType : "custom" ,
416
+ } ,
417
+ ] ;
418
+
419
+ await addInstructionsToTx (
420
+ cluster ,
421
+ squad ,
422
+ ledger ,
423
+ msAccount . publicKey ,
424
+ txKey ,
425
+ squadIxs
426
+ ) ;
371
427
}
372
428
373
429
async function executeMultisigTx (
@@ -377,7 +433,6 @@ async function executeMultisigTx(
377
433
ledgerDerivationAccount : number | undefined ,
378
434
ledgerDerivationChange : number | undefined ,
379
435
walletPath : string ,
380
- messagePath : string ,
381
436
txPDA : PublicKey ,
382
437
rpcUrl : string
383
438
) {
@@ -398,13 +453,6 @@ async function executeMultisigTx(
398
453
console . log ( `Loaded wallet with address: ${ wallet . publicKey . toBase58 ( ) } ` ) ;
399
454
}
400
455
401
- const message = Keypair . fromSecretKey (
402
- Uint8Array . from ( JSON . parse ( fs . readFileSync ( messagePath , "ascii" ) ) )
403
- ) ;
404
- console . log (
405
- `Loaded message account with address: ${ message . publicKey . toBase58 ( ) } `
406
- ) ;
407
-
408
456
const squad =
409
457
cluster === "devnet" ? Squads . devnet ( wallet ) : Squads . mainnet ( wallet ) ;
410
458
const msAccount = await squad . getMultisig ( vault ) ;
@@ -418,11 +466,6 @@ async function executeMultisigTx(
418
466
txPDA ,
419
467
wallet . publicKey
420
468
) ;
421
- executeIx . keys . forEach ( ( key ) => {
422
- if ( key . pubkey . equals ( message . publicKey ) ) {
423
- key . isSigner = true ;
424
- }
425
- } ) ;
426
469
427
470
// airdrop 0.1 SOL to emitter if on devnet
428
471
if ( cluster === "devnet" ) {
@@ -457,7 +500,7 @@ async function executeMultisigTx(
457
500
console . log ( "Sending transaction..." ) ;
458
501
if ( ledger )
459
502
console . log ( "Please approve the transaction on your ledger device..." ) ;
460
- const signature = await provider . sendAndConfirm ( executeTx , [ message ] ) ;
503
+ const signature = await provider . sendAndConfirm ( executeTx ) ;
461
504
462
505
console . log (
463
506
`Executed tx: https://explorer.solana.com/tx/${ signature } ${
@@ -497,8 +540,8 @@ async function executeMultisigTx(
497
540
) ;
498
541
const { vaaBytes } = await response . json ( ) ;
499
542
console . log ( `VAA (Base64): ${ vaaBytes } ` ) ;
500
- const parsedVaa = await parse ( vaaBytes ) ;
501
543
console . log ( `VAA (Hex): ${ Buffer . from ( vaaBytes ) . toString ( "hex" ) } ` ) ;
544
+ const parsedVaa = await parse ( vaaBytes ) ;
502
545
console . log ( `Emitter chain: ${ parsedVaa . emitter_chain } ` ) ;
503
546
console . log ( `Nonce: ${ parsedVaa . nonce } ` ) ;
504
547
console . log ( `Payload: ${ Buffer . from ( parsedVaa . payload ) . toString ( "hex" ) } ` ) ;
0 commit comments