token_2022.rs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618
  1. use anchor_lang::solana_program::account_info::AccountInfo;
  2. use anchor_lang::solana_program::pubkey::Pubkey;
  3. use anchor_lang::Result;
  4. use anchor_lang::{context::CpiContext, Accounts};
  5. pub use spl_token_2022;
  6. pub use spl_token_2022::ID;
  7. #[deprecated(
  8. since = "0.28.0",
  9. note = "please use `transfer_checked` or `transfer_checked_with_fee` instead"
  10. )]
  11. pub fn transfer<'info>(
  12. ctx: CpiContext<'_, '_, '_, 'info, Transfer<'info>>,
  13. amount: u64,
  14. ) -> Result<()> {
  15. #[allow(deprecated)]
  16. let ix = spl_token_2022::instruction::transfer(
  17. ctx.program.key,
  18. ctx.accounts.from.key,
  19. ctx.accounts.to.key,
  20. ctx.accounts.authority.key,
  21. &[],
  22. amount,
  23. )?;
  24. anchor_lang::solana_program::program::invoke_signed(
  25. &ix,
  26. &[ctx.accounts.from, ctx.accounts.to, ctx.accounts.authority],
  27. ctx.signer_seeds,
  28. )
  29. .map_err(Into::into)
  30. }
  31. pub fn transfer_checked<'info>(
  32. ctx: CpiContext<'_, '_, '_, 'info, TransferChecked<'info>>,
  33. amount: u64,
  34. decimals: u8,
  35. ) -> Result<()> {
  36. let ix = spl_token_2022::instruction::transfer_checked(
  37. ctx.program.key,
  38. ctx.accounts.from.key,
  39. ctx.accounts.mint.key,
  40. ctx.accounts.to.key,
  41. ctx.accounts.authority.key,
  42. &[],
  43. amount,
  44. decimals,
  45. )?;
  46. anchor_lang::solana_program::program::invoke_signed(
  47. &ix,
  48. &[
  49. ctx.accounts.from,
  50. ctx.accounts.mint,
  51. ctx.accounts.to,
  52. ctx.accounts.authority,
  53. ],
  54. ctx.signer_seeds,
  55. )
  56. .map_err(Into::into)
  57. }
  58. pub fn mint_to<'info>(
  59. ctx: CpiContext<'_, '_, '_, 'info, MintTo<'info>>,
  60. amount: u64,
  61. ) -> Result<()> {
  62. let ix = spl_token_2022::instruction::mint_to(
  63. ctx.program.key,
  64. ctx.accounts.mint.key,
  65. ctx.accounts.to.key,
  66. ctx.accounts.authority.key,
  67. &[],
  68. amount,
  69. )?;
  70. anchor_lang::solana_program::program::invoke_signed(
  71. &ix,
  72. &[ctx.accounts.to, ctx.accounts.mint, ctx.accounts.authority],
  73. ctx.signer_seeds,
  74. )
  75. .map_err(Into::into)
  76. }
  77. pub fn mint_to_checked<'info>(
  78. ctx: CpiContext<'_, '_, '_, 'info, MintToChecked<'info>>,
  79. amount: u64,
  80. decimals: u8,
  81. ) -> Result<()> {
  82. let ix = spl_token_2022::instruction::mint_to_checked(
  83. ctx.program.key,
  84. ctx.accounts.mint.key,
  85. ctx.accounts.to.key,
  86. ctx.accounts.authority.key,
  87. &[],
  88. amount,
  89. decimals,
  90. )?;
  91. anchor_lang::solana_program::program::invoke_signed(
  92. &ix,
  93. &[ctx.accounts.to, ctx.accounts.mint, ctx.accounts.authority],
  94. ctx.signer_seeds,
  95. )
  96. .map_err(Into::into)
  97. }
  98. pub fn burn<'info>(ctx: CpiContext<'_, '_, '_, 'info, Burn<'info>>, amount: u64) -> Result<()> {
  99. let ix = spl_token_2022::instruction::burn(
  100. ctx.program.key,
  101. ctx.accounts.from.key,
  102. ctx.accounts.mint.key,
  103. ctx.accounts.authority.key,
  104. &[],
  105. amount,
  106. )?;
  107. anchor_lang::solana_program::program::invoke_signed(
  108. &ix,
  109. &[ctx.accounts.from, ctx.accounts.mint, ctx.accounts.authority],
  110. ctx.signer_seeds,
  111. )
  112. .map_err(Into::into)
  113. }
  114. pub fn burn_checked<'info>(
  115. ctx: CpiContext<'_, '_, '_, 'info, BurnChecked<'info>>,
  116. amount: u64,
  117. decimals: u8,
  118. ) -> Result<()> {
  119. let ix = spl_token_2022::instruction::burn_checked(
  120. ctx.program.key,
  121. ctx.accounts.from.key,
  122. ctx.accounts.mint.key,
  123. ctx.accounts.authority.key,
  124. &[],
  125. amount,
  126. decimals,
  127. )?;
  128. anchor_lang::solana_program::program::invoke_signed(
  129. &ix,
  130. &[ctx.accounts.from, ctx.accounts.mint, ctx.accounts.authority],
  131. ctx.signer_seeds,
  132. )
  133. .map_err(Into::into)
  134. }
  135. pub fn approve<'info>(
  136. ctx: CpiContext<'_, '_, '_, 'info, Approve<'info>>,
  137. amount: u64,
  138. ) -> Result<()> {
  139. let ix = spl_token_2022::instruction::approve(
  140. ctx.program.key,
  141. ctx.accounts.to.key,
  142. ctx.accounts.delegate.key,
  143. ctx.accounts.authority.key,
  144. &[],
  145. amount,
  146. )?;
  147. anchor_lang::solana_program::program::invoke_signed(
  148. &ix,
  149. &[
  150. ctx.accounts.to,
  151. ctx.accounts.delegate,
  152. ctx.accounts.authority,
  153. ],
  154. ctx.signer_seeds,
  155. )
  156. .map_err(Into::into)
  157. }
  158. pub fn approve_checked<'info>(
  159. ctx: CpiContext<'_, '_, '_, 'info, ApproveChecked<'info>>,
  160. amount: u64,
  161. decimals: u8,
  162. ) -> Result<()> {
  163. let ix = spl_token_2022::instruction::approve_checked(
  164. ctx.program.key,
  165. ctx.accounts.to.key,
  166. ctx.accounts.mint.key,
  167. ctx.accounts.delegate.key,
  168. ctx.accounts.authority.key,
  169. &[],
  170. amount,
  171. decimals,
  172. )?;
  173. anchor_lang::solana_program::program::invoke_signed(
  174. &ix,
  175. &[
  176. ctx.accounts.to,
  177. ctx.accounts.mint,
  178. ctx.accounts.delegate,
  179. ctx.accounts.authority,
  180. ],
  181. ctx.signer_seeds,
  182. )
  183. .map_err(Into::into)
  184. }
  185. pub fn revoke<'info>(ctx: CpiContext<'_, '_, '_, 'info, Revoke<'info>>) -> Result<()> {
  186. let ix = spl_token_2022::instruction::revoke(
  187. ctx.program.key,
  188. ctx.accounts.source.key,
  189. ctx.accounts.authority.key,
  190. &[],
  191. )?;
  192. anchor_lang::solana_program::program::invoke_signed(
  193. &ix,
  194. &[ctx.accounts.source, ctx.accounts.authority],
  195. ctx.signer_seeds,
  196. )
  197. .map_err(Into::into)
  198. }
  199. pub fn initialize_account<'info>(
  200. ctx: CpiContext<'_, '_, '_, 'info, InitializeAccount<'info>>,
  201. ) -> Result<()> {
  202. let ix = spl_token_2022::instruction::initialize_account(
  203. ctx.program.key,
  204. ctx.accounts.account.key,
  205. ctx.accounts.mint.key,
  206. ctx.accounts.authority.key,
  207. )?;
  208. anchor_lang::solana_program::program::invoke(
  209. &ix,
  210. &[
  211. ctx.accounts.account,
  212. ctx.accounts.mint,
  213. ctx.accounts.authority,
  214. ctx.accounts.rent,
  215. ],
  216. )
  217. .map_err(Into::into)
  218. }
  219. pub fn initialize_account3<'info>(
  220. ctx: CpiContext<'_, '_, '_, 'info, InitializeAccount3<'info>>,
  221. ) -> Result<()> {
  222. let ix = spl_token_2022::instruction::initialize_account3(
  223. ctx.program.key,
  224. ctx.accounts.account.key,
  225. ctx.accounts.mint.key,
  226. ctx.accounts.authority.key,
  227. )?;
  228. anchor_lang::solana_program::program::invoke(&ix, &[ctx.accounts.account, ctx.accounts.mint])
  229. .map_err(Into::into)
  230. }
  231. pub fn close_account<'info>(ctx: CpiContext<'_, '_, '_, 'info, CloseAccount<'info>>) -> Result<()> {
  232. let ix = spl_token_2022::instruction::close_account(
  233. ctx.program.key,
  234. ctx.accounts.account.key,
  235. ctx.accounts.destination.key,
  236. ctx.accounts.authority.key,
  237. &[], // TODO: support multisig
  238. )?;
  239. anchor_lang::solana_program::program::invoke_signed(
  240. &ix,
  241. &[
  242. ctx.accounts.account,
  243. ctx.accounts.destination,
  244. ctx.accounts.authority,
  245. ],
  246. ctx.signer_seeds,
  247. )
  248. .map_err(Into::into)
  249. }
  250. pub fn freeze_account<'info>(
  251. ctx: CpiContext<'_, '_, '_, 'info, FreezeAccount<'info>>,
  252. ) -> Result<()> {
  253. let ix = spl_token_2022::instruction::freeze_account(
  254. ctx.program.key,
  255. ctx.accounts.account.key,
  256. ctx.accounts.mint.key,
  257. ctx.accounts.authority.key,
  258. &[], // TODO: Support multisig signers.
  259. )?;
  260. anchor_lang::solana_program::program::invoke_signed(
  261. &ix,
  262. &[
  263. ctx.accounts.account,
  264. ctx.accounts.mint,
  265. ctx.accounts.authority,
  266. ],
  267. ctx.signer_seeds,
  268. )
  269. .map_err(Into::into)
  270. }
  271. pub fn thaw_account<'info>(ctx: CpiContext<'_, '_, '_, 'info, ThawAccount<'info>>) -> Result<()> {
  272. let ix = spl_token_2022::instruction::thaw_account(
  273. ctx.program.key,
  274. ctx.accounts.account.key,
  275. ctx.accounts.mint.key,
  276. ctx.accounts.authority.key,
  277. &[], // TODO: Support multisig signers.
  278. )?;
  279. anchor_lang::solana_program::program::invoke_signed(
  280. &ix,
  281. &[
  282. ctx.accounts.account,
  283. ctx.accounts.mint,
  284. ctx.accounts.authority,
  285. ],
  286. ctx.signer_seeds,
  287. )
  288. .map_err(Into::into)
  289. }
  290. pub fn initialize_mint<'info>(
  291. ctx: CpiContext<'_, '_, '_, 'info, InitializeMint<'info>>,
  292. decimals: u8,
  293. authority: &Pubkey,
  294. freeze_authority: Option<&Pubkey>,
  295. ) -> Result<()> {
  296. let ix = spl_token_2022::instruction::initialize_mint(
  297. ctx.program.key,
  298. ctx.accounts.mint.key,
  299. authority,
  300. freeze_authority,
  301. decimals,
  302. )?;
  303. anchor_lang::solana_program::program::invoke(&ix, &[ctx.accounts.mint, ctx.accounts.rent])
  304. .map_err(Into::into)
  305. }
  306. pub fn initialize_mint2<'info>(
  307. ctx: CpiContext<'_, '_, '_, 'info, InitializeMint2<'info>>,
  308. decimals: u8,
  309. authority: &Pubkey,
  310. freeze_authority: Option<&Pubkey>,
  311. ) -> Result<()> {
  312. let ix = spl_token_2022::instruction::initialize_mint2(
  313. ctx.program.key,
  314. ctx.accounts.mint.key,
  315. authority,
  316. freeze_authority,
  317. decimals,
  318. )?;
  319. anchor_lang::solana_program::program::invoke(&ix, &[ctx.accounts.mint]).map_err(Into::into)
  320. }
  321. pub fn set_authority<'info>(
  322. ctx: CpiContext<'_, '_, '_, 'info, SetAuthority<'info>>,
  323. authority_type: spl_token_2022::instruction::AuthorityType,
  324. new_authority: Option<Pubkey>,
  325. ) -> Result<()> {
  326. let mut spl_new_authority: Option<&Pubkey> = None;
  327. if new_authority.is_some() {
  328. spl_new_authority = new_authority.as_ref()
  329. }
  330. let ix = spl_token_2022::instruction::set_authority(
  331. ctx.program.key,
  332. ctx.accounts.account_or_mint.key,
  333. spl_new_authority,
  334. authority_type,
  335. ctx.accounts.current_authority.key,
  336. &[], // TODO: Support multisig signers.
  337. )?;
  338. anchor_lang::solana_program::program::invoke_signed(
  339. &ix,
  340. &[ctx.accounts.account_or_mint, ctx.accounts.current_authority],
  341. ctx.signer_seeds,
  342. )
  343. .map_err(Into::into)
  344. }
  345. pub fn sync_native<'info>(ctx: CpiContext<'_, '_, '_, 'info, SyncNative<'info>>) -> Result<()> {
  346. let ix = spl_token_2022::instruction::sync_native(ctx.program.key, ctx.accounts.account.key)?;
  347. anchor_lang::solana_program::program::invoke(&ix, &[ctx.accounts.account]).map_err(Into::into)
  348. }
  349. pub fn get_account_data_size<'info>(
  350. ctx: CpiContext<'_, '_, '_, 'info, GetAccountDataSize<'info>>,
  351. extension_types: &[spl_token_2022::extension::ExtensionType],
  352. ) -> Result<u64> {
  353. let ix = spl_token_2022::instruction::get_account_data_size(
  354. ctx.program.key,
  355. ctx.accounts.mint.key,
  356. extension_types,
  357. )?;
  358. anchor_lang::solana_program::program::invoke(&ix, &[ctx.accounts.mint])?;
  359. anchor_lang::solana_program::program::get_return_data()
  360. .ok_or(anchor_lang::solana_program::program_error::ProgramError::InvalidInstructionData)
  361. .and_then(|(key, data)| {
  362. if key != *ctx.program.key {
  363. Err(anchor_lang::solana_program::program_error::ProgramError::IncorrectProgramId)
  364. } else {
  365. data.try_into().map(u64::from_le_bytes).map_err(|_| {
  366. anchor_lang::solana_program::program_error::ProgramError::InvalidInstructionData
  367. })
  368. }
  369. })
  370. .map_err(Into::into)
  371. }
  372. pub fn initialize_mint_close_authority<'info>(
  373. ctx: CpiContext<'_, '_, '_, 'info, InitializeMintCloseAuthority<'info>>,
  374. close_authority: Option<&Pubkey>,
  375. ) -> Result<()> {
  376. let ix = spl_token_2022::instruction::initialize_mint_close_authority(
  377. ctx.program.key,
  378. ctx.accounts.mint.key,
  379. close_authority,
  380. )?;
  381. anchor_lang::solana_program::program::invoke(&ix, &[ctx.accounts.mint]).map_err(Into::into)
  382. }
  383. pub fn initialize_immutable_owner<'info>(
  384. ctx: CpiContext<'_, '_, '_, 'info, InitializeImmutableOwner<'info>>,
  385. ) -> Result<()> {
  386. let ix = spl_token_2022::instruction::initialize_immutable_owner(
  387. ctx.program.key,
  388. ctx.accounts.account.key,
  389. )?;
  390. anchor_lang::solana_program::program::invoke(&ix, &[ctx.accounts.account]).map_err(Into::into)
  391. }
  392. pub fn amount_to_ui_amount<'info>(
  393. ctx: CpiContext<'_, '_, '_, 'info, AmountToUiAmount<'info>>,
  394. amount: u64,
  395. ) -> Result<String> {
  396. let ix = spl_token_2022::instruction::amount_to_ui_amount(
  397. ctx.program.key,
  398. ctx.accounts.account.key,
  399. amount,
  400. )?;
  401. anchor_lang::solana_program::program::invoke(&ix, &[ctx.accounts.account])?;
  402. anchor_lang::solana_program::program::get_return_data()
  403. .ok_or(anchor_lang::solana_program::program_error::ProgramError::InvalidInstructionData)
  404. .and_then(|(key, data)| {
  405. if key != *ctx.program.key {
  406. Err(anchor_lang::solana_program::program_error::ProgramError::IncorrectProgramId)
  407. } else {
  408. String::from_utf8(data).map_err(|_| {
  409. anchor_lang::solana_program::program_error::ProgramError::InvalidInstructionData
  410. })
  411. }
  412. })
  413. .map_err(Into::into)
  414. }
  415. pub fn ui_amount_to_amount<'info>(
  416. ctx: CpiContext<'_, '_, '_, 'info, UiAmountToAmount<'info>>,
  417. ui_amount: &str,
  418. ) -> Result<u64> {
  419. let ix = spl_token_2022::instruction::ui_amount_to_amount(
  420. ctx.program.key,
  421. ctx.accounts.account.key,
  422. ui_amount,
  423. )?;
  424. anchor_lang::solana_program::program::invoke(&ix, &[ctx.accounts.account])?;
  425. anchor_lang::solana_program::program::get_return_data()
  426. .ok_or(anchor_lang::solana_program::program_error::ProgramError::InvalidInstructionData)
  427. .and_then(|(key, data)| {
  428. if key != *ctx.program.key {
  429. Err(anchor_lang::solana_program::program_error::ProgramError::IncorrectProgramId)
  430. } else {
  431. data.try_into().map(u64::from_le_bytes).map_err(|_| {
  432. anchor_lang::solana_program::program_error::ProgramError::InvalidInstructionData
  433. })
  434. }
  435. })
  436. .map_err(Into::into)
  437. }
  438. #[derive(Accounts)]
  439. pub struct Transfer<'info> {
  440. pub from: AccountInfo<'info>,
  441. pub to: AccountInfo<'info>,
  442. pub authority: AccountInfo<'info>,
  443. }
  444. #[derive(Accounts)]
  445. pub struct TransferChecked<'info> {
  446. pub from: AccountInfo<'info>,
  447. pub mint: AccountInfo<'info>,
  448. pub to: AccountInfo<'info>,
  449. pub authority: AccountInfo<'info>,
  450. }
  451. #[derive(Accounts)]
  452. pub struct MintTo<'info> {
  453. pub mint: AccountInfo<'info>,
  454. pub to: AccountInfo<'info>,
  455. pub authority: AccountInfo<'info>,
  456. }
  457. #[derive(Accounts)]
  458. pub struct MintToChecked<'info> {
  459. pub mint: AccountInfo<'info>,
  460. pub to: AccountInfo<'info>,
  461. pub authority: AccountInfo<'info>,
  462. }
  463. #[derive(Accounts)]
  464. pub struct Burn<'info> {
  465. pub mint: AccountInfo<'info>,
  466. pub from: AccountInfo<'info>,
  467. pub authority: AccountInfo<'info>,
  468. }
  469. #[derive(Accounts)]
  470. pub struct BurnChecked<'info> {
  471. pub mint: AccountInfo<'info>,
  472. pub from: AccountInfo<'info>,
  473. pub authority: AccountInfo<'info>,
  474. }
  475. #[derive(Accounts)]
  476. pub struct Approve<'info> {
  477. pub to: AccountInfo<'info>,
  478. pub delegate: AccountInfo<'info>,
  479. pub authority: AccountInfo<'info>,
  480. }
  481. #[derive(Accounts)]
  482. pub struct ApproveChecked<'info> {
  483. pub to: AccountInfo<'info>,
  484. pub mint: AccountInfo<'info>,
  485. pub delegate: AccountInfo<'info>,
  486. pub authority: AccountInfo<'info>,
  487. }
  488. #[derive(Accounts)]
  489. pub struct Revoke<'info> {
  490. pub source: AccountInfo<'info>,
  491. pub authority: AccountInfo<'info>,
  492. }
  493. #[derive(Accounts)]
  494. pub struct InitializeAccount<'info> {
  495. pub account: AccountInfo<'info>,
  496. pub mint: AccountInfo<'info>,
  497. pub authority: AccountInfo<'info>,
  498. pub rent: AccountInfo<'info>,
  499. }
  500. #[derive(Accounts)]
  501. pub struct InitializeAccount3<'info> {
  502. pub account: AccountInfo<'info>,
  503. pub mint: AccountInfo<'info>,
  504. pub authority: AccountInfo<'info>,
  505. }
  506. #[derive(Accounts)]
  507. pub struct CloseAccount<'info> {
  508. pub account: AccountInfo<'info>,
  509. pub destination: AccountInfo<'info>,
  510. pub authority: AccountInfo<'info>,
  511. }
  512. #[derive(Accounts)]
  513. pub struct FreezeAccount<'info> {
  514. pub account: AccountInfo<'info>,
  515. pub mint: AccountInfo<'info>,
  516. pub authority: AccountInfo<'info>,
  517. }
  518. #[derive(Accounts)]
  519. pub struct ThawAccount<'info> {
  520. pub account: AccountInfo<'info>,
  521. pub mint: AccountInfo<'info>,
  522. pub authority: AccountInfo<'info>,
  523. }
  524. #[derive(Accounts)]
  525. pub struct InitializeMint<'info> {
  526. pub mint: AccountInfo<'info>,
  527. pub rent: AccountInfo<'info>,
  528. }
  529. #[derive(Accounts)]
  530. pub struct InitializeMint2<'info> {
  531. pub mint: AccountInfo<'info>,
  532. }
  533. #[derive(Accounts)]
  534. pub struct SetAuthority<'info> {
  535. pub current_authority: AccountInfo<'info>,
  536. pub account_or_mint: AccountInfo<'info>,
  537. }
  538. #[derive(Accounts)]
  539. pub struct SyncNative<'info> {
  540. pub account: AccountInfo<'info>,
  541. }
  542. #[derive(Accounts)]
  543. pub struct GetAccountDataSize<'info> {
  544. pub mint: AccountInfo<'info>,
  545. }
  546. #[derive(Accounts)]
  547. pub struct InitializeMintCloseAuthority<'info> {
  548. pub mint: AccountInfo<'info>,
  549. }
  550. #[derive(Accounts)]
  551. pub struct InitializeImmutableOwner<'info> {
  552. pub account: AccountInfo<'info>,
  553. }
  554. #[derive(Accounts)]
  555. pub struct AmountToUiAmount<'info> {
  556. pub account: AccountInfo<'info>,
  557. }
  558. #[derive(Accounts)]
  559. pub struct UiAmountToAmount<'info> {
  560. pub account: AccountInfo<'info>,
  561. }
  562. #[derive(Clone)]
  563. pub struct Token2022;
  564. impl anchor_lang::Id for Token2022 {
  565. fn id() -> Pubkey {
  566. ID
  567. }
  568. }