@@ -230,6 +230,122 @@ describe('Transaction', () => {
230
230
expect ( message . header . numReadonlySignedAccounts ) . to . eq ( 0 ) ;
231
231
expect ( message . header . numReadonlyUnsignedAccounts ) . to . eq ( 1 ) ;
232
232
} ) ;
233
+
234
+ it ( 'uses the nonce as the recent blockhash when compiling nonce-based transactions' , ( ) => {
235
+ const nonce = new PublicKey ( 1 ) ;
236
+ const nonceAuthority = new PublicKey ( 2 ) ;
237
+ const nonceInfo = {
238
+ nonce : nonce . toBase58 ( ) ,
239
+ nonceInstruction : SystemProgram . nonceAdvance ( {
240
+ noncePubkey : nonce ,
241
+ authorizedPubkey : nonceAuthority ,
242
+ } ) ,
243
+ } ;
244
+ const transaction = new Transaction ( {
245
+ feePayer : nonceAuthority ,
246
+ nonceInfo,
247
+ } ) ;
248
+ const message = transaction . compileMessage ( ) ;
249
+ expect ( message . recentBlockhash ) . to . equal ( nonce . toBase58 ( ) ) ;
250
+ } ) ;
251
+
252
+ it ( 'prepends the nonce advance instruction when compiling nonce-based transactions' , ( ) => {
253
+ const nonce = new PublicKey ( 1 ) ;
254
+ const nonceAuthority = new PublicKey ( 2 ) ;
255
+ const nonceInfo = {
256
+ nonce : nonce . toBase58 ( ) ,
257
+ nonceInstruction : SystemProgram . nonceAdvance ( {
258
+ noncePubkey : nonce ,
259
+ authorizedPubkey : nonceAuthority ,
260
+ } ) ,
261
+ } ;
262
+ const transaction = new Transaction ( {
263
+ feePayer : nonceAuthority ,
264
+ nonceInfo,
265
+ } ) . add (
266
+ SystemProgram . transfer ( {
267
+ fromPubkey : nonceAuthority ,
268
+ lamports : 1 ,
269
+ toPubkey : new PublicKey ( 3 ) ,
270
+ } ) ,
271
+ ) ;
272
+ const message = transaction . compileMessage ( ) ;
273
+ expect ( message . instructions ) . to . have . length ( 2 ) ;
274
+ const expectedNonceAdvanceCompiledInstruction = {
275
+ accounts : [ 1 , 4 , 0 ] ,
276
+ data : ( ( ) => {
277
+ const expectedData = Buffer . alloc ( 4 ) ;
278
+ expectedData . writeInt32LE (
279
+ 4 /* SystemInstruction::AdvanceNonceAccount */ ,
280
+ 0 ,
281
+ ) ;
282
+ return bs58 . encode ( expectedData ) ;
283
+ } ) ( ) ,
284
+ programIdIndex : ( ( ) => {
285
+ let foundIndex = - 1 ;
286
+ message . accountKeys . find ( ( publicKey , ii ) => {
287
+ if ( publicKey . equals ( SystemProgram . programId ) ) {
288
+ foundIndex = ii ;
289
+ return true ;
290
+ }
291
+ } ) ;
292
+ return foundIndex ;
293
+ } ) ( ) ,
294
+ } ;
295
+ expect ( message . instructions [ 0 ] ) . to . deep . equal (
296
+ expectedNonceAdvanceCompiledInstruction ,
297
+ ) ;
298
+ } ) ;
299
+
300
+ it ( 'does not prepend the nonce advance instruction when compiling nonce-based transactions if it is already there' , ( ) => {
301
+ const nonce = new PublicKey ( 1 ) ;
302
+ const nonceAuthority = new PublicKey ( 2 ) ;
303
+ const nonceInfo = {
304
+ nonce : nonce . toBase58 ( ) ,
305
+ nonceInstruction : SystemProgram . nonceAdvance ( {
306
+ noncePubkey : nonce ,
307
+ authorizedPubkey : nonceAuthority ,
308
+ } ) ,
309
+ } ;
310
+ const transaction = new Transaction ( {
311
+ feePayer : nonceAuthority ,
312
+ nonceInfo,
313
+ } )
314
+ . add ( nonceInfo . nonceInstruction )
315
+ . add (
316
+ SystemProgram . transfer ( {
317
+ fromPubkey : nonceAuthority ,
318
+ lamports : 1 ,
319
+ toPubkey : new PublicKey ( 3 ) ,
320
+ } ) ,
321
+ ) ;
322
+ const message = transaction . compileMessage ( ) ;
323
+ expect ( message . instructions ) . to . have . length ( 2 ) ;
324
+ const expectedNonceAdvanceCompiledInstruction = {
325
+ accounts : [ 1 , 4 , 0 ] ,
326
+ data : ( ( ) => {
327
+ const expectedData = Buffer . alloc ( 4 ) ;
328
+ expectedData . writeInt32LE (
329
+ 4 /* SystemInstruction::AdvanceNonceAccount */ ,
330
+ 0 ,
331
+ ) ;
332
+ return bs58 . encode ( expectedData ) ;
333
+ } ) ( ) ,
334
+ programIdIndex : ( ( ) => {
335
+ let foundIndex = - 1 ;
336
+ message . accountKeys . find ( ( publicKey , ii ) => {
337
+ if ( publicKey . equals ( SystemProgram . programId ) ) {
338
+ foundIndex = ii ;
339
+ return true ;
340
+ }
341
+ } ) ;
342
+ return foundIndex ;
343
+ } ) ( ) ,
344
+ } ;
345
+ expect ( message . instructions [ 0 ] ) . to . deep . equal (
346
+ expectedNonceAdvanceCompiledInstruction ,
347
+ ) ;
348
+ } ) ;
233
349
} ) ;
234
350
235
351
if ( process . env . TEST_LIVE ) {
@@ -455,15 +571,8 @@ describe('Transaction', () => {
455
571
) ;
456
572
transferTransaction . sign ( account1 ) ;
457
573
458
- let expectedData = Buffer . alloc ( 4 ) ;
459
- expectedData . writeInt32LE ( 4 , 0 ) ;
460
-
461
- expect ( transferTransaction . instructions ) . to . have . length ( 2 ) ;
462
- expect ( transferTransaction . instructions [ 0 ] . programId ) . to . eql (
463
- SystemProgram . programId ,
464
- ) ;
465
- expect ( transferTransaction . instructions [ 0 ] . data ) . to . eql ( expectedData ) ;
466
- expect ( transferTransaction . recentBlockhash ) . to . eq ( nonce ) ;
574
+ expect ( transferTransaction . instructions ) . to . have . length ( 1 ) ;
575
+ expect ( transferTransaction . recentBlockhash ) . to . be . undefined ;
467
576
468
577
const stakeAccount = Keypair . generate ( ) ;
469
578
const voteAccount = Keypair . generate ( ) ;
@@ -476,12 +585,8 @@ describe('Transaction', () => {
476
585
) ;
477
586
stakeTransaction . sign ( account1 ) ;
478
587
479
- expect ( stakeTransaction . instructions ) . to . have . length ( 2 ) ;
480
- expect ( stakeTransaction . instructions [ 0 ] . programId ) . to . eql (
481
- SystemProgram . programId ,
482
- ) ;
483
- expect ( stakeTransaction . instructions [ 0 ] . data ) . to . eql ( expectedData ) ;
484
- expect ( stakeTransaction . recentBlockhash ) . to . eq ( nonce ) ;
588
+ expect ( stakeTransaction . instructions ) . to . have . length ( 1 ) ;
589
+ expect ( stakeTransaction . recentBlockhash ) . to . be . undefined ;
485
590
} ) ;
486
591
487
592
it ( 'parse wire format and serialize' , ( ) => {
@@ -596,6 +701,22 @@ describe('Transaction', () => {
596
701
expect ( compiledMessage3 ) . not . to . eql ( message ) ;
597
702
} ) ;
598
703
704
+ it ( 'constructs a transaction with nonce info' , ( ) => {
705
+ const nonce = new PublicKey ( 1 ) ;
706
+ const nonceAuthority = new PublicKey ( 2 ) ;
707
+ const nonceInfo = {
708
+ nonce : nonce . toBase58 ( ) ,
709
+ nonceInstruction : SystemProgram . nonceAdvance ( {
710
+ noncePubkey : nonce ,
711
+ authorizedPubkey : nonceAuthority ,
712
+ } ) ,
713
+ } ;
714
+ const transaction = new Transaction ( { nonceInfo} ) ;
715
+ expect ( transaction . recentBlockhash ) . to . be . undefined ;
716
+ expect ( transaction . lastValidBlockHeight ) . to . be . undefined ;
717
+ expect ( transaction . nonceInfo ) . to . equal ( nonceInfo ) ;
718
+ } ) ;
719
+
599
720
it ( 'constructs a transaction with last valid block height' , ( ) => {
600
721
const blockhash = 'EETubP5AKHgjPAhzPAFcb8BAY1hMH639CWCFTqi3hq1k' ;
601
722
const lastValidBlockHeight = 1234 ;
0 commit comments