|
2 | 2 |
|
3 | 3 | use anchor_lang::{prelude::*, solana_program::program::invoke, Discriminator};
|
4 | 4 | use light_compressed_token_sdk::{
|
5 |
| - cpi::{create_compressed_token_instruction, CpiAccounts, CpiInputs}, |
6 |
| - InputTokenDataWithContext, ValidityProof, |
| 5 | + account::CTokenAccount, |
| 6 | + cpi_account_infos::TransferAccountInfos, |
| 7 | + instructions::transfer::instruction::{ |
| 8 | + compress, decompress, transfer, CompressInputs, TransferInputs, |
| 9 | + }, |
| 10 | + TokenAccountMeta, ValidityProof, |
7 | 11 | };
|
8 |
| - |
9 | 12 | declare_id!("5p1t1GAaKtK1FKCh5Hd2Gu8JCu3eREhJm4Q2qYfTEPYK");
|
10 | 13 |
|
11 | 14 | #[program]
|
12 | 15 | pub mod sdk_token_test {
|
13 | 16 |
|
| 17 | + use light_compressed_token_sdk::instructions::transfer::instruction::DecompressInputs; |
| 18 | + |
14 | 19 | use super::*;
|
15 | 20 |
|
16 |
| - pub fn compress<'info>( |
| 21 | + pub fn compress_tokens<'info>( |
17 | 22 | ctx: Context<'_, '_, '_, 'info, Generic<'info>>,
|
18 | 23 | output_tree_index: u8,
|
19 | 24 | recipient: Pubkey, // TODO: make recpient pda
|
20 | 25 | mint: Pubkey, // TODO: deserialize from token account.
|
21 | 26 | amount: u64,
|
22 | 27 | ) -> Result<()> {
|
23 |
| - let mut token_account = light_compressed_token_sdk::account::CTokenAccount::new_empty( |
24 |
| - mint, |
25 |
| - recipient, |
26 |
| - output_tree_index, |
27 |
| - ); |
28 |
| - token_account.compress(amount).unwrap(); |
29 |
| - |
30 |
| - let cpi_inputs = CpiInputs::new_compress(vec![token_account]); |
31 |
| - |
32 |
| - let light_cpi_accounts = CpiAccounts::new_compress( |
| 28 | + let light_cpi_accounts = TransferAccountInfos::new_compress( |
33 | 29 | ctx.accounts.signer.as_ref(),
|
34 | 30 | ctx.accounts.signer.as_ref(),
|
35 | 31 | ctx.remaining_accounts,
|
36 | 32 | );
|
37 | 33 |
|
38 |
| - // TODO: add to program error conversion |
39 |
| - let instruction = |
40 |
| - create_compressed_token_instruction(cpi_inputs, &light_cpi_accounts).unwrap(); |
| 34 | + let compress_inputs = CompressInputs { |
| 35 | + fee_payer: *ctx.accounts.signer.key, |
| 36 | + authority: *ctx.accounts.signer.key, |
| 37 | + mint, |
| 38 | + recipient, |
| 39 | + sender_token_account: *light_cpi_accounts.sender_token_account().unwrap().key, |
| 40 | + amount, |
| 41 | + // can be hardcoded as 0, exposed for flexibility |
| 42 | + // and as marker that a tree has to be provided. |
| 43 | + output_tree_index, |
| 44 | + output_queue_pubkey: *light_cpi_accounts.tree_accounts().unwrap()[0].key, |
| 45 | + token_pool_pda: *light_cpi_accounts.token_pool_pda().unwrap().key, |
| 46 | + transfer_config: None, |
| 47 | + spl_token_program: *light_cpi_accounts.spl_token_program().unwrap().key, |
| 48 | + }; |
| 49 | + |
| 50 | + let instruction = compress(compress_inputs).map_err(ProgramError::from)?; |
| 51 | + msg!("instruction {:?}", instruction); |
41 | 52 | let account_infos = light_cpi_accounts.to_account_infos();
|
42 | 53 |
|
43 | 54 | invoke(&instruction, account_infos.as_slice())?;
|
44 | 55 |
|
45 | 56 | Ok(())
|
46 | 57 | }
|
47 | 58 |
|
48 |
| - pub fn transfer<'info>( |
| 59 | + pub fn transfer_tokens<'info>( |
49 | 60 | ctx: Context<'_, '_, '_, 'info, Generic<'info>>,
|
50 | 61 | validity_proof: ValidityProof,
|
51 |
| - token_data: Vec<InputTokenDataWithContext>, |
| 62 | + token_metas: Vec<TokenAccountMeta>, |
52 | 63 | output_tree_index: u8,
|
53 | 64 | mint: Pubkey,
|
54 | 65 | recipient: Pubkey,
|
55 | 66 | ) -> Result<()> {
|
56 |
| - let mut token_account = light_compressed_token_sdk::account::CTokenAccount::new( |
57 |
| - mint, |
58 |
| - ctx.accounts.signer.key(), // TODO: reconsider whether this makes sense |
59 |
| - token_data, |
60 |
| - output_tree_index, |
61 |
| - ); |
62 |
| - // None is the same output_tree_index as token account |
63 |
| - let recipient_token_account = token_account.transfer(&recipient, 10, None).unwrap(); |
64 |
| - |
65 |
| - let cpi_inputs = |
66 |
| - CpiInputs::new(vec![token_account, recipient_token_account], validity_proof); |
67 |
| - let light_cpi_accounts = CpiAccounts::new( |
| 67 | + let light_cpi_accounts = TransferAccountInfos::new( |
68 | 68 | ctx.accounts.signer.as_ref(),
|
69 | 69 | ctx.accounts.signer.as_ref(),
|
70 | 70 | ctx.remaining_accounts,
|
71 | 71 | );
|
72 |
| - |
73 |
| - // TODO: add to program error conversion |
74 |
| - let instruction = |
75 |
| - create_compressed_token_instruction(cpi_inputs, &light_cpi_accounts).unwrap(); |
| 72 | + let sender_account = CTokenAccount::new( |
| 73 | + mint, |
| 74 | + ctx.accounts.signer.key(), |
| 75 | + token_metas, |
| 76 | + // We pack the accounts offchain. |
| 77 | + output_tree_index, |
| 78 | + ); |
| 79 | + let transfer_inputs = TransferInputs { |
| 80 | + fee_payer: ctx.accounts.signer.key(), |
| 81 | + // This way we can use CTokenAccount as anchor account type |
| 82 | + sender_account, |
| 83 | + validity_proof, |
| 84 | + recipient, |
| 85 | + // This is necessary for on and offchain compatibility. |
| 86 | + // This is not an optimal solution because we collect pubkeys into a vector. |
| 87 | + tree_pubkeys: light_cpi_accounts.tree_pubkeys().unwrap(), |
| 88 | + config: None, |
| 89 | + amount: 10, |
| 90 | + }; |
| 91 | + let instruction = transfer(transfer_inputs).unwrap(); |
76 | 92 |
|
77 | 93 | let account_infos = light_cpi_accounts.to_account_infos();
|
78 | 94 |
|
79 |
| - // TODO: make invoke_signed |
80 | 95 | invoke(&instruction, account_infos.as_slice())?;
|
81 | 96 |
|
82 | 97 | Ok(())
|
83 | 98 | }
|
84 | 99 |
|
85 |
| - pub fn decompress<'info>( |
| 100 | + pub fn decompress_tokens<'info>( |
86 | 101 | ctx: Context<'_, '_, '_, 'info, Generic<'info>>,
|
87 | 102 | validity_proof: ValidityProof,
|
88 |
| - token_data: Vec<InputTokenDataWithContext>, |
| 103 | + token_data: Vec<TokenAccountMeta>, |
89 | 104 | output_tree_index: u8,
|
90 | 105 | mint: Pubkey,
|
91 | 106 | ) -> Result<()> {
|
92 |
| - let mut token_account = light_compressed_token_sdk::account::CTokenAccount::new( |
| 107 | + let sender_account = light_compressed_token_sdk::account::CTokenAccount::new( |
93 | 108 | mint,
|
94 |
| - ctx.accounts.signer.key(), // TODO: reconsider whether this makes sense |
| 109 | + ctx.accounts.signer.key(), |
95 | 110 | token_data,
|
96 | 111 | output_tree_index,
|
97 | 112 | );
|
98 |
| - token_account.decompress(10).unwrap(); |
99 | 113 |
|
100 |
| - let cpi_inputs = CpiInputs::new(vec![token_account], validity_proof); |
101 |
| - let light_cpi_accounts = CpiAccounts::new_decompress( |
| 114 | + let light_cpi_accounts = TransferAccountInfos::new_decompress( |
102 | 115 | ctx.accounts.signer.as_ref(),
|
103 | 116 | ctx.accounts.signer.as_ref(),
|
104 | 117 | ctx.remaining_accounts,
|
105 | 118 | );
|
106 | 119 |
|
107 |
| - // TODO: add to program error conversion |
108 |
| - let instruction = |
109 |
| - create_compressed_token_instruction(cpi_inputs, &light_cpi_accounts).unwrap(); |
| 120 | + let inputs = DecompressInputs { |
| 121 | + fee_payer: *ctx.accounts.signer.key, |
| 122 | + validity_proof, |
| 123 | + sender_account, |
| 124 | + amount: 10, |
| 125 | + tree_pubkeys: light_cpi_accounts.tree_pubkeys().unwrap(), |
| 126 | + token_pool_pda: *light_cpi_accounts.token_pool_pda().unwrap().key, |
| 127 | + recipient_token_account: *light_cpi_accounts.decompression_recipient().unwrap().key, |
| 128 | + // TODO: consider replacing with token program id |
| 129 | + spl_token_program: *light_cpi_accounts.spl_token_program().unwrap().key, |
| 130 | + config: None, |
| 131 | + }; |
| 132 | + |
| 133 | + let instruction = decompress(inputs).unwrap(); |
110 | 134 | let account_infos = light_cpi_accounts.to_account_infos();
|
111 | 135 |
|
112 |
| - // TODO: make invoke_signed |
113 | 136 | invoke(&instruction, account_infos.as_slice())?;
|
114 | 137 |
|
115 | 138 | Ok(())
|
|
0 commit comments