@@ -36,6 +36,7 @@ import {
36
36
import { associatedAddress } from '@coral-xyz/anchor/dist/cjs/utils/token' ;
37
37
import { NttQuoter } from './nttQuoter' ;
38
38
import { getTokenById } from 'utils' ;
39
+ import { Keccak } from 'sha3' ;
39
40
40
41
// TODO: make sure this is in sync with the contract
41
42
const RATE_LIMIT_DURATION = 24 * 60 * 60 ;
@@ -47,6 +48,13 @@ type OutboxRateLimit =
47
48
type InboxRateLimit =
48
49
IdlAccounts < ExampleNativeTokenTransfers > [ 'inboxRateLimit' ] ;
49
50
51
+ interface TransferArgs {
52
+ amount : BN ;
53
+ recipientChain : { id : ChainId } ;
54
+ recipientAddress : number [ ] ;
55
+ shouldQueue : boolean ;
56
+ }
57
+
50
58
export class NttManagerSolana {
51
59
readonly connection : Connection ;
52
60
readonly program : Program < ExampleNativeTokenTransfers > ;
@@ -100,9 +108,15 @@ export class NttManagerSolana {
100
108
outboxItem : outboxItem . publicKey ,
101
109
revertOnDelay : ! txArgs . shouldQueue ,
102
110
} ) ;
111
+ const transferArgs : TransferArgs = {
112
+ amount : txArgs . amount ,
113
+ recipientChain : { id : wh . toChainId ( txArgs . recipientChain ) } ,
114
+ recipientAddress : Array . from ( txArgs . recipientAddress ) ,
115
+ shouldQueue : txArgs . shouldQueue ,
116
+ } ;
103
117
const approveIx = createApproveInstruction (
104
118
tokenAccount ,
105
- this . tokenAuthorityAddress ( ) ,
119
+ this . sessionAuthorityAddress ( txArgs . fromAuthority , transferArgs ) ,
106
120
payer ,
107
121
BigInt ( amount . toString ( ) ) ,
108
122
) ;
@@ -349,7 +363,7 @@ export class NttManagerSolana {
349
363
350
364
// Account addresses
351
365
352
- derive_pda ( seeds : Buffer | Array < Uint8Array | Buffer > ) : PublicKey {
366
+ derivePda ( seeds : Buffer | Array < Uint8Array | Buffer > ) : PublicKey {
353
367
const seedsArray = seeds instanceof Buffer ? [ seeds ] : seeds ;
354
368
const [ address ] = PublicKey . findProgramAddressSync (
355
369
seedsArray ,
@@ -359,51 +373,68 @@ export class NttManagerSolana {
359
373
}
360
374
361
375
configAccountAddress ( ) : PublicKey {
362
- return this . derive_pda ( Buffer . from ( 'config' ) ) ;
376
+ return this . derivePda ( Buffer . from ( 'config' ) ) ;
363
377
}
364
378
365
379
outboxRateLimitAccountAddress ( ) : PublicKey {
366
- return this . derive_pda ( Buffer . from ( 'outbox_rate_limit' ) ) ;
380
+ return this . derivePda ( Buffer . from ( 'outbox_rate_limit' ) ) ;
367
381
}
368
382
369
383
inboxRateLimitAccountAddress ( chain : ChainName | ChainId ) : PublicKey {
370
384
const chainId = wh . toChainId ( chain ) ;
371
- return this . derive_pda ( [
385
+ return this . derivePda ( [
372
386
Buffer . from ( 'inbox_rate_limit' ) ,
373
387
new BN ( chainId ) . toBuffer ( 'be' , 2 ) ,
374
388
] ) ;
375
389
}
376
390
377
391
inboxItemAccountAddress ( messageDigest : string ) : PublicKey {
378
- return this . derive_pda ( [
392
+ return this . derivePda ( [
379
393
Buffer . from ( 'inbox_item' ) ,
380
394
Buffer . from ( messageDigest . slice ( 2 ) , 'hex' ) ,
381
395
] ) ;
382
396
}
383
397
398
+ sessionAuthorityAddress ( sender : PublicKey , args : TransferArgs ) : PublicKey {
399
+ const { amount, recipientChain, recipientAddress, shouldQueue } = args ;
400
+ const serialized = Buffer . concat ( [
401
+ amount . toArrayLike ( Buffer , 'be' , 8 ) ,
402
+ Buffer . from ( new BN ( recipientChain . id ) . toArrayLike ( Buffer , 'be' , 2 ) ) ,
403
+ Buffer . from ( new Uint8Array ( recipientAddress ) ) ,
404
+ Buffer . from ( [ shouldQueue ? 1 : 0 ] ) ,
405
+ ] ) ;
406
+ const hasher = new Keccak ( 256 ) ;
407
+ hasher . update ( serialized ) ;
408
+ return this . derivePda ( [
409
+ Buffer . from ( 'session_authority' ) ,
410
+ sender . toBytes ( ) ,
411
+ hasher . digest ( ) ,
412
+ ] ) ;
413
+ }
414
+
384
415
tokenAuthorityAddress ( ) : PublicKey {
385
- return this . derive_pda ( [ Buffer . from ( 'token_authority' ) ] ) ;
416
+ return this . derivePda ( [ Buffer . from ( 'token_authority' ) ] ) ;
386
417
}
387
418
388
419
emitterAccountAddress ( ) : PublicKey {
389
- return this . derive_pda ( [ Buffer . from ( 'emitter' ) ] ) ;
420
+ return this . derivePda ( [ Buffer . from ( 'emitter' ) ] ) ;
390
421
}
391
422
392
423
wormholeMessageAccountAddress ( outboxItem : PublicKey ) : PublicKey {
393
- return this . derive_pda ( [ Buffer . from ( 'message' ) , outboxItem . toBuffer ( ) ] ) ;
424
+ return this . derivePda ( [ Buffer . from ( 'message' ) , outboxItem . toBuffer ( ) ] ) ;
394
425
}
395
426
396
427
peerAccountAddress ( chain : ChainName | ChainId ) : PublicKey {
397
428
const chainId = wh . toChainId ( chain ) ;
398
- return this . derive_pda ( [
429
+ return this . derivePda ( [
399
430
Buffer . from ( 'peer' ) ,
400
431
new BN ( chainId ) . toBuffer ( 'be' , 2 ) ,
401
432
] ) ;
402
433
}
403
434
404
435
transceiverPeerAccountAddress ( chain : ChainName | ChainId ) : PublicKey {
405
436
const chainId = wh . toChainId ( chain ) ;
406
- return this . derive_pda ( [
437
+ return this . derivePda ( [
407
438
Buffer . from ( 'transceiver_peer' ) ,
408
439
new BN ( chainId ) . toBuffer ( 'be' , 2 ) ,
409
440
] ) ;
@@ -417,15 +448,15 @@ export class NttManagerSolana {
417
448
if ( id . length !== 32 ) {
418
449
throw new Error ( 'id must be 32 bytes' ) ;
419
450
}
420
- return this . derive_pda ( [
451
+ return this . derivePda ( [
421
452
Buffer . from ( 'transceiver_message' ) ,
422
453
new BN ( chainId ) . toBuffer ( 'be' , 2 ) ,
423
454
id ,
424
455
] ) ;
425
456
}
426
457
427
458
registeredTransceiverAddress ( transceiver : PublicKey ) : PublicKey {
428
- return this . derive_pda ( [
459
+ return this . derivePda ( [
429
460
Buffer . from ( 'registered_transceiver' ) ,
430
461
transceiver . toBuffer ( ) ,
431
462
] ) ;
@@ -451,6 +482,12 @@ export class NttManagerSolana {
451
482
const config = await this . getConfig ( args . config ) ;
452
483
const chainId = wh . toChainId ( args . recipientChain ) ;
453
484
const mint = await this . mintAccountAddress ( config ) ;
485
+ const transferArgs : TransferArgs = {
486
+ amount : args . amount ,
487
+ recipientChain : { id : chainId } ,
488
+ recipientAddress : Array . from ( args . recipientAddress ) ,
489
+ shouldQueue : args . shouldQueue ,
490
+ } ;
454
491
return await this . program . methods
455
492
. transferBurn ( {
456
493
amount : args . amount ,
@@ -464,13 +501,15 @@ export class NttManagerSolana {
464
501
config : { config : this . configAccountAddress ( ) } ,
465
502
mint,
466
503
from : args . from ,
467
- sender : args . fromAuthority ,
468
504
outboxItem : args . outboxItem ,
469
505
outboxRateLimit : this . outboxRateLimitAccountAddress ( ) ,
470
- tokenAuthority : this . tokenAuthorityAddress ( ) ,
471
506
} ,
472
507
peer : this . peerAccountAddress ( args . recipientChain ) ,
473
508
inboxRateLimit : this . inboxRateLimitAccountAddress ( args . recipientChain ) ,
509
+ sessionAuthority : this . sessionAuthorityAddress (
510
+ args . fromAuthority ,
511
+ transferArgs ,
512
+ ) ,
474
513
} )
475
514
. instruction ( ) ;
476
515
}
@@ -493,6 +532,12 @@ export class NttManagerSolana {
493
532
const config = await this . getConfig ( args . config ) ;
494
533
const chainId = wh . toChainId ( args . recipientChain ) ;
495
534
const mint = await this . mintAccountAddress ( config ) ;
535
+ const transferArgs : TransferArgs = {
536
+ amount : args . amount ,
537
+ recipientChain : { id : chainId } ,
538
+ recipientAddress : Array . from ( args . recipientAddress ) ,
539
+ shouldQueue : args . shouldQueue ,
540
+ } ;
496
541
return await this . program . methods
497
542
. transferLock ( {
498
543
amount : args . amount ,
@@ -506,15 +551,17 @@ export class NttManagerSolana {
506
551
config : { config : this . configAccountAddress ( ) } ,
507
552
mint,
508
553
from : args . from ,
509
- sender : args . fromAuthority ,
510
554
tokenProgram : await this . tokenProgram ( config ) ,
511
555
outboxItem : args . outboxItem ,
512
556
outboxRateLimit : this . outboxRateLimitAccountAddress ( ) ,
513
- tokenAuthority : this . tokenAuthorityAddress ( ) ,
514
557
} ,
515
558
peer : this . peerAccountAddress ( args . recipientChain ) ,
516
559
inboxRateLimit : this . inboxRateLimitAccountAddress ( args . recipientChain ) ,
517
560
custody : await this . custodyAccountAddress ( config ) ,
561
+ sessionAuthority : this . sessionAuthorityAddress (
562
+ args . fromAuthority ,
563
+ transferArgs ,
564
+ ) ,
518
565
} )
519
566
. instruction ( ) ;
520
567
}
0 commit comments