@@ -731,6 +731,24 @@ pub enum TokenInstruction<'a> {
731731 ScaledUiAmountExtension ,
732732 /// Instruction prefix for instructions to the pausable extension
733733 PausableExtension ,
734+ /// 45
735+ /// Transfer lamports from a native SOL account to a destination account.
736+ ///
737+ /// This is useful to unwrap lamports from a wrapped SOL account.
738+ ///
739+ /// Accounts expected by this instruction:
740+ ///
741+ /// 0. `[writable]` The source account.
742+ /// 1. `[writable]` The destination account.
743+ /// 2. `[signer]` The source account's owner/delegate.
744+ ///
745+ UnwrapLamports {
746+ /// The amount of lamports to transfer. When an amount is
747+ /// not specified, the entire balance of the source account will be
748+ /// transferred.
749+ #[ cfg_attr( feature = "serde" , serde( with = "coption_fromstr" ) ) ]
750+ amount : COption < u64 > ,
751+ } ,
734752}
735753impl < ' a > TokenInstruction < ' a > {
736754 /// Unpacks a byte buffer into a
@@ -873,6 +891,10 @@ impl<'a> TokenInstruction<'a> {
873891 42 => Self :: ConfidentialMintBurnExtension ,
874892 43 => Self :: ScaledUiAmountExtension ,
875893 44 => Self :: PausableExtension ,
894+ 45 => {
895+ let ( amount, _rest) = Self :: unpack_u64_option ( rest) ?;
896+ Self :: UnwrapLamports { amount }
897+ }
876898 _ => return Err ( TokenError :: InvalidInstruction . into ( ) ) ,
877899 } )
878900 }
@@ -1053,6 +1075,10 @@ impl<'a> TokenInstruction<'a> {
10531075 & Self :: PausableExtension => {
10541076 buf. push ( 44 ) ;
10551077 }
1078+ & Self :: UnwrapLamports { amount } => {
1079+ buf. push ( 45 ) ;
1080+ Self :: pack_u64_option ( & amount, & mut buf) ;
1081+ }
10561082 } ;
10571083 buf
10581084 }
@@ -2084,6 +2110,37 @@ pub fn withdraw_excess_lamports(
20842110 } )
20852111}
20862112
2113+ /// Creates an `UnwrapLamports` instruction
2114+ pub fn unwrap_lamports (
2115+ token_program_id : & Pubkey ,
2116+ source_pubkey : & Pubkey ,
2117+ destination_pubkey : & Pubkey ,
2118+ authority_pubkey : & Pubkey ,
2119+ signer_pubkeys : & [ & Pubkey ] ,
2120+ amount : Option < u64 > ,
2121+ ) -> Result < Instruction , ProgramError > {
2122+ check_program_account ( token_program_id) ?;
2123+ let amount = amount. into ( ) ;
2124+ let data = TokenInstruction :: UnwrapLamports { amount } . pack ( ) ;
2125+
2126+ let mut accounts = Vec :: with_capacity ( 3 + signer_pubkeys. len ( ) ) ;
2127+ accounts. push ( AccountMeta :: new ( * source_pubkey, false ) ) ;
2128+ accounts. push ( AccountMeta :: new ( * destination_pubkey, false ) ) ;
2129+ accounts. push ( AccountMeta :: new_readonly (
2130+ * authority_pubkey,
2131+ signer_pubkeys. is_empty ( ) ,
2132+ ) ) ;
2133+ for signer_pubkey in signer_pubkeys. iter ( ) {
2134+ accounts. push ( AccountMeta :: new_readonly ( * * signer_pubkey, true ) ) ;
2135+ }
2136+
2137+ Ok ( Instruction {
2138+ program_id : * token_program_id,
2139+ accounts,
2140+ data,
2141+ } )
2142+ }
2143+
20872144#[ cfg( test) ]
20882145mod test {
20892146 use { super :: * , proptest:: prelude:: * } ;
@@ -2458,6 +2515,25 @@ mod test {
24582515 assert_eq ! ( unpacked, check) ;
24592516 }
24602517
2518+ #[ test]
2519+ fn test_unwrap_lamports_packing ( ) {
2520+ let amount = COption :: None ;
2521+ let check = TokenInstruction :: UnwrapLamports { amount } ;
2522+ let packed = check. pack ( ) ;
2523+ let expect = Vec :: from ( [ 45u8 , 0 ] ) ;
2524+ assert_eq ! ( packed, expect) ;
2525+ let unpacked = TokenInstruction :: unpack ( & expect) . unwrap ( ) ;
2526+ assert_eq ! ( unpacked, check) ;
2527+
2528+ let amount = COption :: Some ( 1 ) ;
2529+ let check = TokenInstruction :: UnwrapLamports { amount } ;
2530+ let packed = check. pack ( ) ;
2531+ let expect = Vec :: from ( [ 45u8 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] ) ;
2532+ assert_eq ! ( packed, expect) ;
2533+ let unpacked = TokenInstruction :: unpack ( & expect) . unwrap ( ) ;
2534+ assert_eq ! ( unpacked, check) ;
2535+ }
2536+
24612537 macro_rules! test_instruction {
24622538 ( $a: ident( $( $b: tt) * ) ) => {
24632539 let instruction_v3 = spl_token_interface:: instruction:: $a( $( $b) * ) . unwrap( ) ;
0 commit comments